@devvit/shared-types 0.12.0-next-2025-04-30-2e2a14dbe.0 → 0.12.0-next-2025-08-12-20-19-11-8d352335b.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AdsMetadata.d.ts +6 -0
- package/AdsMetadata.d.ts.map +1 -0
- package/AdsMetadata.js +5 -0
- package/Assets.d.ts +0 -2
- package/Assets.d.ts.map +1 -1
- package/Assets.js +0 -2
- package/CircuitBreaker.d.ts.map +1 -1
- package/Config.d.ts +3 -3
- package/Config.d.ts.map +1 -1
- package/ConfigImpl.d.ts +8 -8
- package/ConfigImpl.d.ts.map +1 -1
- package/ConfigImpl.js +22 -31
- package/Header.d.ts +1 -0
- package/Header.d.ts.map +1 -1
- package/Header.js +1 -0
- package/PostData.d.ts +8 -0
- package/PostData.d.ts.map +1 -0
- package/ProjectTemplateInfo.d.ts +21 -0
- package/ProjectTemplateInfo.d.ts.map +1 -0
- package/ProjectTemplateInfo.js +10 -0
- package/client/emit-effect.d.ts +24 -0
- package/client/emit-effect.d.ts.map +1 -0
- package/client/emit-effect.js +56 -0
- package/client/emit-effect.test.d.ts.map +1 -0
- package/client/share.d.ts +3 -0
- package/client/share.d.ts.map +1 -0
- package/client/share.js +2 -0
- package/constants.d.ts +9 -0
- package/constants.d.ts.map +1 -1
- package/constants.js +9 -0
- package/fetch-domains.d.ts +14 -0
- package/fetch-domains.d.ts.map +1 -0
- package/fetch-domains.js +42 -0
- package/fetch-domains.test.d.ts.map +1 -0
- package/isDevvitDependency.js +1 -1
- package/json.d.ts +12 -12
- package/package.json +18 -13
- package/richtext/index.d.ts +6 -0
- package/richtext/index.d.ts.map +1 -0
- package/richtext/index.js +1 -0
- package/schemas/config-file.v1.d.ts +272 -0
- package/schemas/config-file.v1.d.ts.map +1 -0
- package/schemas/config-file.v1.js +254 -0
- package/schemas/config-file.v1.json +683 -0
- package/schemas/config-file.v1.test.d.ts.map +1 -0
- package/schemas/constants.d.ts +4 -0
- package/schemas/constants.d.ts.map +1 -0
- package/schemas/constants.js +3 -0
- package/{payments/products.schema.json → schemas/products.json} +1 -1
- package/{payments/productSchemaJSONValidator.d.ts → schemas/productsSchemaJSONValidator.d.ts} +2 -2
- package/schemas/productsSchemaJSONValidator.d.ts.map +1 -0
- package/{payments/productSchemaJSONValidator.js → schemas/productsSchemaJSONValidator.js} +1 -1
- package/schemas/productsSchemaJSONValidator.test.d.ts.map +1 -0
- package/server/get-devvit-config.d.ts +7 -0
- package/server/get-devvit-config.d.ts.map +1 -0
- package/server/get-devvit-config.js +10 -0
- package/shared/devvit-worker-global.d.ts +47 -0
- package/shared/devvit-worker-global.d.ts.map +1 -0
- package/shared/devvit-worker-global.js +7 -0
- package/{forms/types.d.ts → shared/form.d.ts} +16 -72
- package/shared/form.d.ts.map +1 -0
- package/tid.d.ts +26 -32
- package/tid.d.ts.map +1 -1
- package/tid.js +43 -62
- package/web-view-scripts-constants.d.ts +14 -0
- package/web-view-scripts-constants.d.ts.map +1 -0
- package/web-view-scripts-constants.js +13 -0
- package/forms/assertValidFormFields.d.ts +0 -11
- package/forms/assertValidFormFields.d.ts.map +0 -1
- package/forms/assertValidFormFields.js +0 -29
- package/forms/assertValidFormFields.test.d.ts.map +0 -1
- package/forms/getFormValues.d.ts +0 -6
- package/forms/getFormValues.d.ts.map +0 -1
- package/forms/getFormValues.js +0 -31
- package/forms/getFormValues.test.d.ts.map +0 -1
- package/forms/transformForm.d.ts +0 -4
- package/forms/transformForm.d.ts.map +0 -1
- package/forms/transformForm.js +0 -141
- package/forms/transformForm.test.d.ts.map +0 -1
- package/forms/types.d.ts.map +0 -1
- package/index.d.ts +0 -2
- package/index.d.ts.map +0 -1
- package/payments/index.d.ts +0 -4
- package/payments/index.d.ts.map +0 -1
- package/payments/index.js +0 -3
- package/payments/productSchemaJSONValidator.d.ts.map +0 -1
- package/payments/productSchemaJSONValidator.test.d.ts.map +0 -1
- /package/{index.js → PostData.js} +0 -0
- /package/{forms/types.js → shared/form.js} +0 -0
package/package.json
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devvit/shared-types",
|
|
3
|
-
"version": "0.12.0-next-2025-
|
|
3
|
+
"version": "0.12.0-next-2025-08-12-20-19-11-8d352335b.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://developers.reddit.com/"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
-
"
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./index.js",
|
|
12
|
+
"./package.json": "./package.json",
|
|
13
|
+
"./*": "./*"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"files": [
|
|
17
|
+
"**"
|
|
18
|
+
],
|
|
11
19
|
"scripts": {
|
|
12
|
-
"build": "tsc && yarn postbuild:copy-
|
|
20
|
+
"build": "tsc && yarn postbuild:copy-schemas",
|
|
13
21
|
"clean": "rm -rf .turbo coverage dist",
|
|
14
22
|
"clobber": "yarn clean && rm -rf node_modules",
|
|
15
23
|
"dev": "tsc -w",
|
|
16
24
|
"dev:build": "chokidar ./src --command 'yarn build && echo \"BUILD COMPLETE\"'",
|
|
17
25
|
"lint": "redlint .",
|
|
18
26
|
"lint:fix": "yarn lint --fix",
|
|
19
|
-
"postbuild:copy-
|
|
27
|
+
"postbuild:copy-schemas": "cp -af src/schemas/*.json dist/schemas/",
|
|
20
28
|
"prepublishOnly": "publish-package-json",
|
|
21
29
|
"test": "yarn test:unit && yarn test:types",
|
|
22
30
|
"test:types": "tsc --noEmit",
|
|
23
31
|
"test:unit": "vitest run",
|
|
24
32
|
"test:unit-with-coverage": "vitest run --coverage"
|
|
25
33
|
},
|
|
26
|
-
"types": "./index.d.ts",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
27
35
|
"dependencies": {
|
|
28
|
-
"@devvit/protos": "0.12.0-next-2025-
|
|
36
|
+
"@devvit/protos": "0.12.0-next-2025-08-12-20-19-11-8d352335b.0",
|
|
29
37
|
"jsonschema": "1.4.1",
|
|
30
38
|
"uuid": "9.0.0"
|
|
31
39
|
},
|
|
32
40
|
"devDependencies": {
|
|
33
|
-
"@devvit/repo-tools": "0.12.0-next-2025-
|
|
34
|
-
"@devvit/tsconfig": "0.12.0-next-2025-
|
|
41
|
+
"@devvit/repo-tools": "0.12.0-next-2025-08-12-20-19-11-8d352335b.0",
|
|
42
|
+
"@devvit/tsconfig": "0.12.0-next-2025-08-12-20-19-11-8d352335b.0",
|
|
35
43
|
"@types/redis-mock": "0.17.1",
|
|
36
44
|
"@types/uuid": "9.0.0",
|
|
37
45
|
"chokidar-cli": "3.0.0",
|
|
@@ -39,12 +47,9 @@
|
|
|
39
47
|
"lit": "2.5.0",
|
|
40
48
|
"redis": "4.6.6",
|
|
41
49
|
"redis-mock": "0.56.3",
|
|
42
|
-
"typescript": "5.3
|
|
50
|
+
"typescript": "5.8.3",
|
|
43
51
|
"vitest": "1.6.1"
|
|
44
52
|
},
|
|
45
|
-
"publishConfig": {
|
|
46
|
-
"directory": "dist"
|
|
47
|
-
},
|
|
48
53
|
"source": "./src/index.ts",
|
|
49
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "7d371722329289fb5dc280a264636ef8c8ea1863"
|
|
50
55
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/richtext/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,iBAAiB,CAAC;AACrC,mBAAmB,eAAe,CAAC;AAEnC,mBAAmB,cAAc,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,mBAAmB,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './RichTextBuilder.js';
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warning: this file is not isomorphic. Do not functionally import this file
|
|
3
|
+
* from client code.
|
|
4
|
+
*/
|
|
5
|
+
import { Scope } from '@devvit/protos';
|
|
6
|
+
import type { JsonObject, JsonValue } from '../json.js';
|
|
7
|
+
/**
|
|
8
|
+
* devvit.json with defaults. See config-file.v1.json schema. Schema is assumed
|
|
9
|
+
* to be v1.
|
|
10
|
+
*/
|
|
11
|
+
export type AppConfig = {
|
|
12
|
+
schema: 'v1';
|
|
13
|
+
name: string;
|
|
14
|
+
media?: {
|
|
15
|
+
dir: string;
|
|
16
|
+
};
|
|
17
|
+
permissions: AppPermissionConfig;
|
|
18
|
+
post?: AppPostConfig;
|
|
19
|
+
server?: AppServerConfig;
|
|
20
|
+
triggers?: AppTriggersConfig;
|
|
21
|
+
blocks?: AppBlocksConfig;
|
|
22
|
+
dev?: AppDevConfig;
|
|
23
|
+
menu?: AppMenuConfig;
|
|
24
|
+
scheduler?: AppSchedulerConfig;
|
|
25
|
+
settings?: AppSettingsConfig;
|
|
26
|
+
forms?: AppFormsConfig;
|
|
27
|
+
marketingAssets?: AppMarketingAssetsConfig;
|
|
28
|
+
/** The original config as parsed. Used for writebacks. */
|
|
29
|
+
json: AppConfigJson;
|
|
30
|
+
};
|
|
31
|
+
export type AppBlocksConfig = {
|
|
32
|
+
entry: string;
|
|
33
|
+
};
|
|
34
|
+
/** Describes plugin usage. */
|
|
35
|
+
export type AppPermissionConfig = {
|
|
36
|
+
http: {
|
|
37
|
+
enable: boolean;
|
|
38
|
+
domains: string[];
|
|
39
|
+
};
|
|
40
|
+
media: boolean;
|
|
41
|
+
menu: boolean;
|
|
42
|
+
payments: boolean;
|
|
43
|
+
realtime: boolean;
|
|
44
|
+
redis: boolean;
|
|
45
|
+
reddit: {
|
|
46
|
+
enable: boolean;
|
|
47
|
+
scope: AppScopeConfig;
|
|
48
|
+
asUser: Scope[];
|
|
49
|
+
};
|
|
50
|
+
settings: boolean;
|
|
51
|
+
triggers: boolean;
|
|
52
|
+
};
|
|
53
|
+
export type AppPostConfig = {
|
|
54
|
+
dir: string;
|
|
55
|
+
entrypoints: AppPostEntrypointsConfig;
|
|
56
|
+
};
|
|
57
|
+
export type AppPostEntrypointsConfig = {
|
|
58
|
+
[name: string]: AppPostEntrypointConfig;
|
|
59
|
+
default: AppPostEntrypointConfig;
|
|
60
|
+
};
|
|
61
|
+
export type AppPostEntrypointConfig = {
|
|
62
|
+
entry: string;
|
|
63
|
+
name: string;
|
|
64
|
+
height: AppPostHeightConfig;
|
|
65
|
+
};
|
|
66
|
+
export type AppPostHeightConfig = 'regular' | 'tall';
|
|
67
|
+
export type AppScopeConfig = 'user' | 'moderator';
|
|
68
|
+
export type AppServerConfig = {
|
|
69
|
+
dir: string;
|
|
70
|
+
entry: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Keys are assumed to have the format of `on${keyof TriggerEventType}` in
|
|
74
|
+
* blocks.template.tsx.
|
|
75
|
+
*/
|
|
76
|
+
export type AppTriggersConfig = {
|
|
77
|
+
onAppInstall?: string;
|
|
78
|
+
onAppUpgrade?: string;
|
|
79
|
+
onAutomoderatorFilterComment?: string;
|
|
80
|
+
onAutomoderatorFilterPost?: string;
|
|
81
|
+
onCommentCreate?: string;
|
|
82
|
+
onCommentDelete?: string;
|
|
83
|
+
onCommentReport?: string;
|
|
84
|
+
onCommentSubmit?: string;
|
|
85
|
+
onCommentUpdate?: string;
|
|
86
|
+
onModAction?: string;
|
|
87
|
+
onModMail?: string;
|
|
88
|
+
onPostCreate?: string;
|
|
89
|
+
onPostDelete?: string;
|
|
90
|
+
onPostFlairUpdate?: string;
|
|
91
|
+
onPostNsfwUpdate?: string;
|
|
92
|
+
onPostReport?: string;
|
|
93
|
+
onPostSpoilerUpdate?: string;
|
|
94
|
+
onPostSubmit?: string;
|
|
95
|
+
onPostUpdate?: string;
|
|
96
|
+
};
|
|
97
|
+
export type AppMenuUserTypeConfig = 'moderator' | 'user';
|
|
98
|
+
export type AppMenuLocationConfig = 'comment' | 'post' | 'subreddit';
|
|
99
|
+
export type AppMenuPostFilterConfig = 'currentApp' | 'none';
|
|
100
|
+
export type AppMenuItemConfig = {
|
|
101
|
+
label: string;
|
|
102
|
+
description: string;
|
|
103
|
+
forUserType: AppMenuUserTypeConfig;
|
|
104
|
+
location: AppMenuLocationConfig[];
|
|
105
|
+
endpoint: string;
|
|
106
|
+
postFilter: AppMenuPostFilterConfig;
|
|
107
|
+
};
|
|
108
|
+
export type AppMenuConfig = {
|
|
109
|
+
items: AppMenuItemConfig[];
|
|
110
|
+
};
|
|
111
|
+
export type AppFormsConfig = {
|
|
112
|
+
[formName: string]: string;
|
|
113
|
+
};
|
|
114
|
+
export type AppMarketingAssetsConfig = {
|
|
115
|
+
icon?: string;
|
|
116
|
+
};
|
|
117
|
+
export type AppDevConfig = {
|
|
118
|
+
subreddit?: string;
|
|
119
|
+
};
|
|
120
|
+
export type AppSchedulerConfig = {
|
|
121
|
+
tasks: {
|
|
122
|
+
[name: string]: AppSchedulerTaskConfig;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
export type AppSchedulerTaskConfig = {
|
|
126
|
+
endpoint: string;
|
|
127
|
+
cron?: string;
|
|
128
|
+
data?: JsonObject;
|
|
129
|
+
};
|
|
130
|
+
export type AppSettingsConfig = {
|
|
131
|
+
global?: {
|
|
132
|
+
[name: string]: AppSettingConfig;
|
|
133
|
+
};
|
|
134
|
+
subreddit?: {
|
|
135
|
+
[name: string]: AppSettingConfig;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
export type AppSettingConfig = AppStringSettingConfig | AppParagraphSettingConfig | AppNumberSettingConfig | AppBooleanSettingConfig | AppSelectSettingConfig | AppMultiSelectSettingConfig;
|
|
139
|
+
export type AppBaseSettingConfig = {
|
|
140
|
+
name: string;
|
|
141
|
+
label: string;
|
|
142
|
+
helpText?: string;
|
|
143
|
+
validationEndpoint?: string;
|
|
144
|
+
};
|
|
145
|
+
export type AppStringSettingConfig = AppBaseSettingConfig & {
|
|
146
|
+
type: 'string';
|
|
147
|
+
placeholder?: string;
|
|
148
|
+
defaultValue?: string;
|
|
149
|
+
isSecret?: boolean;
|
|
150
|
+
};
|
|
151
|
+
export type AppParagraphSettingConfig = AppBaseSettingConfig & {
|
|
152
|
+
type: 'paragraph';
|
|
153
|
+
placeholder?: string;
|
|
154
|
+
defaultValue?: string;
|
|
155
|
+
};
|
|
156
|
+
export type AppNumberSettingConfig = AppBaseSettingConfig & {
|
|
157
|
+
type: 'number';
|
|
158
|
+
defaultValue?: number;
|
|
159
|
+
};
|
|
160
|
+
export type AppBooleanSettingConfig = AppBaseSettingConfig & {
|
|
161
|
+
type: 'boolean';
|
|
162
|
+
defaultValue?: boolean;
|
|
163
|
+
};
|
|
164
|
+
export type AppSelectSettingConfig = AppBaseSettingConfig & {
|
|
165
|
+
type: 'select';
|
|
166
|
+
options: Array<{
|
|
167
|
+
label: string;
|
|
168
|
+
value: string;
|
|
169
|
+
}>;
|
|
170
|
+
defaultValue?: string;
|
|
171
|
+
};
|
|
172
|
+
export type AppMultiSelectSettingConfig = AppBaseSettingConfig & {
|
|
173
|
+
type: 'multiSelect';
|
|
174
|
+
options: Array<{
|
|
175
|
+
label: string;
|
|
176
|
+
value: string;
|
|
177
|
+
}>;
|
|
178
|
+
defaultValue?: string[];
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* https://transform.tools/json-schema-to-typescript
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
184
|
+
export type AppConfigJson = {
|
|
185
|
+
$schema?: string;
|
|
186
|
+
name: string;
|
|
187
|
+
media?: {
|
|
188
|
+
dir?: string;
|
|
189
|
+
};
|
|
190
|
+
permissions?: {
|
|
191
|
+
http?: {
|
|
192
|
+
enable?: boolean;
|
|
193
|
+
domains?: string[];
|
|
194
|
+
};
|
|
195
|
+
media?: boolean;
|
|
196
|
+
payments?: boolean;
|
|
197
|
+
realtime?: boolean;
|
|
198
|
+
redis?: boolean;
|
|
199
|
+
reddit?: {
|
|
200
|
+
enable?: boolean;
|
|
201
|
+
scope?: AppScopeConfig;
|
|
202
|
+
asUser?: string[];
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
post?: {
|
|
206
|
+
dir?: string;
|
|
207
|
+
entrypoints?: {
|
|
208
|
+
[name: string]: AppPostEntrypointConfigJson;
|
|
209
|
+
} & {
|
|
210
|
+
default: Partial<AppPostEntrypointConfigJson>;
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
server?: {
|
|
214
|
+
dir?: string;
|
|
215
|
+
entry?: string;
|
|
216
|
+
};
|
|
217
|
+
triggers?: AppTriggersConfig;
|
|
218
|
+
blocks?: {
|
|
219
|
+
entry?: string;
|
|
220
|
+
menu?: {
|
|
221
|
+
enable?: boolean;
|
|
222
|
+
};
|
|
223
|
+
settings?: {
|
|
224
|
+
enable?: boolean;
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
menu?: {
|
|
228
|
+
items?: {
|
|
229
|
+
label: string;
|
|
230
|
+
description?: string;
|
|
231
|
+
forUserType: AppMenuUserTypeConfig;
|
|
232
|
+
location: AppMenuLocationConfig | AppMenuLocationConfig[];
|
|
233
|
+
endpoint: string;
|
|
234
|
+
postFilter: AppMenuPostFilterConfig;
|
|
235
|
+
}[];
|
|
236
|
+
};
|
|
237
|
+
forms?: {
|
|
238
|
+
[formName: string]: string;
|
|
239
|
+
};
|
|
240
|
+
dev?: {
|
|
241
|
+
subreddit?: string;
|
|
242
|
+
};
|
|
243
|
+
scheduler?: AppSchedulerConfigJson;
|
|
244
|
+
settings?: {
|
|
245
|
+
global?: {
|
|
246
|
+
[name: string]: AppSettingConfigJson;
|
|
247
|
+
};
|
|
248
|
+
subreddit?: {
|
|
249
|
+
[name: string]: AppSettingConfigJson;
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
marketingAssets?: {
|
|
253
|
+
icon?: string;
|
|
254
|
+
};
|
|
255
|
+
/** User data. */
|
|
256
|
+
[key: string]: JsonValue;
|
|
257
|
+
};
|
|
258
|
+
export type AppPostEntrypointConfigJson = {
|
|
259
|
+
entry: string;
|
|
260
|
+
height?: AppPostHeightConfig;
|
|
261
|
+
};
|
|
262
|
+
export type AppSchedulerConfigJson = {
|
|
263
|
+
tasks: {
|
|
264
|
+
[name: string]: AppSchedulerTaskConfig | string;
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
export type AppSettingConfigJson = Omit<AppStringSettingConfig, 'name'> | Omit<AppParagraphSettingConfig, 'name'> | Omit<AppNumberSettingConfig, 'name'> | Omit<AppBooleanSettingConfig, 'name'> | Omit<AppSelectSettingConfig, 'name'> | Omit<AppMultiSelectSettingConfig, 'name'>;
|
|
268
|
+
export declare function parseAppConfig(str: string, allowUninitializedConfig: boolean): AppConfig;
|
|
269
|
+
export declare function parseAppConfigJson(json: JsonValue, allowUninitializedConfig: boolean): AppConfig;
|
|
270
|
+
/** @internal */
|
|
271
|
+
export declare function validate(config: Readonly<AppConfig>): void;
|
|
272
|
+
//# sourceMappingURL=config-file.v1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.v1.d.ts","sourceRoot":"","sources":["../../src/schemas/config-file.v1.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warning: this file is not isomorphic. Do not functionally import this file
|
|
3
|
+
* from client code.
|
|
4
|
+
*/
|
|
5
|
+
import { Scope, scopeFromJSON } from '@devvit/protos';
|
|
6
|
+
import jsonschema from 'jsonschema/lib/index.js';
|
|
7
|
+
import schema from './config-file.v1.json' with { type: 'json' };
|
|
8
|
+
import { defaultPostEntry, UNINITIALIZED_APP_NAME } from './constants.js';
|
|
9
|
+
export function parseAppConfig(str, allowUninitializedConfig) {
|
|
10
|
+
if (!str)
|
|
11
|
+
throw Error('config is empty');
|
|
12
|
+
let json;
|
|
13
|
+
try {
|
|
14
|
+
json = JSON.parse(str);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
throw Error(`cannot parse config JSON`, { cause: err });
|
|
18
|
+
}
|
|
19
|
+
return parseAppConfigJson(json, allowUninitializedConfig);
|
|
20
|
+
}
|
|
21
|
+
export function parseAppConfigJson(json, allowUninitializedConfig) {
|
|
22
|
+
const unitializedSchema = {
|
|
23
|
+
...schema,
|
|
24
|
+
properties: {
|
|
25
|
+
...schema.properties,
|
|
26
|
+
name: {
|
|
27
|
+
...schema.properties.name,
|
|
28
|
+
pattern: `${schema.properties.name.pattern}|^${UNINITIALIZED_APP_NAME}$`,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const ret = jsonschema.validate(json, allowUninitializedConfig ? unitializedSchema : schema);
|
|
33
|
+
if (!ret.valid)
|
|
34
|
+
throw new Error(ret.errors
|
|
35
|
+
.map((err) => {
|
|
36
|
+
if (!err.path.length && err.name === 'anyOf' && /\[subschema \d\]/.test(err.stack))
|
|
37
|
+
return 'config requires property "post", "server", or "blocks".';
|
|
38
|
+
if (err.stack.includes('name does not match pattern'))
|
|
39
|
+
return err.stack
|
|
40
|
+
.replaceAll('instance.', '')
|
|
41
|
+
.concat('. Try running `npm create devvit` to fix your app name.');
|
|
42
|
+
return err.stack.replaceAll('instance.', '').replaceAll('instance', 'config');
|
|
43
|
+
})
|
|
44
|
+
.join('; '));
|
|
45
|
+
const instance = ret.instance;
|
|
46
|
+
if (instance.$schema != null && instance.$schema !== schema.$id)
|
|
47
|
+
console.warn(`Unknown schema "${instance.$schema}".`);
|
|
48
|
+
return AppConfig(instance);
|
|
49
|
+
}
|
|
50
|
+
// jsonschema only supports rewrite hooks but it's easier to update defaults
|
|
51
|
+
// after validation when the entire config is known. Eg,
|
|
52
|
+
// `config.permissions.http` has a different default if `config.server` is set.
|
|
53
|
+
//
|
|
54
|
+
// Ajv supports some default application but it seems like some features are
|
|
55
|
+
// still missing (https://github.com/ajv-validator/ajv/issues/1158). Even if the
|
|
56
|
+
// feature is added, we need the defaults in the properties for documentation
|
|
57
|
+
// and the same dynamic default adjustments as above are required.
|
|
58
|
+
function AppConfig(json) {
|
|
59
|
+
const partial = {
|
|
60
|
+
schema: 'v1', // Always assume v1 since that's all that's supported.
|
|
61
|
+
name: json.name,
|
|
62
|
+
json,
|
|
63
|
+
};
|
|
64
|
+
if (json.media)
|
|
65
|
+
partial.media = {
|
|
66
|
+
dir: json.media.dir ?? schema.properties.media.properties.dir.default,
|
|
67
|
+
};
|
|
68
|
+
if (json.post)
|
|
69
|
+
partial.post = AppPostConfig(json);
|
|
70
|
+
if (json.server)
|
|
71
|
+
partial.server = {
|
|
72
|
+
dir: json.server.dir ?? schema.properties.server.properties.dir.default,
|
|
73
|
+
entry: json.server.entry ?? schema.properties.server.properties.entry.default,
|
|
74
|
+
};
|
|
75
|
+
if (json.triggers && Object.keys(json.triggers).length)
|
|
76
|
+
partial.triggers = json.triggers;
|
|
77
|
+
if (json.blocks)
|
|
78
|
+
partial.blocks = AppBlocksConfig(json);
|
|
79
|
+
if (json.menu)
|
|
80
|
+
partial.menu = AppMenuConfig(json);
|
|
81
|
+
if (json.scheduler)
|
|
82
|
+
partial.scheduler = AppSchedulerConfig(json);
|
|
83
|
+
if (json.settings)
|
|
84
|
+
partial.settings = AppSettingsConfig(json);
|
|
85
|
+
if (json.forms)
|
|
86
|
+
partial.forms = json.forms;
|
|
87
|
+
if (json.marketingAssets)
|
|
88
|
+
partial.marketingAssets = json.marketingAssets;
|
|
89
|
+
if (json.dev) {
|
|
90
|
+
partial.dev = {};
|
|
91
|
+
if (json.dev.subreddit)
|
|
92
|
+
partial.dev.subreddit = json.dev.subreddit;
|
|
93
|
+
}
|
|
94
|
+
const config = { ...partial, permissions: AppPermissionConfig(json, partial) };
|
|
95
|
+
validate(config);
|
|
96
|
+
// Deep copy so schema is not mutated.
|
|
97
|
+
return structuredClone(config);
|
|
98
|
+
}
|
|
99
|
+
function AppSchedulerConfig(json) {
|
|
100
|
+
const appSchedulerConfig = { tasks: {} };
|
|
101
|
+
if (json.scheduler?.tasks) {
|
|
102
|
+
for (const [name, taskSpec] of Object.entries(json.scheduler.tasks)) {
|
|
103
|
+
if (typeof taskSpec === 'string') {
|
|
104
|
+
// If the task is a string, it is an endpoint.
|
|
105
|
+
appSchedulerConfig.tasks[name] = {
|
|
106
|
+
endpoint: taskSpec,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Otherwise, it is an object with an endpoint and optionally a cron.
|
|
111
|
+
appSchedulerConfig.tasks[name] = {
|
|
112
|
+
endpoint: taskSpec.endpoint,
|
|
113
|
+
...(taskSpec.cron
|
|
114
|
+
? { cron: taskSpec.cron, ...(taskSpec.data ? { data: taskSpec.data } : {}) }
|
|
115
|
+
: {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return appSchedulerConfig;
|
|
121
|
+
}
|
|
122
|
+
function AppPermissionConfig(json, partial) {
|
|
123
|
+
return {
|
|
124
|
+
http: {
|
|
125
|
+
enable: json.permissions?.http?.enable ??
|
|
126
|
+
(json.permissions?.http
|
|
127
|
+
? schema.properties.permissions.properties.http.properties.enable.default
|
|
128
|
+
: false),
|
|
129
|
+
domains: json.permissions?.http?.domains ??
|
|
130
|
+
schema.properties.permissions.properties.http.properties.domains.default,
|
|
131
|
+
},
|
|
132
|
+
media: json.permissions?.media ?? schema.properties.permissions.properties.media.default,
|
|
133
|
+
menu: !!partial.menu?.items?.length ||
|
|
134
|
+
(json.blocks?.menu?.enable ??
|
|
135
|
+
(json.blocks ? schema.properties.blocks.properties.menu.properties.enable.default : false)),
|
|
136
|
+
payments: json.permissions?.payments ?? schema.properties.permissions.properties.payments.default,
|
|
137
|
+
realtime: json.permissions?.realtime ?? schema.properties.permissions.properties.realtime.default,
|
|
138
|
+
redis: json.permissions?.redis ??
|
|
139
|
+
// Menu items call addCSRFTokenToContext() which uses Redis.
|
|
140
|
+
(partial.menu?.items?.length
|
|
141
|
+
? true
|
|
142
|
+
: partial.post
|
|
143
|
+
? true
|
|
144
|
+
: schema.properties.permissions.properties.redis.default),
|
|
145
|
+
reddit: {
|
|
146
|
+
enable: json.permissions?.reddit?.enable ??
|
|
147
|
+
(partial.post
|
|
148
|
+
? true
|
|
149
|
+
: json.permissions?.reddit
|
|
150
|
+
? schema.properties.permissions.properties.reddit.properties.enable.default
|
|
151
|
+
: false),
|
|
152
|
+
scope: json.permissions?.reddit?.scope ??
|
|
153
|
+
schema.properties.permissions.properties.reddit.properties.scope
|
|
154
|
+
.default,
|
|
155
|
+
asUser: json.permissions?.reddit?.asUser?.map((x) => scopeFromJSON(x)) ??
|
|
156
|
+
schema.properties.permissions.properties.reddit.properties.asUser.default,
|
|
157
|
+
},
|
|
158
|
+
settings: json.blocks?.settings?.enable ??
|
|
159
|
+
(json.blocks
|
|
160
|
+
? schema.properties.blocks.properties.settings.properties.enable.default
|
|
161
|
+
: false),
|
|
162
|
+
triggers: !!partial.triggers,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function AppPostConfig(json) {
|
|
166
|
+
const dir = json.post?.dir ?? schema.properties.post.properties.dir.default;
|
|
167
|
+
const defaultHeight = schema.$defs.Entrypoint.properties.height.default;
|
|
168
|
+
const entrypoints = {
|
|
169
|
+
[defaultPostEntry]: {
|
|
170
|
+
name: defaultPostEntry,
|
|
171
|
+
entry: json.post?.entrypoints?.default.entry ??
|
|
172
|
+
schema.properties.post.properties.entrypoints.properties.default.properties.entry.default,
|
|
173
|
+
height: json.post?.entrypoints?.default.height ?? defaultHeight,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
for (const [name, pt] of Object.entries(json.post?.entrypoints ?? {})) {
|
|
177
|
+
if (name !== defaultPostEntry)
|
|
178
|
+
entrypoints[name] = {
|
|
179
|
+
name,
|
|
180
|
+
entry: pt.entry,
|
|
181
|
+
height: pt.height ?? defaultHeight,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
dir,
|
|
186
|
+
entrypoints,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function AppBlocksConfig(json) {
|
|
190
|
+
return {
|
|
191
|
+
entry: json.blocks?.entry ?? schema.properties.blocks.properties.entry.default,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function AppMenuConfig(json) {
|
|
195
|
+
const items = [];
|
|
196
|
+
for (const item of json.menu?.items ?? []) {
|
|
197
|
+
items.push({
|
|
198
|
+
label: item.label,
|
|
199
|
+
description: item.description ?? '',
|
|
200
|
+
forUserType: item.forUserType ?? 'moderator',
|
|
201
|
+
postFilter: item.postFilter ?? 'none',
|
|
202
|
+
location: Array.isArray(item.location) ? item.location : [item.location],
|
|
203
|
+
endpoint: item.endpoint,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return { items };
|
|
207
|
+
}
|
|
208
|
+
function AppSettingsConfig(json) {
|
|
209
|
+
const appSettingsConfig = {};
|
|
210
|
+
if (json.settings?.global) {
|
|
211
|
+
appSettingsConfig.global = {};
|
|
212
|
+
for (const [name, setting] of Object.entries(json.settings.global)) {
|
|
213
|
+
appSettingsConfig.global[name] = {
|
|
214
|
+
...setting,
|
|
215
|
+
name: name,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (json.settings?.subreddit) {
|
|
220
|
+
appSettingsConfig.subreddit = {};
|
|
221
|
+
for (const [name, setting] of Object.entries(json.settings.subreddit)) {
|
|
222
|
+
appSettingsConfig.subreddit[name] = {
|
|
223
|
+
...setting,
|
|
224
|
+
name: name,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return appSettingsConfig;
|
|
229
|
+
}
|
|
230
|
+
/** @internal */
|
|
231
|
+
export function validate(config) {
|
|
232
|
+
const errs = [];
|
|
233
|
+
if (config.menu?.items?.length && !config.permissions.redis)
|
|
234
|
+
errs.push('`config.menu.items` requires `config.permissions.redis` to be enabled');
|
|
235
|
+
// If there are any select settings, their default values must be in the options,
|
|
236
|
+
// and if it's not a multi-select, the default value must be a single string.
|
|
237
|
+
const settingValues = [
|
|
238
|
+
...Object.values(config.settings?.global ?? {}),
|
|
239
|
+
...Object.values(config.settings?.subreddit ?? {}),
|
|
240
|
+
];
|
|
241
|
+
for (const setting of settingValues) {
|
|
242
|
+
if (setting.type === 'select' && setting.defaultValue) {
|
|
243
|
+
if (!setting.options.some((option) => option.value === setting.defaultValue))
|
|
244
|
+
errs.push(`Setting "${setting.name}" default value "${setting.defaultValue}" is not in
|
|
245
|
+
options "${setting.options.map((option) => option.value).join(', ')}"`);
|
|
246
|
+
}
|
|
247
|
+
if (setting.type === 'multiSelect' && setting.defaultValue) {
|
|
248
|
+
if (!setting.defaultValue.every((value) => setting.options.some((option) => option.value === value)))
|
|
249
|
+
errs.push(`Setting "${setting.name}" default values "${setting.defaultValue.join(', ')}" are not in options "${setting.options.map((option) => option.value).join(', ')}"`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (errs.length)
|
|
253
|
+
throw Error(`${errs.join('; ')}.`);
|
|
254
|
+
}
|