@cms0/cms0 0.0.1 → 0.0.4
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/README.md +31 -0
- package/dist/cjs/custom-types/index.cjs +2 -0
- package/dist/cjs/custom-types/registry.cjs +123 -0
- package/dist/cjs/generated/schema-descriptor.cjs +3 -518
- package/dist/cjs/libs/cli/descriptor-builder-alt.cjs +152 -19
- package/dist/cjs/libs/cli/descriptor-builder.cjs +46 -5
- package/dist/esm/custom-types/index.js +1 -0
- package/dist/esm/custom-types/registry.js +119 -0
- package/dist/esm/generated/schema-descriptor.js +3 -518
- package/dist/esm/index.js +1 -1
- package/dist/esm/libs/cli/descriptor-builder-alt.js +153 -20
- package/dist/esm/libs/cli/descriptor-builder.js +47 -6
- package/dist/types/custom-types/index.d.ts +35 -0
- package/dist/types/custom-types/index.d.ts.map +1 -0
- package/dist/types/custom-types/registry.d.ts +65 -0
- package/dist/types/custom-types/registry.d.ts.map +1 -0
- package/dist/types/generated/schema-descriptor.d.ts +2 -517
- package/dist/types/generated/schema-descriptor.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/libs/cli/descriptor-builder-alt.d.ts.map +1 -1
- package/dist/types/libs/cli/descriptor-builder.d.ts.map +1 -1
- package/package.json +18 -12
|
@@ -9,6 +9,22 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const ts_morph_1 = require("ts-morph");
|
|
11
11
|
const config_loader_js_1 = require("./config-loader.cjs");
|
|
12
|
+
const registry_js_1 = require("../../custom-types/registry.cjs");
|
|
13
|
+
function resolveCustomTypeName(type) {
|
|
14
|
+
const aliasSymbol = type.getAliasSymbol();
|
|
15
|
+
const symbol = type.getSymbol();
|
|
16
|
+
const name = aliasSymbol?.getName() ?? symbol?.getName();
|
|
17
|
+
if (name && registry_js_1.customTypeNames.has(name)) {
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
const text = type.getText();
|
|
21
|
+
for (const customName of registry_js_1.customTypeNames) {
|
|
22
|
+
if (text === customName || text.endsWith(`.${customName}`)) {
|
|
23
|
+
return customName;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
12
28
|
function unwrapOptional(type) {
|
|
13
29
|
let optional = false;
|
|
14
30
|
let nullable = false;
|
|
@@ -31,6 +47,14 @@ function unwrapOptional(type) {
|
|
|
31
47
|
}
|
|
32
48
|
return { base: type, optional, nullable };
|
|
33
49
|
}
|
|
50
|
+
function applyOptionalityToDescriptor(desc, optional, nullable) {
|
|
51
|
+
const clone = JSON.parse(JSON.stringify(desc));
|
|
52
|
+
if (optional)
|
|
53
|
+
clone.optional = true;
|
|
54
|
+
if (nullable)
|
|
55
|
+
clone.nullable = true;
|
|
56
|
+
return clone;
|
|
57
|
+
}
|
|
34
58
|
function collectModelNames(sourceFiles) {
|
|
35
59
|
const names = new Set();
|
|
36
60
|
sourceFiles.forEach((sf) => {
|
|
@@ -56,7 +80,9 @@ function collectReferencedModelNames(type, names, visited, ctx) {
|
|
|
56
80
|
return;
|
|
57
81
|
visited.add(key);
|
|
58
82
|
if (base.isUnion()) {
|
|
59
|
-
base
|
|
83
|
+
base
|
|
84
|
+
.getUnionTypes()
|
|
85
|
+
.forEach((t, idx) => collectReferencedModelNames(t, names, visited, `${ctx}|${idx}`));
|
|
60
86
|
return;
|
|
61
87
|
}
|
|
62
88
|
if (base.isArray()) {
|
|
@@ -67,7 +93,11 @@ function collectReferencedModelNames(type, names, visited, ctx) {
|
|
|
67
93
|
const aliasSymbol = base.getAliasSymbol();
|
|
68
94
|
const symbol = base.getSymbol();
|
|
69
95
|
const name = aliasSymbol?.getName() ?? symbol?.getName();
|
|
70
|
-
|
|
96
|
+
const customName = resolveCustomTypeName(base);
|
|
97
|
+
if (customName) {
|
|
98
|
+
names.add(customName);
|
|
99
|
+
}
|
|
100
|
+
else if (name && base.isObject()) {
|
|
71
101
|
names.add(name);
|
|
72
102
|
}
|
|
73
103
|
if (base.isObject()) {
|
|
@@ -86,7 +116,10 @@ function buildProperties(type, modelNames, warnings, ctx) {
|
|
|
86
116
|
if (!decl)
|
|
87
117
|
return;
|
|
88
118
|
const analyzed = unwrapOptional(decl.getType());
|
|
89
|
-
props[prop.getName()] = descriptorFromType(analyzed.base, modelNames, warnings, `${ctx}.${prop.getName()}`, {
|
|
119
|
+
props[prop.getName()] = descriptorFromType(analyzed.base, modelNames, warnings, `${ctx}.${prop.getName()}`, {
|
|
120
|
+
optional: prop.isOptional() || analyzed.optional,
|
|
121
|
+
nullable: analyzed.nullable,
|
|
122
|
+
});
|
|
90
123
|
});
|
|
91
124
|
return props;
|
|
92
125
|
}
|
|
@@ -95,13 +128,35 @@ function descriptorFromType(type, modelNames, warnings, ctx, opts) {
|
|
|
95
128
|
const isOptional = !!opts?.optional || optional;
|
|
96
129
|
const isNullable = !!opts?.nullable || nullable;
|
|
97
130
|
if (base.isString()) {
|
|
98
|
-
return {
|
|
131
|
+
return {
|
|
132
|
+
kind: "primitive",
|
|
133
|
+
type: "string",
|
|
134
|
+
optional: isOptional,
|
|
135
|
+
nullable: isNullable,
|
|
136
|
+
};
|
|
99
137
|
}
|
|
100
138
|
if (base.isNumber()) {
|
|
101
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
kind: "primitive",
|
|
141
|
+
type: "number",
|
|
142
|
+
optional: isOptional,
|
|
143
|
+
nullable: isNullable,
|
|
144
|
+
};
|
|
102
145
|
}
|
|
103
146
|
if (base.isBoolean()) {
|
|
104
|
-
return {
|
|
147
|
+
return {
|
|
148
|
+
kind: "primitive",
|
|
149
|
+
type: "boolean",
|
|
150
|
+
optional: isOptional,
|
|
151
|
+
nullable: isNullable,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const customName = resolveCustomTypeName(base);
|
|
155
|
+
if (customName && registry_js_1.customInlineTypeNames.has(customName)) {
|
|
156
|
+
const inlineDescriptor = registry_js_1.customInlineDescriptors[customName];
|
|
157
|
+
if (inlineDescriptor) {
|
|
158
|
+
return applyOptionalityToDescriptor(inlineDescriptor, isOptional, isNullable);
|
|
159
|
+
}
|
|
105
160
|
}
|
|
106
161
|
if (base.isArray()) {
|
|
107
162
|
const elem = base.getArrayElementTypeOrThrow();
|
|
@@ -115,8 +170,14 @@ function descriptorFromType(type, modelNames, warnings, ctx, opts) {
|
|
|
115
170
|
const aliasSymbol = base.getAliasSymbol();
|
|
116
171
|
const symbol = base.getSymbol();
|
|
117
172
|
const name = aliasSymbol?.getName() ?? symbol?.getName();
|
|
118
|
-
|
|
119
|
-
|
|
173
|
+
const modelName = customName ?? name;
|
|
174
|
+
if (modelName && modelNames.has(modelName)) {
|
|
175
|
+
return {
|
|
176
|
+
kind: "modelRef",
|
|
177
|
+
model: modelName,
|
|
178
|
+
optional: isOptional,
|
|
179
|
+
nullable: isNullable,
|
|
180
|
+
};
|
|
120
181
|
}
|
|
121
182
|
if (base.isObject()) {
|
|
122
183
|
return {
|
|
@@ -127,7 +188,12 @@ function descriptorFromType(type, modelNames, warnings, ctx, opts) {
|
|
|
127
188
|
};
|
|
128
189
|
}
|
|
129
190
|
warnings.add(`cms0: unsupported type at ${ctx}; falling back to string`);
|
|
130
|
-
return {
|
|
191
|
+
return {
|
|
192
|
+
kind: "primitive",
|
|
193
|
+
type: "string",
|
|
194
|
+
optional: isOptional,
|
|
195
|
+
nullable: isNullable,
|
|
196
|
+
};
|
|
131
197
|
}
|
|
132
198
|
function collectModels(sourceFiles, modelNames, modelMap, warnings) {
|
|
133
199
|
const handleShape = (name, type, ctx) => {
|
|
@@ -137,7 +203,10 @@ function collectModels(sourceFiles, modelNames, modelMap, warnings) {
|
|
|
137
203
|
return;
|
|
138
204
|
if (!type.isObject())
|
|
139
205
|
return;
|
|
140
|
-
modelMap[name] = {
|
|
206
|
+
modelMap[name] = {
|
|
207
|
+
kind: "model",
|
|
208
|
+
properties: buildProperties(type, modelNames, warnings, ctx),
|
|
209
|
+
};
|
|
141
210
|
};
|
|
142
211
|
sourceFiles.forEach((sf) => {
|
|
143
212
|
sf.getTypeAliases().forEach((alias) => {
|
|
@@ -152,24 +221,57 @@ function collectModels(sourceFiles, modelNames, modelMap, warnings) {
|
|
|
152
221
|
});
|
|
153
222
|
});
|
|
154
223
|
}
|
|
155
|
-
function
|
|
224
|
+
function readCms0Options(invoc) {
|
|
225
|
+
const arg = invoc.getArguments()[0];
|
|
226
|
+
if (!arg || !ts_morph_1.Node.isObjectLiteralExpression(arg))
|
|
227
|
+
return {};
|
|
228
|
+
const options = {};
|
|
229
|
+
const localesProp = arg.getProperty("locales");
|
|
230
|
+
if (localesProp && ts_morph_1.Node.isPropertyAssignment(localesProp)) {
|
|
231
|
+
const init = localesProp.getInitializer();
|
|
232
|
+
if (init && ts_morph_1.Node.isArrayLiteralExpression(init)) {
|
|
233
|
+
const values = init
|
|
234
|
+
.getElements()
|
|
235
|
+
.map((el) => (ts_morph_1.Node.isStringLiteral(el) ? el.getLiteralValue() : null))
|
|
236
|
+
.filter((val) => Boolean(val));
|
|
237
|
+
if (values.length)
|
|
238
|
+
options.locales = values;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const defaultProp = arg.getProperty("defaultLocale");
|
|
242
|
+
if (defaultProp && ts_morph_1.Node.isPropertyAssignment(defaultProp)) {
|
|
243
|
+
const init = defaultProp.getInitializer();
|
|
244
|
+
if (init && ts_morph_1.Node.isStringLiteral(init)) {
|
|
245
|
+
options.defaultLocale = init.getLiteralValue();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return options;
|
|
249
|
+
}
|
|
250
|
+
function findRootInvocation(sourceFiles) {
|
|
156
251
|
for (const sf of sourceFiles) {
|
|
157
252
|
const invoc = sf
|
|
158
253
|
?.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression)
|
|
159
254
|
.find((call) => call.getExpression().getText() === "cms0");
|
|
160
255
|
if (invoc) {
|
|
161
256
|
const typeArgs = invoc.getTypeArguments();
|
|
162
|
-
if (typeArgs.length > 0)
|
|
163
|
-
return
|
|
257
|
+
if (typeArgs.length > 0) {
|
|
258
|
+
return {
|
|
259
|
+
rootType: typeArgs[0].getType(),
|
|
260
|
+
...readCms0Options(invoc),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
164
263
|
}
|
|
165
264
|
}
|
|
166
265
|
return undefined;
|
|
167
266
|
}
|
|
168
267
|
function buildDescriptorAlt(resolved) {
|
|
169
268
|
const tsconfig = resolved.tsconfigPath ?? (0, config_loader_js_1.findTsConfig)(resolved.entryFile);
|
|
170
|
-
const project = tsconfig
|
|
269
|
+
const project = tsconfig
|
|
270
|
+
? new ts_morph_1.Project({ tsConfigFilePath: tsconfig })
|
|
271
|
+
: new ts_morph_1.Project();
|
|
171
272
|
const warnings = new Set();
|
|
172
|
-
if (!project.getSourceFile(resolved.entryFile) &&
|
|
273
|
+
if (!project.getSourceFile(resolved.entryFile) &&
|
|
274
|
+
fs_1.default.existsSync(resolved.entryFile)) {
|
|
173
275
|
project.addSourceFileAtPath(resolved.entryFile);
|
|
174
276
|
}
|
|
175
277
|
const sourceFiles = project.getSourceFiles().filter((sf) => {
|
|
@@ -181,16 +283,36 @@ function buildDescriptorAlt(resolved) {
|
|
|
181
283
|
const rel = path_1.default.relative(path_1.default.dirname(resolved.entryFile), filePath);
|
|
182
284
|
return rel && !rel.startsWith("..") && !path_1.default.isAbsolute(rel);
|
|
183
285
|
});
|
|
184
|
-
const
|
|
185
|
-
if (!
|
|
286
|
+
const invocation = findRootInvocation(sourceFiles);
|
|
287
|
+
if (!invocation)
|
|
186
288
|
throw new Error("Could not locate cms0<T>() invocation in project sources.");
|
|
289
|
+
const rootType = invocation.rootType;
|
|
187
290
|
// Restrict models to only those referenced by the root type tree and exported in scope.
|
|
188
291
|
const exportedModelNames = collectModelNames(sourceFiles);
|
|
292
|
+
const collisions = Array.from(registry_js_1.customTypeNames).filter((name) => exportedModelNames.has(name));
|
|
293
|
+
if (collisions.length) {
|
|
294
|
+
throw new Error(`cms0: custom type name collision: ${collisions.join(", ")}. Rename your model(s) or use a different custom type name.`);
|
|
295
|
+
}
|
|
189
296
|
const referencedModelNames = new Set();
|
|
190
297
|
collectReferencedModelNames(rootType, referencedModelNames, new Set(), "root");
|
|
191
|
-
const
|
|
298
|
+
const referencedCustomTypeNames = new Set(Array.from(referencedModelNames).filter((n) => registry_js_1.customTypeNames.has(n)));
|
|
299
|
+
const referencedCustomModelNames = new Set(Array.from(referencedCustomTypeNames).filter((n) => registry_js_1.customModelTypeNames.has(n)));
|
|
300
|
+
const resolvedCustomTypeNames = (0, registry_js_1.resolveCustomTypeDependencies)(referencedCustomModelNames);
|
|
301
|
+
const modelNames = new Set([
|
|
302
|
+
...Array.from(referencedModelNames).filter((n) => exportedModelNames.has(n)),
|
|
303
|
+
...Array.from(resolvedCustomTypeNames),
|
|
304
|
+
]);
|
|
192
305
|
const modelMap = {};
|
|
193
306
|
collectModels(sourceFiles, modelNames, modelMap, warnings);
|
|
307
|
+
resolvedCustomTypeNames.forEach((name) => {
|
|
308
|
+
if (modelMap[name]) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const descriptor = registry_js_1.customModelDescriptors[name];
|
|
312
|
+
if (descriptor) {
|
|
313
|
+
modelMap[name] = descriptor;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
194
316
|
const roots = {};
|
|
195
317
|
for (const prop of rootType.getProperties()) {
|
|
196
318
|
const name = prop.getName();
|
|
@@ -217,5 +339,16 @@ function buildDescriptorAlt(resolved) {
|
|
|
217
339
|
}
|
|
218
340
|
if (warnings.size)
|
|
219
341
|
warnings.forEach((w) => console.warn(w));
|
|
220
|
-
|
|
342
|
+
const locales = invocation.locales;
|
|
343
|
+
const defaultLocale = invocation.defaultLocale;
|
|
344
|
+
return {
|
|
345
|
+
models: modelMap,
|
|
346
|
+
roots,
|
|
347
|
+
metadata: locales || defaultLocale
|
|
348
|
+
? {
|
|
349
|
+
locales,
|
|
350
|
+
defaultLocale,
|
|
351
|
+
}
|
|
352
|
+
: undefined,
|
|
353
|
+
};
|
|
221
354
|
}
|
|
@@ -127,7 +127,33 @@ function collectModels(sourceFiles, modelMap, warnings) {
|
|
|
127
127
|
});
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
|
-
function
|
|
130
|
+
function readCms0Options(invoc) {
|
|
131
|
+
const arg = invoc.getArguments()[0];
|
|
132
|
+
if (!arg || !ts_morph_1.Node.isObjectLiteralExpression(arg))
|
|
133
|
+
return {};
|
|
134
|
+
const options = {};
|
|
135
|
+
const localesProp = arg.getProperty("locales");
|
|
136
|
+
if (localesProp && ts_morph_1.Node.isPropertyAssignment(localesProp)) {
|
|
137
|
+
const init = localesProp.getInitializer();
|
|
138
|
+
if (init && ts_morph_1.Node.isArrayLiteralExpression(init)) {
|
|
139
|
+
const values = init
|
|
140
|
+
.getElements()
|
|
141
|
+
.map((el) => (ts_morph_1.Node.isStringLiteral(el) ? el.getLiteralValue() : null))
|
|
142
|
+
.filter((val) => Boolean(val));
|
|
143
|
+
if (values.length)
|
|
144
|
+
options.locales = values;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const defaultProp = arg.getProperty("defaultLocale");
|
|
148
|
+
if (defaultProp && ts_morph_1.Node.isPropertyAssignment(defaultProp)) {
|
|
149
|
+
const init = defaultProp.getInitializer();
|
|
150
|
+
if (init && ts_morph_1.Node.isStringLiteral(init)) {
|
|
151
|
+
options.defaultLocale = init.getLiteralValue();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return options;
|
|
155
|
+
}
|
|
156
|
+
function findRootInvocation(sourceFiles) {
|
|
131
157
|
for (const sf of sourceFiles) {
|
|
132
158
|
const invoc = sf
|
|
133
159
|
?.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression)
|
|
@@ -135,7 +161,10 @@ function findRootType(sourceFiles) {
|
|
|
135
161
|
if (invoc) {
|
|
136
162
|
const typeArgs = invoc.getTypeArguments();
|
|
137
163
|
if (typeArgs.length > 0) {
|
|
138
|
-
return
|
|
164
|
+
return {
|
|
165
|
+
rootType: typeArgs[0].getType(),
|
|
166
|
+
...readCms0Options(invoc),
|
|
167
|
+
};
|
|
139
168
|
}
|
|
140
169
|
}
|
|
141
170
|
}
|
|
@@ -159,10 +188,11 @@ function buildDescriptor(resolved) {
|
|
|
159
188
|
});
|
|
160
189
|
const modelMap = {};
|
|
161
190
|
collectModels(sourceFiles, modelMap, warnings);
|
|
162
|
-
const
|
|
163
|
-
if (!
|
|
191
|
+
const invocation = findRootInvocation(sourceFiles);
|
|
192
|
+
if (!invocation) {
|
|
164
193
|
throw new Error("Could not locate cms0<T>() invocation in project sources.");
|
|
165
194
|
}
|
|
195
|
+
const rootType = invocation.rootType;
|
|
166
196
|
const roots = {};
|
|
167
197
|
for (const prop of rootType.getProperties()) {
|
|
168
198
|
const name = prop.getName();
|
|
@@ -228,5 +258,16 @@ function buildDescriptor(resolved) {
|
|
|
228
258
|
if (warnings.size) {
|
|
229
259
|
warnings.forEach((w) => console.warn(w));
|
|
230
260
|
}
|
|
231
|
-
|
|
261
|
+
const locales = invocation.locales;
|
|
262
|
+
const defaultLocale = invocation.defaultLocale;
|
|
263
|
+
return {
|
|
264
|
+
models: modelMap,
|
|
265
|
+
roots,
|
|
266
|
+
metadata: locales || defaultLocale
|
|
267
|
+
? {
|
|
268
|
+
locales,
|
|
269
|
+
defaultLocale,
|
|
270
|
+
}
|
|
271
|
+
: undefined,
|
|
272
|
+
};
|
|
232
273
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const primitive = (type) => ({
|
|
2
|
+
kind: "primitive",
|
|
3
|
+
type,
|
|
4
|
+
optional: false,
|
|
5
|
+
nullable: false,
|
|
6
|
+
});
|
|
7
|
+
const fileFieldDescriptors = {
|
|
8
|
+
name: primitive("string"),
|
|
9
|
+
filename: primitive("string"),
|
|
10
|
+
extension: primitive("string"),
|
|
11
|
+
mimeType: primitive("string"),
|
|
12
|
+
size: primitive("number"),
|
|
13
|
+
};
|
|
14
|
+
const fileDescriptor = {
|
|
15
|
+
kind: "model",
|
|
16
|
+
properties: fileFieldDescriptors,
|
|
17
|
+
};
|
|
18
|
+
const imageDescriptor = {
|
|
19
|
+
kind: "model",
|
|
20
|
+
properties: {
|
|
21
|
+
...fileFieldDescriptors,
|
|
22
|
+
width: primitive("number"),
|
|
23
|
+
height: primitive("number"),
|
|
24
|
+
alt: { kind: "primitive", type: "string", optional: true, nullable: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const videoDescriptor = {
|
|
28
|
+
kind: "model",
|
|
29
|
+
properties: {
|
|
30
|
+
...fileFieldDescriptors,
|
|
31
|
+
width: primitive("number"),
|
|
32
|
+
height: primitive("number"),
|
|
33
|
+
length: primitive("number"),
|
|
34
|
+
alt: { kind: "primitive", type: "string", optional: true, nullable: false },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
const richTextDescriptor = {
|
|
38
|
+
kind: "primitive",
|
|
39
|
+
type: "json",
|
|
40
|
+
customType: "RichText",
|
|
41
|
+
};
|
|
42
|
+
const localizedStringDescriptor = {
|
|
43
|
+
type: "array",
|
|
44
|
+
items: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
locale: primitive("string"),
|
|
48
|
+
isDefault: primitive("boolean"),
|
|
49
|
+
value: primitive("string"),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
customType: "LocalizedString",
|
|
53
|
+
};
|
|
54
|
+
const localizedRichTextDescriptor = {
|
|
55
|
+
type: "array",
|
|
56
|
+
items: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
locale: primitive("string"),
|
|
60
|
+
isDefault: primitive("boolean"),
|
|
61
|
+
value: primitive("json"),
|
|
62
|
+
html: primitive("string"),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
customType: "LocalizedRichText",
|
|
66
|
+
};
|
|
67
|
+
export const customModelDescriptors = {
|
|
68
|
+
File: fileDescriptor,
|
|
69
|
+
Image: imageDescriptor,
|
|
70
|
+
Video: videoDescriptor,
|
|
71
|
+
};
|
|
72
|
+
export const customInlineDescriptors = {
|
|
73
|
+
RichText: richTextDescriptor,
|
|
74
|
+
LocalizedString: localizedStringDescriptor,
|
|
75
|
+
LocalizedRichText: localizedRichTextDescriptor,
|
|
76
|
+
};
|
|
77
|
+
export const customTypeDescriptors = {
|
|
78
|
+
...customModelDescriptors,
|
|
79
|
+
...customInlineDescriptors,
|
|
80
|
+
};
|
|
81
|
+
export const customTypeNames = new Set(Object.keys(customTypeDescriptors));
|
|
82
|
+
export const customModelTypeNames = new Set(Object.keys(customModelDescriptors));
|
|
83
|
+
export const customInlineTypeNames = new Set(Object.keys(customInlineDescriptors));
|
|
84
|
+
export function resolveCustomTypeDependencies(names) {
|
|
85
|
+
const resolved = new Set();
|
|
86
|
+
const queue = Array.from(names);
|
|
87
|
+
while (queue.length) {
|
|
88
|
+
const name = queue.shift();
|
|
89
|
+
if (!name || resolved.has(name))
|
|
90
|
+
continue;
|
|
91
|
+
const descriptor = customModelDescriptors[name];
|
|
92
|
+
if (!descriptor)
|
|
93
|
+
continue;
|
|
94
|
+
resolved.add(name);
|
|
95
|
+
const refs = new Set();
|
|
96
|
+
for (const prop of Object.values(descriptor.properties)) {
|
|
97
|
+
collectModelRefs(prop, refs);
|
|
98
|
+
}
|
|
99
|
+
refs.forEach((ref) => {
|
|
100
|
+
if (customTypeDescriptors[ref] && !resolved.has(ref)) {
|
|
101
|
+
queue.push(ref);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return resolved;
|
|
106
|
+
}
|
|
107
|
+
function collectModelRefs(desc, out) {
|
|
108
|
+
if (desc.kind === "modelRef") {
|
|
109
|
+
out.add(desc.model);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (desc.type === "array") {
|
|
113
|
+
collectModelRefs(desc.items, out);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (desc.type === "object") {
|
|
117
|
+
Object.values(desc.properties).forEach((child) => collectModelRefs(child, out));
|
|
118
|
+
}
|
|
119
|
+
}
|