@formspec/build 0.1.0-alpha.28 → 0.1.0-alpha.29
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/dist/analyzer/class-analyzer.d.ts +11 -5
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/program.d.ts +3 -2
- package/dist/analyzer/program.d.ts.map +1 -1
- package/dist/browser.cjs +485 -76
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +486 -77
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +18 -2
- package/dist/build-beta.d.ts +18 -2
- package/dist/build-internal.d.ts +18 -2
- package/dist/build.d.ts +18 -2
- package/dist/canonicalize/chain-dsl-canonicalizer.d.ts +5 -2
- package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -1
- package/dist/canonicalize/tsdoc-canonicalizer.d.ts +5 -1
- package/dist/canonicalize/tsdoc-canonicalizer.d.ts.map +1 -1
- package/dist/cli.cjs +1031 -170
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1032 -171
- package/dist/cli.js.map +1 -1
- package/dist/generators/class-schema.d.ts +6 -1
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/generators/method-schema.d.ts.map +1 -1
- package/dist/generators/mixed-authoring.d.ts.map +1 -1
- package/dist/index.cjs +998 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +999 -171
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +921 -155
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +922 -156
- package/dist/internals.js.map +1 -1
- package/dist/json-schema/generator.d.ts +3 -1
- package/dist/json-schema/generator.d.ts.map +1 -1
- package/dist/json-schema/ir-generator.d.ts.map +1 -1
- package/dist/metadata/collision-guards.d.ts +3 -0
- package/dist/metadata/collision-guards.d.ts.map +1 -0
- package/dist/metadata/index.d.ts +7 -0
- package/dist/metadata/index.d.ts.map +1 -0
- package/dist/metadata/policy.d.ts +11 -0
- package/dist/metadata/policy.d.ts.map +1 -0
- package/dist/metadata/resolve.d.ts +20 -0
- package/dist/metadata/resolve.d.ts.map +1 -0
- package/dist/ui-schema/generator.d.ts +11 -2
- package/dist/ui-schema/generator.d.ts.map +1 -1
- package/dist/ui-schema/ir-generator.d.ts +2 -1
- package/dist/ui-schema/ir-generator.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,315 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
46
|
|
|
47
47
|
// src/canonicalize/chain-dsl-canonicalizer.ts
|
|
48
48
|
var import_internals = require("@formspec/core/internals");
|
|
49
|
+
|
|
50
|
+
// src/metadata/policy.ts
|
|
51
|
+
var NOOP_INFLECT = () => "";
|
|
52
|
+
function normalizePluralization(input) {
|
|
53
|
+
if (input?.mode === "infer-if-missing") {
|
|
54
|
+
return {
|
|
55
|
+
mode: "infer-if-missing",
|
|
56
|
+
infer: () => "",
|
|
57
|
+
inflect: input.inflect
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (input?.mode === "require-explicit") {
|
|
61
|
+
return {
|
|
62
|
+
mode: "require-explicit",
|
|
63
|
+
infer: () => "",
|
|
64
|
+
inflect: NOOP_INFLECT
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
mode: "disabled",
|
|
69
|
+
infer: () => "",
|
|
70
|
+
inflect: NOOP_INFLECT
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function normalizeScalarPolicy(input) {
|
|
74
|
+
if (input?.mode === "infer-if-missing") {
|
|
75
|
+
return {
|
|
76
|
+
mode: "infer-if-missing",
|
|
77
|
+
infer: input.infer,
|
|
78
|
+
pluralization: normalizePluralization(input.pluralization)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (input?.mode === "require-explicit") {
|
|
82
|
+
return {
|
|
83
|
+
mode: "require-explicit",
|
|
84
|
+
infer: () => "",
|
|
85
|
+
pluralization: normalizePluralization(input.pluralization)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
mode: "disabled",
|
|
90
|
+
infer: () => "",
|
|
91
|
+
pluralization: normalizePluralization(input?.pluralization)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function normalizeDeclarationPolicy(input) {
|
|
95
|
+
return {
|
|
96
|
+
apiName: normalizeScalarPolicy(input?.apiName),
|
|
97
|
+
displayName: normalizeScalarPolicy(input?.displayName)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function normalizeMetadataPolicy(input) {
|
|
101
|
+
return {
|
|
102
|
+
type: normalizeDeclarationPolicy(input?.type),
|
|
103
|
+
field: normalizeDeclarationPolicy(input?.field),
|
|
104
|
+
method: normalizeDeclarationPolicy(input?.method)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function getDeclarationMetadataPolicy(policy, declarationKind) {
|
|
108
|
+
return policy[declarationKind];
|
|
109
|
+
}
|
|
110
|
+
function makeMetadataContext(surface, declarationKind, logicalName, buildContext) {
|
|
111
|
+
return {
|
|
112
|
+
surface,
|
|
113
|
+
declarationKind,
|
|
114
|
+
logicalName,
|
|
115
|
+
...buildContext !== void 0 && { buildContext }
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/metadata/resolve.ts
|
|
120
|
+
function toExplicitScalar(value) {
|
|
121
|
+
return value !== void 0 && value.trim() !== "" ? { value, source: "explicit" } : void 0;
|
|
122
|
+
}
|
|
123
|
+
function toExplicitResolvedMetadata(explicit) {
|
|
124
|
+
if (explicit === void 0) {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
const apiName = toExplicitScalar(explicit.apiName);
|
|
128
|
+
const displayName = toExplicitScalar(explicit.displayName);
|
|
129
|
+
const apiNamePlural = toExplicitScalar(explicit.apiNamePlural);
|
|
130
|
+
const displayNamePlural = toExplicitScalar(explicit.displayNamePlural);
|
|
131
|
+
const metadata = {
|
|
132
|
+
...apiName !== void 0 && { apiName },
|
|
133
|
+
...displayName !== void 0 && { displayName },
|
|
134
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
135
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
136
|
+
};
|
|
137
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
138
|
+
}
|
|
139
|
+
function resolveScalar(current, policy, context, metadataLabel) {
|
|
140
|
+
if (current !== void 0) {
|
|
141
|
+
return current;
|
|
142
|
+
}
|
|
143
|
+
if (policy.mode === "require-explicit") {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`Metadata policy requires explicit ${metadataLabel} for ${context.declarationKind} "${context.logicalName}" on the ${context.surface} surface.`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (policy.mode !== "infer-if-missing") {
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
const inferredValue = policy.infer(context);
|
|
152
|
+
return inferredValue.trim() !== "" ? { value: inferredValue, source: "inferred" } : void 0;
|
|
153
|
+
}
|
|
154
|
+
function resolvePlural(current, singular, policy, context, metadataLabel) {
|
|
155
|
+
if (current !== void 0) {
|
|
156
|
+
return current;
|
|
157
|
+
}
|
|
158
|
+
if (policy.mode === "require-explicit") {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Metadata policy requires explicit ${metadataLabel} for ${context.declarationKind} "${context.logicalName}" on the ${context.surface} surface.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (singular === void 0 || policy.mode !== "infer-if-missing") {
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
const pluralValue = policy.inflect({ ...context, singular: singular.value });
|
|
167
|
+
return pluralValue.trim() !== "" ? { value: pluralValue, source: "inferred" } : void 0;
|
|
168
|
+
}
|
|
169
|
+
function resolveResolvedMetadata(current, policy, context) {
|
|
170
|
+
const apiName = resolveScalar(current?.apiName, policy.apiName, context, "apiName");
|
|
171
|
+
const displayName = resolveScalar(
|
|
172
|
+
current?.displayName,
|
|
173
|
+
policy.displayName,
|
|
174
|
+
context,
|
|
175
|
+
"displayName"
|
|
176
|
+
);
|
|
177
|
+
const apiNamePlural = resolvePlural(
|
|
178
|
+
current?.apiNamePlural,
|
|
179
|
+
apiName,
|
|
180
|
+
policy.apiName.pluralization,
|
|
181
|
+
context,
|
|
182
|
+
"apiNamePlural"
|
|
183
|
+
);
|
|
184
|
+
const displayNamePlural = resolvePlural(
|
|
185
|
+
current?.displayNamePlural,
|
|
186
|
+
displayName,
|
|
187
|
+
policy.displayName.pluralization,
|
|
188
|
+
context,
|
|
189
|
+
"displayNamePlural"
|
|
190
|
+
);
|
|
191
|
+
if (apiName === void 0 && displayName === void 0 && apiNamePlural === void 0 && displayNamePlural === void 0) {
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
...apiName !== void 0 && { apiName },
|
|
196
|
+
...displayName !== void 0 && { displayName },
|
|
197
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
198
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function pickResolvedMetadataValue(baseValue, overlayValue) {
|
|
202
|
+
if (overlayValue?.source === "explicit") {
|
|
203
|
+
return overlayValue;
|
|
204
|
+
}
|
|
205
|
+
if (baseValue?.source === "explicit") {
|
|
206
|
+
return baseValue;
|
|
207
|
+
}
|
|
208
|
+
return baseValue ?? overlayValue;
|
|
209
|
+
}
|
|
210
|
+
function resolveTypeNodeMetadata(type, options) {
|
|
211
|
+
switch (type.kind) {
|
|
212
|
+
case "array":
|
|
213
|
+
return {
|
|
214
|
+
...type,
|
|
215
|
+
items: resolveTypeNodeMetadata(type.items, options)
|
|
216
|
+
};
|
|
217
|
+
case "object":
|
|
218
|
+
return {
|
|
219
|
+
...type,
|
|
220
|
+
properties: type.properties.map((property) => resolveObjectPropertyMetadata(property, options))
|
|
221
|
+
};
|
|
222
|
+
case "record":
|
|
223
|
+
return {
|
|
224
|
+
...type,
|
|
225
|
+
valueType: resolveTypeNodeMetadata(type.valueType, options)
|
|
226
|
+
};
|
|
227
|
+
case "union":
|
|
228
|
+
return {
|
|
229
|
+
...type,
|
|
230
|
+
members: type.members.map((member) => resolveTypeNodeMetadata(member, options))
|
|
231
|
+
};
|
|
232
|
+
case "reference":
|
|
233
|
+
case "primitive":
|
|
234
|
+
case "enum":
|
|
235
|
+
case "dynamic":
|
|
236
|
+
case "custom":
|
|
237
|
+
return type;
|
|
238
|
+
default: {
|
|
239
|
+
const _exhaustive = type;
|
|
240
|
+
return _exhaustive;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function resolveObjectPropertyMetadata(property, options) {
|
|
245
|
+
const metadata = resolveResolvedMetadata(property.metadata, options.policy.field, {
|
|
246
|
+
surface: options.surface,
|
|
247
|
+
declarationKind: "field",
|
|
248
|
+
logicalName: property.name,
|
|
249
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
250
|
+
});
|
|
251
|
+
return {
|
|
252
|
+
...property,
|
|
253
|
+
...metadata !== void 0 && { metadata },
|
|
254
|
+
type: resolveTypeNodeMetadata(property.type, options)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function resolveFieldMetadataNode(field, options) {
|
|
258
|
+
const metadata = resolveResolvedMetadata(field.metadata, options.policy.field, {
|
|
259
|
+
surface: options.surface,
|
|
260
|
+
declarationKind: "field",
|
|
261
|
+
logicalName: field.name,
|
|
262
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
263
|
+
});
|
|
264
|
+
return {
|
|
265
|
+
...field,
|
|
266
|
+
...metadata !== void 0 && { metadata },
|
|
267
|
+
type: resolveTypeNodeMetadata(field.type, options)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function resolveFormElementMetadata(element, options) {
|
|
271
|
+
switch (element.kind) {
|
|
272
|
+
case "field":
|
|
273
|
+
return resolveFieldMetadataNode(element, options);
|
|
274
|
+
case "group":
|
|
275
|
+
return {
|
|
276
|
+
...element,
|
|
277
|
+
elements: element.elements.map((child) => resolveFormElementMetadata(child, options))
|
|
278
|
+
};
|
|
279
|
+
case "conditional":
|
|
280
|
+
return {
|
|
281
|
+
...element,
|
|
282
|
+
elements: element.elements.map((child) => resolveFormElementMetadata(child, options))
|
|
283
|
+
};
|
|
284
|
+
default: {
|
|
285
|
+
const _exhaustive = element;
|
|
286
|
+
return _exhaustive;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function resolveTypeDefinitionMetadata(typeDefinition, options) {
|
|
291
|
+
const metadata = resolveResolvedMetadata(typeDefinition.metadata, options.policy.type, {
|
|
292
|
+
surface: options.surface,
|
|
293
|
+
declarationKind: "type",
|
|
294
|
+
logicalName: typeDefinition.name,
|
|
295
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
296
|
+
});
|
|
297
|
+
return {
|
|
298
|
+
...typeDefinition,
|
|
299
|
+
...metadata !== void 0 && { metadata },
|
|
300
|
+
type: resolveTypeNodeMetadata(typeDefinition.type, options)
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function resolveMetadata(explicit, policy, context) {
|
|
304
|
+
return resolveResolvedMetadata(toExplicitResolvedMetadata(explicit), policy, context);
|
|
305
|
+
}
|
|
306
|
+
function mergeResolvedMetadata(baseMetadata, overlayMetadata) {
|
|
307
|
+
const apiName = pickResolvedMetadataValue(baseMetadata?.apiName, overlayMetadata?.apiName);
|
|
308
|
+
const displayName = pickResolvedMetadataValue(
|
|
309
|
+
baseMetadata?.displayName,
|
|
310
|
+
overlayMetadata?.displayName
|
|
311
|
+
);
|
|
312
|
+
const apiNamePlural = pickResolvedMetadataValue(
|
|
313
|
+
baseMetadata?.apiNamePlural,
|
|
314
|
+
overlayMetadata?.apiNamePlural
|
|
315
|
+
);
|
|
316
|
+
const displayNamePlural = pickResolvedMetadataValue(
|
|
317
|
+
baseMetadata?.displayNamePlural,
|
|
318
|
+
overlayMetadata?.displayNamePlural
|
|
319
|
+
);
|
|
320
|
+
if (apiName === void 0 && displayName === void 0 && apiNamePlural === void 0 && displayNamePlural === void 0) {
|
|
321
|
+
return void 0;
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
...apiName !== void 0 && { apiName },
|
|
325
|
+
...displayName !== void 0 && { displayName },
|
|
326
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
327
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function getSerializedName(logicalName, metadata) {
|
|
331
|
+
return metadata?.apiName?.value ?? logicalName;
|
|
332
|
+
}
|
|
333
|
+
function getDisplayName(metadata) {
|
|
334
|
+
return metadata?.displayName?.value;
|
|
335
|
+
}
|
|
336
|
+
function resolveFormIRMetadata(ir, options) {
|
|
337
|
+
const rootLogicalName = options.rootLogicalName ?? ir.name ?? "FormSpec";
|
|
338
|
+
const metadata = resolveResolvedMetadata(ir.metadata, options.policy.type, {
|
|
339
|
+
surface: options.surface,
|
|
340
|
+
declarationKind: "type",
|
|
341
|
+
logicalName: rootLogicalName,
|
|
342
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
343
|
+
});
|
|
344
|
+
return {
|
|
345
|
+
...ir,
|
|
346
|
+
...metadata !== void 0 && { metadata },
|
|
347
|
+
elements: ir.elements.map((element) => resolveFormElementMetadata(element, options)),
|
|
348
|
+
typeRegistry: Object.fromEntries(
|
|
349
|
+
Object.entries(ir.typeRegistry).map(([name, definition]) => [
|
|
350
|
+
name,
|
|
351
|
+
resolveTypeDefinitionMetadata(definition, options)
|
|
352
|
+
])
|
|
353
|
+
)
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/canonicalize/chain-dsl-canonicalizer.ts
|
|
49
358
|
var CHAIN_DSL_PROVENANCE = {
|
|
50
359
|
surface: "chain-dsl",
|
|
51
360
|
file: "",
|
|
@@ -61,57 +370,60 @@ function isConditional(el) {
|
|
|
61
370
|
function isField(el) {
|
|
62
371
|
return el._type === "field";
|
|
63
372
|
}
|
|
64
|
-
function canonicalizeChainDSL(form) {
|
|
373
|
+
function canonicalizeChainDSL(form, options) {
|
|
374
|
+
const metadataPolicy = normalizeMetadataPolicy(
|
|
375
|
+
options?.metadata ?? (0, import_internals._getFormSpecMetadataPolicy)(form)
|
|
376
|
+
);
|
|
65
377
|
return {
|
|
66
378
|
kind: "form-ir",
|
|
67
379
|
irVersion: import_internals.IR_VERSION,
|
|
68
|
-
elements: canonicalizeElements(form.elements),
|
|
380
|
+
elements: canonicalizeElements(form.elements, metadataPolicy),
|
|
69
381
|
rootAnnotations: [],
|
|
70
382
|
typeRegistry: {},
|
|
71
383
|
provenance: CHAIN_DSL_PROVENANCE
|
|
72
384
|
};
|
|
73
385
|
}
|
|
74
|
-
function canonicalizeElements(elements) {
|
|
75
|
-
return elements.map(canonicalizeElement);
|
|
386
|
+
function canonicalizeElements(elements, metadataPolicy) {
|
|
387
|
+
return elements.map((element) => canonicalizeElement(element, metadataPolicy));
|
|
76
388
|
}
|
|
77
|
-
function canonicalizeElement(element) {
|
|
389
|
+
function canonicalizeElement(element, metadataPolicy) {
|
|
78
390
|
if (isField(element)) {
|
|
79
|
-
return canonicalizeField(element);
|
|
391
|
+
return canonicalizeField(element, metadataPolicy);
|
|
80
392
|
}
|
|
81
393
|
if (isGroup(element)) {
|
|
82
|
-
return canonicalizeGroup(element);
|
|
394
|
+
return canonicalizeGroup(element, metadataPolicy);
|
|
83
395
|
}
|
|
84
396
|
if (isConditional(element)) {
|
|
85
|
-
return canonicalizeConditional(element);
|
|
397
|
+
return canonicalizeConditional(element, metadataPolicy);
|
|
86
398
|
}
|
|
87
399
|
const _exhaustive = element;
|
|
88
400
|
throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);
|
|
89
401
|
}
|
|
90
|
-
function canonicalizeField(field) {
|
|
402
|
+
function canonicalizeField(field, metadataPolicy) {
|
|
91
403
|
switch (field._field) {
|
|
92
404
|
case "text":
|
|
93
|
-
return canonicalizeTextField(field);
|
|
405
|
+
return canonicalizeTextField(field, metadataPolicy);
|
|
94
406
|
case "number":
|
|
95
|
-
return canonicalizeNumberField(field);
|
|
407
|
+
return canonicalizeNumberField(field, metadataPolicy);
|
|
96
408
|
case "boolean":
|
|
97
|
-
return canonicalizeBooleanField(field);
|
|
409
|
+
return canonicalizeBooleanField(field, metadataPolicy);
|
|
98
410
|
case "enum":
|
|
99
|
-
return canonicalizeStaticEnumField(field);
|
|
411
|
+
return canonicalizeStaticEnumField(field, metadataPolicy);
|
|
100
412
|
case "dynamic_enum":
|
|
101
|
-
return canonicalizeDynamicEnumField(field);
|
|
413
|
+
return canonicalizeDynamicEnumField(field, metadataPolicy);
|
|
102
414
|
case "dynamic_schema":
|
|
103
|
-
return canonicalizeDynamicSchemaField(field);
|
|
415
|
+
return canonicalizeDynamicSchemaField(field, metadataPolicy);
|
|
104
416
|
case "array":
|
|
105
|
-
return canonicalizeArrayField(field);
|
|
417
|
+
return canonicalizeArrayField(field, metadataPolicy);
|
|
106
418
|
case "object":
|
|
107
|
-
return canonicalizeObjectField(field);
|
|
419
|
+
return canonicalizeObjectField(field, metadataPolicy);
|
|
108
420
|
default: {
|
|
109
421
|
const _exhaustive = field;
|
|
110
422
|
throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);
|
|
111
423
|
}
|
|
112
424
|
}
|
|
113
425
|
}
|
|
114
|
-
function canonicalizeTextField(field) {
|
|
426
|
+
function canonicalizeTextField(field, metadataPolicy) {
|
|
115
427
|
const type = { kind: "primitive", primitiveKind: "string" };
|
|
116
428
|
const constraints = [];
|
|
117
429
|
if (field.minLength !== void 0) {
|
|
@@ -143,13 +455,14 @@ function canonicalizeTextField(field) {
|
|
|
143
455
|
}
|
|
144
456
|
return buildFieldNode(
|
|
145
457
|
field.name,
|
|
458
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
146
459
|
type,
|
|
147
460
|
field.required,
|
|
148
|
-
buildAnnotations(field
|
|
461
|
+
buildAnnotations(getExplicitDisplayName(field), field.placeholder),
|
|
149
462
|
constraints
|
|
150
463
|
);
|
|
151
464
|
}
|
|
152
|
-
function canonicalizeNumberField(field) {
|
|
465
|
+
function canonicalizeNumberField(field, metadataPolicy) {
|
|
153
466
|
const type = { kind: "primitive", primitiveKind: "number" };
|
|
154
467
|
const constraints = [];
|
|
155
468
|
if (field.min !== void 0) {
|
|
@@ -181,17 +494,24 @@ function canonicalizeNumberField(field) {
|
|
|
181
494
|
}
|
|
182
495
|
return buildFieldNode(
|
|
183
496
|
field.name,
|
|
497
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
184
498
|
type,
|
|
185
499
|
field.required,
|
|
186
|
-
buildAnnotations(field
|
|
500
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
187
501
|
constraints
|
|
188
502
|
);
|
|
189
503
|
}
|
|
190
|
-
function canonicalizeBooleanField(field) {
|
|
504
|
+
function canonicalizeBooleanField(field, metadataPolicy) {
|
|
191
505
|
const type = { kind: "primitive", primitiveKind: "boolean" };
|
|
192
|
-
return buildFieldNode(
|
|
506
|
+
return buildFieldNode(
|
|
507
|
+
field.name,
|
|
508
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
509
|
+
type,
|
|
510
|
+
field.required,
|
|
511
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
512
|
+
);
|
|
193
513
|
}
|
|
194
|
-
function canonicalizeStaticEnumField(field) {
|
|
514
|
+
function canonicalizeStaticEnumField(field, metadataPolicy) {
|
|
195
515
|
const members = field.options.map((opt) => {
|
|
196
516
|
if (typeof opt === "string") {
|
|
197
517
|
return { value: opt };
|
|
@@ -199,28 +519,46 @@ function canonicalizeStaticEnumField(field) {
|
|
|
199
519
|
return { value: opt.id, displayName: opt.label };
|
|
200
520
|
});
|
|
201
521
|
const type = { kind: "enum", members };
|
|
202
|
-
return buildFieldNode(
|
|
522
|
+
return buildFieldNode(
|
|
523
|
+
field.name,
|
|
524
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
525
|
+
type,
|
|
526
|
+
field.required,
|
|
527
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
528
|
+
);
|
|
203
529
|
}
|
|
204
|
-
function canonicalizeDynamicEnumField(field) {
|
|
530
|
+
function canonicalizeDynamicEnumField(field, metadataPolicy) {
|
|
205
531
|
const type = {
|
|
206
532
|
kind: "dynamic",
|
|
207
533
|
dynamicKind: "enum",
|
|
208
534
|
sourceKey: field.source,
|
|
209
535
|
parameterFields: field.params ? [...field.params] : []
|
|
210
536
|
};
|
|
211
|
-
return buildFieldNode(
|
|
537
|
+
return buildFieldNode(
|
|
538
|
+
field.name,
|
|
539
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
540
|
+
type,
|
|
541
|
+
field.required,
|
|
542
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
543
|
+
);
|
|
212
544
|
}
|
|
213
|
-
function canonicalizeDynamicSchemaField(field) {
|
|
545
|
+
function canonicalizeDynamicSchemaField(field, metadataPolicy) {
|
|
214
546
|
const type = {
|
|
215
547
|
kind: "dynamic",
|
|
216
548
|
dynamicKind: "schema",
|
|
217
549
|
sourceKey: field.schemaSource,
|
|
218
550
|
parameterFields: []
|
|
219
551
|
};
|
|
220
|
-
return buildFieldNode(
|
|
552
|
+
return buildFieldNode(
|
|
553
|
+
field.name,
|
|
554
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
555
|
+
type,
|
|
556
|
+
field.required,
|
|
557
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
558
|
+
);
|
|
221
559
|
}
|
|
222
|
-
function canonicalizeArrayField(field) {
|
|
223
|
-
const itemProperties = buildObjectProperties(field.items);
|
|
560
|
+
function canonicalizeArrayField(field, metadataPolicy) {
|
|
561
|
+
const itemProperties = buildObjectProperties(field.items, metadataPolicy);
|
|
224
562
|
const itemsType = {
|
|
225
563
|
kind: "object",
|
|
226
564
|
properties: itemProperties,
|
|
@@ -248,37 +586,44 @@ function canonicalizeArrayField(field) {
|
|
|
248
586
|
}
|
|
249
587
|
return buildFieldNode(
|
|
250
588
|
field.name,
|
|
589
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
251
590
|
type,
|
|
252
591
|
field.required,
|
|
253
|
-
buildAnnotations(field
|
|
592
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
254
593
|
constraints
|
|
255
594
|
);
|
|
256
595
|
}
|
|
257
|
-
function canonicalizeObjectField(field) {
|
|
258
|
-
const properties = buildObjectProperties(field.properties);
|
|
596
|
+
function canonicalizeObjectField(field, metadataPolicy) {
|
|
597
|
+
const properties = buildObjectProperties(field.properties, metadataPolicy);
|
|
259
598
|
const type = {
|
|
260
599
|
kind: "object",
|
|
261
600
|
properties,
|
|
262
601
|
additionalProperties: true
|
|
263
602
|
};
|
|
264
|
-
return buildFieldNode(
|
|
603
|
+
return buildFieldNode(
|
|
604
|
+
field.name,
|
|
605
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
606
|
+
type,
|
|
607
|
+
field.required,
|
|
608
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
609
|
+
);
|
|
265
610
|
}
|
|
266
|
-
function canonicalizeGroup(g) {
|
|
611
|
+
function canonicalizeGroup(g, metadataPolicy) {
|
|
267
612
|
return {
|
|
268
613
|
kind: "group",
|
|
269
614
|
label: g.label,
|
|
270
|
-
elements: canonicalizeElements(g.elements),
|
|
615
|
+
elements: canonicalizeElements(g.elements, metadataPolicy),
|
|
271
616
|
provenance: CHAIN_DSL_PROVENANCE
|
|
272
617
|
};
|
|
273
618
|
}
|
|
274
|
-
function canonicalizeConditional(c) {
|
|
619
|
+
function canonicalizeConditional(c, metadataPolicy) {
|
|
275
620
|
return {
|
|
276
621
|
kind: "conditional",
|
|
277
622
|
fieldName: c.field,
|
|
278
623
|
// Conditional values from the chain DSL are JSON-serializable primitives
|
|
279
624
|
// (strings, numbers, booleans) produced by the `is()` predicate helper.
|
|
280
625
|
value: assertJsonValue(c.value),
|
|
281
|
-
elements: canonicalizeElements(c.elements),
|
|
626
|
+
elements: canonicalizeElements(c.elements, metadataPolicy),
|
|
282
627
|
provenance: CHAIN_DSL_PROVENANCE
|
|
283
628
|
};
|
|
284
629
|
}
|
|
@@ -298,10 +643,11 @@ function assertJsonValue(v) {
|
|
|
298
643
|
}
|
|
299
644
|
throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);
|
|
300
645
|
}
|
|
301
|
-
function buildFieldNode(name, type, required, annotations, constraints = []) {
|
|
646
|
+
function buildFieldNode(name, metadata, type, required, annotations, constraints = []) {
|
|
302
647
|
return {
|
|
303
648
|
kind: "field",
|
|
304
649
|
name,
|
|
650
|
+
...metadata !== void 0 && { metadata },
|
|
305
651
|
type,
|
|
306
652
|
required: required === true,
|
|
307
653
|
constraints,
|
|
@@ -331,13 +677,14 @@ function buildAnnotations(label, placeholder) {
|
|
|
331
677
|
}
|
|
332
678
|
return annotations;
|
|
333
679
|
}
|
|
334
|
-
function buildObjectProperties(elements, insideConditional = false) {
|
|
680
|
+
function buildObjectProperties(elements, metadataPolicy, insideConditional = false) {
|
|
335
681
|
const properties = [];
|
|
336
682
|
for (const el of elements) {
|
|
337
683
|
if (isField(el)) {
|
|
338
|
-
const fieldNode = canonicalizeField(el);
|
|
684
|
+
const fieldNode = canonicalizeField(el, metadataPolicy);
|
|
339
685
|
properties.push({
|
|
340
686
|
name: fieldNode.name,
|
|
687
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
341
688
|
type: fieldNode.type,
|
|
342
689
|
// Fields inside a conditional branch are always optional in the
|
|
343
690
|
// data schema, regardless of their `required` flag — the condition
|
|
@@ -348,17 +695,34 @@ function buildObjectProperties(elements, insideConditional = false) {
|
|
|
348
695
|
provenance: CHAIN_DSL_PROVENANCE
|
|
349
696
|
});
|
|
350
697
|
} else if (isGroup(el)) {
|
|
351
|
-
properties.push(...buildObjectProperties(el.elements, insideConditional));
|
|
698
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, insideConditional));
|
|
352
699
|
} else if (isConditional(el)) {
|
|
353
|
-
properties.push(...buildObjectProperties(el.elements, true));
|
|
700
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, true));
|
|
354
701
|
}
|
|
355
702
|
}
|
|
356
703
|
return properties;
|
|
357
704
|
}
|
|
705
|
+
function getExplicitDisplayName(field) {
|
|
706
|
+
if (field.label !== void 0 && field.displayName !== void 0) {
|
|
707
|
+
throw new Error('Chain DSL fields cannot specify both "label" and "displayName".');
|
|
708
|
+
}
|
|
709
|
+
return field.displayName ?? field.label;
|
|
710
|
+
}
|
|
711
|
+
function resolveFieldMetadata(logicalName, field, metadataPolicy) {
|
|
712
|
+
const displayName = getExplicitDisplayName(field);
|
|
713
|
+
return resolveMetadata(
|
|
714
|
+
{
|
|
715
|
+
...field.apiName !== void 0 && { apiName: field.apiName },
|
|
716
|
+
...displayName !== void 0 && { displayName }
|
|
717
|
+
},
|
|
718
|
+
getDeclarationMetadataPolicy(metadataPolicy, "field"),
|
|
719
|
+
makeMetadataContext("chain-dsl", "field", logicalName)
|
|
720
|
+
);
|
|
721
|
+
}
|
|
358
722
|
|
|
359
723
|
// src/canonicalize/tsdoc-canonicalizer.ts
|
|
360
724
|
var import_internals2 = require("@formspec/core/internals");
|
|
361
|
-
function canonicalizeTSDoc(analysis, source) {
|
|
725
|
+
function canonicalizeTSDoc(analysis, source, options) {
|
|
362
726
|
const file = source?.file ?? "";
|
|
363
727
|
const provenance = {
|
|
364
728
|
surface: "tsdoc",
|
|
@@ -367,15 +731,21 @@ function canonicalizeTSDoc(analysis, source) {
|
|
|
367
731
|
column: 0
|
|
368
732
|
};
|
|
369
733
|
const elements = assembleElements(analysis.fields, analysis.fieldLayouts, provenance);
|
|
370
|
-
|
|
734
|
+
const ir = {
|
|
371
735
|
kind: "form-ir",
|
|
736
|
+
name: analysis.name,
|
|
372
737
|
irVersion: import_internals2.IR_VERSION,
|
|
373
738
|
elements,
|
|
739
|
+
...analysis.metadata !== void 0 && { metadata: analysis.metadata },
|
|
374
740
|
typeRegistry: analysis.typeRegistry,
|
|
375
741
|
...analysis.annotations !== void 0 && analysis.annotations.length > 0 && { rootAnnotations: analysis.annotations },
|
|
376
742
|
...analysis.annotations !== void 0 && analysis.annotations.length > 0 && { annotations: analysis.annotations },
|
|
377
743
|
provenance
|
|
378
744
|
};
|
|
745
|
+
return resolveFormIRMetadata(ir, {
|
|
746
|
+
policy: normalizeMetadataPolicy(options?.metadata),
|
|
747
|
+
surface: "tsdoc"
|
|
748
|
+
});
|
|
379
749
|
}
|
|
380
750
|
function assembleElements(fields, layouts, provenance) {
|
|
381
751
|
const elements = [];
|
|
@@ -432,6 +802,120 @@ function wrapInConditional(field, layout, provenance) {
|
|
|
432
802
|
return conditional;
|
|
433
803
|
}
|
|
434
804
|
|
|
805
|
+
// src/metadata/collision-guards.ts
|
|
806
|
+
function assertUniqueSerializedNames(entries, scope) {
|
|
807
|
+
const seen = /* @__PURE__ */ new Map();
|
|
808
|
+
for (const entry of entries) {
|
|
809
|
+
const previous = seen.get(entry.serializedName);
|
|
810
|
+
if (previous !== void 0) {
|
|
811
|
+
if (previous.logicalName === entry.logicalName && previous.category === entry.category) {
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
throw new Error(
|
|
815
|
+
`Serialized name collision in ${scope}: ${previous.category} "${previous.logicalName}" and ${entry.category} "${entry.logicalName}" both resolve to "${entry.serializedName}".`
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
seen.set(entry.serializedName, entry);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
function collectFlattenedFields(elements) {
|
|
822
|
+
const fields = [];
|
|
823
|
+
for (const element of elements) {
|
|
824
|
+
switch (element.kind) {
|
|
825
|
+
case "field":
|
|
826
|
+
fields.push(element);
|
|
827
|
+
break;
|
|
828
|
+
case "group":
|
|
829
|
+
case "conditional":
|
|
830
|
+
fields.push(...collectFlattenedFields(element.elements));
|
|
831
|
+
break;
|
|
832
|
+
default: {
|
|
833
|
+
const exhaustive = element;
|
|
834
|
+
void exhaustive;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return fields;
|
|
839
|
+
}
|
|
840
|
+
function validateObjectProperties(properties, scope) {
|
|
841
|
+
assertUniqueSerializedNames(
|
|
842
|
+
properties.map((property) => ({
|
|
843
|
+
logicalName: property.name,
|
|
844
|
+
serializedName: getSerializedName(property.name, property.metadata),
|
|
845
|
+
category: "object property"
|
|
846
|
+
})),
|
|
847
|
+
scope
|
|
848
|
+
);
|
|
849
|
+
for (const property of properties) {
|
|
850
|
+
validateTypeNode(
|
|
851
|
+
property.type,
|
|
852
|
+
`${scope}.${getSerializedName(property.name, property.metadata)}`
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
function validateTypeNode(type, scope) {
|
|
857
|
+
switch (type.kind) {
|
|
858
|
+
case "array":
|
|
859
|
+
validateTypeNode(type.items, `${scope}[]`);
|
|
860
|
+
break;
|
|
861
|
+
case "object":
|
|
862
|
+
validateObjectProperties(type.properties, scope);
|
|
863
|
+
break;
|
|
864
|
+
case "record":
|
|
865
|
+
validateTypeNode(type.valueType, `${scope}.*`);
|
|
866
|
+
break;
|
|
867
|
+
case "union":
|
|
868
|
+
type.members.forEach((member, index) => {
|
|
869
|
+
validateTypeNode(member, `${scope}|${String(index)}`);
|
|
870
|
+
});
|
|
871
|
+
break;
|
|
872
|
+
case "reference":
|
|
873
|
+
case "primitive":
|
|
874
|
+
case "enum":
|
|
875
|
+
case "dynamic":
|
|
876
|
+
case "custom":
|
|
877
|
+
break;
|
|
878
|
+
default: {
|
|
879
|
+
const exhaustive = type;
|
|
880
|
+
void exhaustive;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function validateTypeDefinitions(typeRegistry) {
|
|
885
|
+
const definitions = Object.values(typeRegistry);
|
|
886
|
+
assertUniqueSerializedNames(
|
|
887
|
+
definitions.map((definition) => ({
|
|
888
|
+
logicalName: definition.name,
|
|
889
|
+
serializedName: getSerializedName(definition.name, definition.metadata),
|
|
890
|
+
category: "type definition"
|
|
891
|
+
})),
|
|
892
|
+
"$defs"
|
|
893
|
+
);
|
|
894
|
+
for (const definition of definitions) {
|
|
895
|
+
validateTypeDefinition(definition);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
function validateTypeDefinition(definition) {
|
|
899
|
+
validateTypeNode(
|
|
900
|
+
definition.type,
|
|
901
|
+
`type "${getSerializedName(definition.name, definition.metadata)}"`
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
function assertNoSerializedNameCollisions(ir) {
|
|
905
|
+
assertUniqueSerializedNames(
|
|
906
|
+
collectFlattenedFields(ir.elements).map((field) => ({
|
|
907
|
+
logicalName: field.name,
|
|
908
|
+
serializedName: getSerializedName(field.name, field.metadata),
|
|
909
|
+
category: "field"
|
|
910
|
+
})),
|
|
911
|
+
"form root"
|
|
912
|
+
);
|
|
913
|
+
for (const field of collectFlattenedFields(ir.elements)) {
|
|
914
|
+
validateTypeNode(field.type, `field "${getSerializedName(field.name, field.metadata)}"`);
|
|
915
|
+
}
|
|
916
|
+
validateTypeDefinitions(ir.typeRegistry);
|
|
917
|
+
}
|
|
918
|
+
|
|
435
919
|
// src/json-schema/ir-generator.ts
|
|
436
920
|
function makeContext(options) {
|
|
437
921
|
const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
|
|
@@ -442,19 +926,33 @@ function makeContext(options) {
|
|
|
442
926
|
}
|
|
443
927
|
return {
|
|
444
928
|
defs: {},
|
|
929
|
+
typeNameMap: {},
|
|
930
|
+
typeRegistry: {},
|
|
445
931
|
extensionRegistry: options?.extensionRegistry,
|
|
446
932
|
vendorPrefix
|
|
447
933
|
};
|
|
448
934
|
}
|
|
449
935
|
function generateJsonSchemaFromIR(ir, options) {
|
|
450
|
-
|
|
936
|
+
assertNoSerializedNameCollisions(ir);
|
|
937
|
+
const ctx = {
|
|
938
|
+
...makeContext(options),
|
|
939
|
+
typeRegistry: ir.typeRegistry,
|
|
940
|
+
typeNameMap: Object.fromEntries(
|
|
941
|
+
Object.entries(ir.typeRegistry).map(([name, typeDef]) => [
|
|
942
|
+
name,
|
|
943
|
+
getSerializedName(name, typeDef.metadata)
|
|
944
|
+
])
|
|
945
|
+
)
|
|
946
|
+
};
|
|
451
947
|
for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {
|
|
452
|
-
ctx.
|
|
948
|
+
const schemaName = ctx.typeNameMap[name] ?? name;
|
|
949
|
+
ctx.defs[schemaName] = generateTypeNode(typeDef.type, ctx);
|
|
950
|
+
applyResolvedMetadata(ctx.defs[schemaName], typeDef.metadata);
|
|
453
951
|
if (typeDef.constraints && typeDef.constraints.length > 0) {
|
|
454
|
-
applyConstraints(ctx.defs[
|
|
952
|
+
applyConstraints(ctx.defs[schemaName], typeDef.constraints, ctx);
|
|
455
953
|
}
|
|
456
954
|
if (typeDef.annotations && typeDef.annotations.length > 0) {
|
|
457
|
-
applyAnnotations(ctx.defs[
|
|
955
|
+
applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx);
|
|
458
956
|
}
|
|
459
957
|
}
|
|
460
958
|
const properties = {};
|
|
@@ -467,6 +965,7 @@ function generateJsonSchemaFromIR(ir, options) {
|
|
|
467
965
|
properties,
|
|
468
966
|
...uniqueRequired.length > 0 && { required: uniqueRequired }
|
|
469
967
|
};
|
|
968
|
+
applyResolvedMetadata(result, ir.metadata);
|
|
470
969
|
if (ir.annotations && ir.annotations.length > 0) {
|
|
471
970
|
applyAnnotations(result, ir.annotations, ctx);
|
|
472
971
|
}
|
|
@@ -479,9 +978,9 @@ function collectFields(elements, properties, required, ctx) {
|
|
|
479
978
|
for (const element of elements) {
|
|
480
979
|
switch (element.kind) {
|
|
481
980
|
case "field":
|
|
482
|
-
properties[element.name] = generateFieldSchema(element, ctx);
|
|
981
|
+
properties[getSerializedName(element.name, element.metadata)] = generateFieldSchema(element, ctx);
|
|
483
982
|
if (element.required) {
|
|
484
|
-
required.push(element.name);
|
|
983
|
+
required.push(getSerializedName(element.name, element.metadata));
|
|
485
984
|
}
|
|
486
985
|
break;
|
|
487
986
|
case "group":
|
|
@@ -525,6 +1024,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
525
1024
|
rootAnnotations.push(annotation);
|
|
526
1025
|
}
|
|
527
1026
|
}
|
|
1027
|
+
applyResolvedMetadata(schema, field.metadata);
|
|
528
1028
|
applyAnnotations(schema, rootAnnotations, ctx);
|
|
529
1029
|
if (itemStringSchema !== void 0) {
|
|
530
1030
|
applyAnnotations(itemStringSchema, itemAnnotations, ctx);
|
|
@@ -532,7 +1032,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
532
1032
|
if (pathConstraints.length === 0) {
|
|
533
1033
|
return schema;
|
|
534
1034
|
}
|
|
535
|
-
return applyPathTargetedConstraints(schema, pathConstraints, ctx);
|
|
1035
|
+
return applyPathTargetedConstraints(schema, pathConstraints, ctx, field.type);
|
|
536
1036
|
}
|
|
537
1037
|
function isStringItemConstraint(constraint) {
|
|
538
1038
|
switch (constraint.constraintKind) {
|
|
@@ -544,9 +1044,11 @@ function isStringItemConstraint(constraint) {
|
|
|
544
1044
|
return false;
|
|
545
1045
|
}
|
|
546
1046
|
}
|
|
547
|
-
function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
1047
|
+
function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
|
|
548
1048
|
if (schema.type === "array" && schema.items) {
|
|
549
|
-
|
|
1049
|
+
const referencedType = typeNode?.kind === "reference" ? resolveReferencedType(typeNode, ctx) : void 0;
|
|
1050
|
+
const nestedType = typeNode?.kind === "array" ? typeNode.items : referencedType?.kind === "array" ? referencedType.items : void 0;
|
|
1051
|
+
schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx, nestedType);
|
|
550
1052
|
return schema;
|
|
551
1053
|
}
|
|
552
1054
|
const byTarget = /* @__PURE__ */ new Map();
|
|
@@ -561,7 +1063,7 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
|
561
1063
|
for (const [target, constraints] of byTarget) {
|
|
562
1064
|
const subSchema = {};
|
|
563
1065
|
applyConstraints(subSchema, constraints, ctx);
|
|
564
|
-
propertyOverrides[target] = subSchema;
|
|
1066
|
+
propertyOverrides[resolveSerializedPropertyName(target, typeNode, ctx)] = subSchema;
|
|
565
1067
|
}
|
|
566
1068
|
if (schema.$ref) {
|
|
567
1069
|
const { $ref, ...rest } = schema;
|
|
@@ -609,7 +1111,7 @@ function generateTypeNode(type, ctx) {
|
|
|
609
1111
|
case "union":
|
|
610
1112
|
return generateUnionType(type, ctx);
|
|
611
1113
|
case "reference":
|
|
612
|
-
return generateReferenceType(type);
|
|
1114
|
+
return generateReferenceType(type, ctx);
|
|
613
1115
|
case "dynamic":
|
|
614
1116
|
return generateDynamicType(type);
|
|
615
1117
|
case "custom":
|
|
@@ -650,9 +1152,10 @@ function generateObjectType(type, ctx) {
|
|
|
650
1152
|
const properties = {};
|
|
651
1153
|
const required = [];
|
|
652
1154
|
for (const prop of type.properties) {
|
|
653
|
-
|
|
1155
|
+
const propertyName = getSerializedName(prop.name, prop.metadata);
|
|
1156
|
+
properties[propertyName] = generatePropertySchema(prop, ctx);
|
|
654
1157
|
if (!prop.optional) {
|
|
655
|
-
required.push(
|
|
1158
|
+
required.push(propertyName);
|
|
656
1159
|
}
|
|
657
1160
|
}
|
|
658
1161
|
const schema = { type: "object", properties };
|
|
@@ -673,6 +1176,7 @@ function generateRecordType(type, ctx) {
|
|
|
673
1176
|
function generatePropertySchema(prop, ctx) {
|
|
674
1177
|
const schema = generateTypeNode(prop.type, ctx);
|
|
675
1178
|
applyConstraints(schema, prop.constraints, ctx);
|
|
1179
|
+
applyResolvedMetadata(schema, prop.metadata);
|
|
676
1180
|
applyAnnotations(schema, prop.annotations, ctx);
|
|
677
1181
|
return schema;
|
|
678
1182
|
}
|
|
@@ -701,8 +1205,28 @@ function isNullableUnion(type) {
|
|
|
701
1205
|
).length;
|
|
702
1206
|
return nullCount === 1;
|
|
703
1207
|
}
|
|
704
|
-
function generateReferenceType(type) {
|
|
705
|
-
return { $ref: `#/$defs/${type.name}` };
|
|
1208
|
+
function generateReferenceType(type, ctx) {
|
|
1209
|
+
return { $ref: `#/$defs/${ctx.typeNameMap[type.name] ?? type.name}` };
|
|
1210
|
+
}
|
|
1211
|
+
function applyResolvedMetadata(schema, metadata) {
|
|
1212
|
+
const displayName = getDisplayName(metadata);
|
|
1213
|
+
if (displayName !== void 0) {
|
|
1214
|
+
schema.title = displayName;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
function resolveReferencedType(type, ctx) {
|
|
1218
|
+
return ctx.typeRegistry[type.name]?.type;
|
|
1219
|
+
}
|
|
1220
|
+
function resolveSerializedPropertyName(logicalName, typeNode, ctx) {
|
|
1221
|
+
if (typeNode?.kind === "object") {
|
|
1222
|
+
const property = typeNode.properties.find((candidate) => candidate.name === logicalName);
|
|
1223
|
+
return property === void 0 ? logicalName : getSerializedName(property.name, property.metadata);
|
|
1224
|
+
}
|
|
1225
|
+
if (typeNode?.kind === "reference") {
|
|
1226
|
+
const referencedType = resolveReferencedType(typeNode, ctx);
|
|
1227
|
+
return referencedType === void 0 ? logicalName : resolveSerializedPropertyName(logicalName, referencedType, ctx);
|
|
1228
|
+
}
|
|
1229
|
+
return logicalName;
|
|
706
1230
|
}
|
|
707
1231
|
function generateDynamicType(type) {
|
|
708
1232
|
if (type.dynamicKind === "enum") {
|
|
@@ -782,7 +1306,7 @@ function applyAnnotations(schema, annotations, ctx) {
|
|
|
782
1306
|
for (const annotation of annotations) {
|
|
783
1307
|
switch (annotation.annotationKind) {
|
|
784
1308
|
case "displayName":
|
|
785
|
-
schema.title
|
|
1309
|
+
schema.title ??= annotation.value;
|
|
786
1310
|
break;
|
|
787
1311
|
case "description":
|
|
788
1312
|
schema.description = annotation.value;
|
|
@@ -869,7 +1393,10 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
|
|
|
869
1393
|
|
|
870
1394
|
// src/json-schema/generator.ts
|
|
871
1395
|
function generateJsonSchema(form, options) {
|
|
872
|
-
const ir = canonicalizeChainDSL(
|
|
1396
|
+
const ir = canonicalizeChainDSL(
|
|
1397
|
+
form,
|
|
1398
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1399
|
+
);
|
|
873
1400
|
const internalOptions = options?.vendorPrefix === void 0 ? void 0 : { vendorPrefix: options.vendorPrefix };
|
|
874
1401
|
return generateJsonSchemaFromIR(ir, internalOptions);
|
|
875
1402
|
}
|
|
@@ -1039,13 +1566,21 @@ function combineRules(parentRule, childRule) {
|
|
|
1039
1566
|
}
|
|
1040
1567
|
};
|
|
1041
1568
|
}
|
|
1042
|
-
function
|
|
1043
|
-
const
|
|
1569
|
+
function getFieldDisplayName(field) {
|
|
1570
|
+
const resolvedDisplayName = getDisplayName(field.metadata);
|
|
1571
|
+
if (resolvedDisplayName !== void 0) {
|
|
1572
|
+
return resolvedDisplayName;
|
|
1573
|
+
}
|
|
1574
|
+
return field.annotations.find((annotation) => annotation.annotationKind === "displayName")?.value;
|
|
1575
|
+
}
|
|
1576
|
+
function fieldNodeToControl(field, fieldNameMap, parentRule) {
|
|
1044
1577
|
const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === "placeholder");
|
|
1578
|
+
const serializedName = fieldNameMap.get(field.name) ?? getSerializedName(field.name, field.metadata);
|
|
1579
|
+
const displayName = getFieldDisplayName(field);
|
|
1045
1580
|
const control = {
|
|
1046
1581
|
type: "Control",
|
|
1047
|
-
scope: fieldToScope(
|
|
1048
|
-
...
|
|
1582
|
+
scope: fieldToScope(serializedName),
|
|
1583
|
+
...displayName !== void 0 && { label: displayName },
|
|
1049
1584
|
...placeholderAnnotation !== void 0 && {
|
|
1050
1585
|
options: { placeholder: placeholderAnnotation.value }
|
|
1051
1586
|
},
|
|
@@ -1053,30 +1588,30 @@ function fieldNodeToControl(field, parentRule) {
|
|
|
1053
1588
|
};
|
|
1054
1589
|
return control;
|
|
1055
1590
|
}
|
|
1056
|
-
function groupNodeToLayout(group, parentRule) {
|
|
1591
|
+
function groupNodeToLayout(group, fieldNameMap, parentRule) {
|
|
1057
1592
|
return {
|
|
1058
1593
|
type: "Group",
|
|
1059
1594
|
label: group.label,
|
|
1060
|
-
elements: irElementsToUiSchema(group.elements, parentRule),
|
|
1595
|
+
elements: irElementsToUiSchema(group.elements, fieldNameMap, parentRule),
|
|
1061
1596
|
...parentRule !== void 0 && { rule: parentRule }
|
|
1062
1597
|
};
|
|
1063
1598
|
}
|
|
1064
|
-
function irElementsToUiSchema(elements, parentRule) {
|
|
1599
|
+
function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
1065
1600
|
const result = [];
|
|
1066
1601
|
for (const element of elements) {
|
|
1067
1602
|
switch (element.kind) {
|
|
1068
1603
|
case "field": {
|
|
1069
|
-
result.push(fieldNodeToControl(element, parentRule));
|
|
1604
|
+
result.push(fieldNodeToControl(element, fieldNameMap, parentRule));
|
|
1070
1605
|
break;
|
|
1071
1606
|
}
|
|
1072
1607
|
case "group": {
|
|
1073
|
-
result.push(groupNodeToLayout(element, parentRule));
|
|
1608
|
+
result.push(groupNodeToLayout(element, fieldNameMap, parentRule));
|
|
1074
1609
|
break;
|
|
1075
1610
|
}
|
|
1076
1611
|
case "conditional": {
|
|
1077
|
-
const newRule = createShowRule(element.fieldName, element.value);
|
|
1612
|
+
const newRule = createShowRule(fieldNameMap.get(element.fieldName) ?? element.fieldName, element.value);
|
|
1078
1613
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
1079
|
-
const childElements = irElementsToUiSchema(element.elements, combinedRule);
|
|
1614
|
+
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
1080
1615
|
result.push(...childElements);
|
|
1081
1616
|
break;
|
|
1082
1617
|
}
|
|
@@ -1090,16 +1625,42 @@ function irElementsToUiSchema(elements, parentRule) {
|
|
|
1090
1625
|
return result;
|
|
1091
1626
|
}
|
|
1092
1627
|
function generateUiSchemaFromIR(ir) {
|
|
1628
|
+
assertNoSerializedNameCollisions(ir);
|
|
1629
|
+
const fieldNameMap = collectFieldNameMap(ir.elements);
|
|
1093
1630
|
const result = {
|
|
1094
1631
|
type: "VerticalLayout",
|
|
1095
|
-
elements: irElementsToUiSchema(ir.elements)
|
|
1632
|
+
elements: irElementsToUiSchema(ir.elements, fieldNameMap)
|
|
1096
1633
|
};
|
|
1097
1634
|
return parseOrThrow(uiSchema, result, "UI Schema");
|
|
1098
1635
|
}
|
|
1636
|
+
function collectFieldNameMap(elements) {
|
|
1637
|
+
const map = /* @__PURE__ */ new Map();
|
|
1638
|
+
for (const element of elements) {
|
|
1639
|
+
switch (element.kind) {
|
|
1640
|
+
case "field":
|
|
1641
|
+
map.set(element.name, getSerializedName(element.name, element.metadata));
|
|
1642
|
+
break;
|
|
1643
|
+
case "group":
|
|
1644
|
+
case "conditional":
|
|
1645
|
+
for (const [key, value] of collectFieldNameMap(element.elements)) {
|
|
1646
|
+
map.set(key, value);
|
|
1647
|
+
}
|
|
1648
|
+
break;
|
|
1649
|
+
default: {
|
|
1650
|
+
const _exhaustive = element;
|
|
1651
|
+
void _exhaustive;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
return map;
|
|
1656
|
+
}
|
|
1099
1657
|
|
|
1100
1658
|
// src/ui-schema/generator.ts
|
|
1101
|
-
function generateUiSchema(form) {
|
|
1102
|
-
const ir = canonicalizeChainDSL(
|
|
1659
|
+
function generateUiSchema(form, options) {
|
|
1660
|
+
const ir = canonicalizeChainDSL(
|
|
1661
|
+
form,
|
|
1662
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1663
|
+
);
|
|
1103
1664
|
return generateUiSchemaFromIR(ir);
|
|
1104
1665
|
}
|
|
1105
1666
|
|
|
@@ -2136,7 +2697,76 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
|
|
|
2136
2697
|
...hostType !== void 0 && { hostType }
|
|
2137
2698
|
};
|
|
2138
2699
|
}
|
|
2139
|
-
function
|
|
2700
|
+
function makeExplicitScalarMetadata(value) {
|
|
2701
|
+
return value === void 0 || value === "" ? void 0 : { value, source: "explicit" };
|
|
2702
|
+
}
|
|
2703
|
+
function extractExplicitMetadata(node) {
|
|
2704
|
+
let apiName;
|
|
2705
|
+
let displayName;
|
|
2706
|
+
let apiNamePlural;
|
|
2707
|
+
let displayNamePlural;
|
|
2708
|
+
for (const tag of getLeadingParsedTags(node)) {
|
|
2709
|
+
const value = tag.argumentText.trim();
|
|
2710
|
+
if (value === "") {
|
|
2711
|
+
continue;
|
|
2712
|
+
}
|
|
2713
|
+
if (tag.normalizedTagName === "apiName") {
|
|
2714
|
+
if (tag.target === null) {
|
|
2715
|
+
apiName ??= value;
|
|
2716
|
+
} else if (tag.target.kind === "variant") {
|
|
2717
|
+
if (tag.target.rawText === "singular") {
|
|
2718
|
+
apiName ??= value;
|
|
2719
|
+
} else if (tag.target.rawText === "plural") {
|
|
2720
|
+
apiNamePlural ??= value;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
continue;
|
|
2724
|
+
}
|
|
2725
|
+
if (tag.normalizedTagName === "displayName") {
|
|
2726
|
+
if (tag.target === null) {
|
|
2727
|
+
displayName ??= value;
|
|
2728
|
+
} else if (tag.target.kind === "variant") {
|
|
2729
|
+
if (tag.target.rawText === "singular") {
|
|
2730
|
+
displayName ??= value;
|
|
2731
|
+
} else if (tag.target.rawText === "plural") {
|
|
2732
|
+
displayNamePlural ??= value;
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
const resolvedApiName = makeExplicitScalarMetadata(apiName);
|
|
2738
|
+
const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
|
|
2739
|
+
const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
|
|
2740
|
+
const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
|
|
2741
|
+
const metadata = {
|
|
2742
|
+
...resolvedApiName !== void 0 && { apiName: resolvedApiName },
|
|
2743
|
+
...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
|
|
2744
|
+
...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
|
|
2745
|
+
...resolvedDisplayNamePlural !== void 0 && {
|
|
2746
|
+
displayNamePlural: resolvedDisplayNamePlural
|
|
2747
|
+
}
|
|
2748
|
+
};
|
|
2749
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
2750
|
+
}
|
|
2751
|
+
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
|
|
2752
|
+
const explicit = extractExplicitMetadata(node);
|
|
2753
|
+
return resolveMetadata(
|
|
2754
|
+
{
|
|
2755
|
+
...explicit?.apiName !== void 0 && { apiName: explicit.apiName.value },
|
|
2756
|
+
...explicit?.displayName !== void 0 && { displayName: explicit.displayName.value },
|
|
2757
|
+
...explicit?.apiNamePlural !== void 0 && {
|
|
2758
|
+
apiNamePlural: explicit.apiNamePlural.value
|
|
2759
|
+
},
|
|
2760
|
+
...explicit?.displayNamePlural !== void 0 && {
|
|
2761
|
+
displayNamePlural: explicit.displayNamePlural.value
|
|
2762
|
+
}
|
|
2763
|
+
},
|
|
2764
|
+
getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
|
|
2765
|
+
makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
|
|
2766
|
+
);
|
|
2767
|
+
}
|
|
2768
|
+
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2769
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2140
2770
|
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
2141
2771
|
const fields = [];
|
|
2142
2772
|
const fieldLayouts = [];
|
|
@@ -2163,6 +2793,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2163
2793
|
visiting,
|
|
2164
2794
|
diagnostics,
|
|
2165
2795
|
classType,
|
|
2796
|
+
normalizedMetadataPolicy,
|
|
2166
2797
|
extensionRegistry
|
|
2167
2798
|
);
|
|
2168
2799
|
if (fieldNode) {
|
|
@@ -2187,10 +2818,18 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2187
2818
|
classType,
|
|
2188
2819
|
checker,
|
|
2189
2820
|
file,
|
|
2190
|
-
diagnostics
|
|
2821
|
+
diagnostics,
|
|
2822
|
+
normalizedMetadataPolicy
|
|
2191
2823
|
);
|
|
2824
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, classDecl, {
|
|
2825
|
+
checker,
|
|
2826
|
+
declaration: classDecl,
|
|
2827
|
+
subjectType: classType,
|
|
2828
|
+
hostType: classType
|
|
2829
|
+
});
|
|
2192
2830
|
return {
|
|
2193
2831
|
name,
|
|
2832
|
+
...metadata !== void 0 && { metadata },
|
|
2194
2833
|
fields: specializedFields,
|
|
2195
2834
|
fieldLayouts,
|
|
2196
2835
|
typeRegistry,
|
|
@@ -2200,7 +2839,8 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2200
2839
|
staticMethods
|
|
2201
2840
|
};
|
|
2202
2841
|
}
|
|
2203
|
-
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry) {
|
|
2842
|
+
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2843
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2204
2844
|
const name = interfaceDecl.name.text;
|
|
2205
2845
|
const fields = [];
|
|
2206
2846
|
const typeRegistry = {};
|
|
@@ -2224,6 +2864,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2224
2864
|
visiting,
|
|
2225
2865
|
diagnostics,
|
|
2226
2866
|
interfaceType,
|
|
2867
|
+
normalizedMetadataPolicy,
|
|
2227
2868
|
extensionRegistry
|
|
2228
2869
|
);
|
|
2229
2870
|
if (fieldNode) {
|
|
@@ -2237,11 +2878,19 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2237
2878
|
interfaceType,
|
|
2238
2879
|
checker,
|
|
2239
2880
|
file,
|
|
2240
|
-
diagnostics
|
|
2881
|
+
diagnostics,
|
|
2882
|
+
normalizedMetadataPolicy
|
|
2241
2883
|
);
|
|
2242
2884
|
const fieldLayouts = specializedFields.map(() => ({}));
|
|
2885
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, interfaceDecl, {
|
|
2886
|
+
checker,
|
|
2887
|
+
declaration: interfaceDecl,
|
|
2888
|
+
subjectType: interfaceType,
|
|
2889
|
+
hostType: interfaceType
|
|
2890
|
+
});
|
|
2243
2891
|
return {
|
|
2244
2892
|
name,
|
|
2893
|
+
...metadata !== void 0 && { metadata },
|
|
2245
2894
|
fields: specializedFields,
|
|
2246
2895
|
fieldLayouts,
|
|
2247
2896
|
typeRegistry,
|
|
@@ -2251,7 +2900,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2251
2900
|
staticMethods: []
|
|
2252
2901
|
};
|
|
2253
2902
|
}
|
|
2254
|
-
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry) {
|
|
2903
|
+
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2255
2904
|
if (!ts3.isTypeLiteralNode(typeAlias.type)) {
|
|
2256
2905
|
const sourceFile = typeAlias.getSourceFile();
|
|
2257
2906
|
const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
|
|
@@ -2261,6 +2910,8 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2261
2910
|
error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`
|
|
2262
2911
|
};
|
|
2263
2912
|
}
|
|
2913
|
+
const typeLiteral = typeAlias.type;
|
|
2914
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2264
2915
|
const name = typeAlias.name.text;
|
|
2265
2916
|
const fields = [];
|
|
2266
2917
|
const typeRegistry = {};
|
|
@@ -2274,7 +2925,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2274
2925
|
const annotations = [...typeAliasDoc.annotations];
|
|
2275
2926
|
diagnostics.push(...typeAliasDoc.diagnostics);
|
|
2276
2927
|
const visiting = /* @__PURE__ */ new Set();
|
|
2277
|
-
for (const member of
|
|
2928
|
+
for (const member of typeLiteral.members) {
|
|
2278
2929
|
if (ts3.isPropertySignature(member)) {
|
|
2279
2930
|
const fieldNode = analyzeInterfacePropertyToIR(
|
|
2280
2931
|
member,
|
|
@@ -2284,6 +2935,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2284
2935
|
visiting,
|
|
2285
2936
|
diagnostics,
|
|
2286
2937
|
aliasType,
|
|
2938
|
+
normalizedMetadataPolicy,
|
|
2287
2939
|
extensionRegistry
|
|
2288
2940
|
);
|
|
2289
2941
|
if (fieldNode) {
|
|
@@ -2297,12 +2949,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2297
2949
|
aliasType,
|
|
2298
2950
|
checker,
|
|
2299
2951
|
file,
|
|
2300
|
-
diagnostics
|
|
2952
|
+
diagnostics,
|
|
2953
|
+
normalizedMetadataPolicy
|
|
2301
2954
|
);
|
|
2955
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, typeAlias, {
|
|
2956
|
+
checker,
|
|
2957
|
+
declaration: typeAlias,
|
|
2958
|
+
subjectType: aliasType,
|
|
2959
|
+
hostType: aliasType
|
|
2960
|
+
});
|
|
2302
2961
|
return {
|
|
2303
2962
|
ok: true,
|
|
2304
2963
|
analysis: {
|
|
2305
2964
|
name,
|
|
2965
|
+
...metadata !== void 0 && { metadata },
|
|
2306
2966
|
fields: specializedFields,
|
|
2307
2967
|
fieldLayouts: specializedFields.map(() => ({})),
|
|
2308
2968
|
typeRegistry,
|
|
@@ -2342,31 +3002,20 @@ function getLeadingParsedTags(node) {
|
|
|
2342
3002
|
}
|
|
2343
3003
|
return parsedTags;
|
|
2344
3004
|
}
|
|
2345
|
-
function
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
return member;
|
|
2350
|
-
}
|
|
2351
|
-
}
|
|
2352
|
-
return null;
|
|
2353
|
-
}
|
|
2354
|
-
if (ts3.isInterfaceDeclaration(node)) {
|
|
2355
|
-
for (const member of node.members) {
|
|
2356
|
-
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2357
|
-
return member;
|
|
2358
|
-
}
|
|
2359
|
-
}
|
|
3005
|
+
function resolveDiscriminatorProperty(node, checker, fieldName) {
|
|
3006
|
+
const subjectType = checker.getTypeAtLocation(node);
|
|
3007
|
+
const propertySymbol = subjectType.getProperty(fieldName);
|
|
3008
|
+
if (propertySymbol === void 0) {
|
|
2360
3009
|
return null;
|
|
2361
3010
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
3011
|
+
const declaration = propertySymbol.valueDeclaration ?? propertySymbol.declarations?.find(
|
|
3012
|
+
(candidate) => ts3.isPropertyDeclaration(candidate) || ts3.isPropertySignature(candidate)
|
|
3013
|
+
) ?? propertySymbol.declarations?.[0];
|
|
3014
|
+
return {
|
|
3015
|
+
declaration,
|
|
3016
|
+
type: checker.getTypeOfSymbolAtLocation(propertySymbol, declaration ?? node),
|
|
3017
|
+
optional: !!(propertySymbol.flags & ts3.SymbolFlags.Optional) || declaration !== void 0 && "questionToken" in declaration && declaration.questionToken !== void 0
|
|
3018
|
+
};
|
|
2370
3019
|
}
|
|
2371
3020
|
function isLocalTypeParameterName(node, typeParameterName) {
|
|
2372
3021
|
return node.typeParameters?.some((typeParameter) => typeParameter.name.text === typeParameterName) ?? false;
|
|
@@ -2459,8 +3108,8 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
|
2459
3108
|
);
|
|
2460
3109
|
return null;
|
|
2461
3110
|
}
|
|
2462
|
-
const
|
|
2463
|
-
if (
|
|
3111
|
+
const property = resolveDiscriminatorProperty(node, checker, directive.fieldName);
|
|
3112
|
+
if (property === null) {
|
|
2464
3113
|
diagnostics.push(
|
|
2465
3114
|
makeAnalysisDiagnostic(
|
|
2466
3115
|
"UNKNOWN_PATH_TARGET",
|
|
@@ -2470,36 +3119,35 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
|
2470
3119
|
);
|
|
2471
3120
|
return null;
|
|
2472
3121
|
}
|
|
2473
|
-
if (
|
|
3122
|
+
if (property.optional) {
|
|
2474
3123
|
diagnostics.push(
|
|
2475
3124
|
makeAnalysisDiagnostic(
|
|
2476
3125
|
"TYPE_MISMATCH",
|
|
2477
3126
|
`Discriminator field "${directive.fieldName}" must be required; optional discriminator fields are not supported.`,
|
|
2478
3127
|
directive.provenance,
|
|
2479
|
-
[provenanceForNode(
|
|
3128
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2480
3129
|
)
|
|
2481
3130
|
);
|
|
2482
3131
|
return null;
|
|
2483
3132
|
}
|
|
2484
|
-
|
|
2485
|
-
if (isNullishSemanticType(propertyType)) {
|
|
3133
|
+
if (isNullishSemanticType(property.type)) {
|
|
2486
3134
|
diagnostics.push(
|
|
2487
3135
|
makeAnalysisDiagnostic(
|
|
2488
3136
|
"TYPE_MISMATCH",
|
|
2489
3137
|
`Discriminator field "${directive.fieldName}" must not be nullable.`,
|
|
2490
3138
|
directive.provenance,
|
|
2491
|
-
[provenanceForNode(
|
|
3139
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2492
3140
|
)
|
|
2493
3141
|
);
|
|
2494
3142
|
return null;
|
|
2495
3143
|
}
|
|
2496
|
-
if (!isStringLikeSemanticType(
|
|
3144
|
+
if (!isStringLikeSemanticType(property.type)) {
|
|
2497
3145
|
diagnostics.push(
|
|
2498
3146
|
makeAnalysisDiagnostic(
|
|
2499
3147
|
"TYPE_MISMATCH",
|
|
2500
3148
|
`Discriminator field "${directive.fieldName}" must be string-like.`,
|
|
2501
3149
|
directive.provenance,
|
|
2502
|
-
[provenanceForNode(
|
|
3150
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2503
3151
|
)
|
|
2504
3152
|
);
|
|
2505
3153
|
return null;
|
|
@@ -2520,25 +3168,58 @@ function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typ
|
|
|
2520
3168
|
const localTypeParameter = node.typeParameters?.[typeParameterIndex];
|
|
2521
3169
|
return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
|
|
2522
3170
|
}
|
|
2523
|
-
function
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
3171
|
+
function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker, provenance, diagnostics) {
|
|
3172
|
+
const propertySymbol = boundType.getProperty(fieldName);
|
|
3173
|
+
if (propertySymbol === void 0) {
|
|
3174
|
+
return void 0;
|
|
3175
|
+
}
|
|
3176
|
+
const declaration = propertySymbol.valueDeclaration ?? propertySymbol.declarations?.[0];
|
|
3177
|
+
const anchorNode = declaration ?? boundType.symbol.declarations?.[0] ?? null;
|
|
3178
|
+
const resolvedAnchorNode = anchorNode ?? resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
3179
|
+
if (resolvedAnchorNode === null) {
|
|
3180
|
+
return void 0;
|
|
3181
|
+
}
|
|
3182
|
+
const propertyType = checker.getTypeOfSymbolAtLocation(
|
|
3183
|
+
propertySymbol,
|
|
3184
|
+
resolvedAnchorNode
|
|
3185
|
+
);
|
|
3186
|
+
if (propertyType.isStringLiteral()) {
|
|
3187
|
+
return propertyType.value;
|
|
3188
|
+
}
|
|
3189
|
+
if (propertyType.isUnion()) {
|
|
3190
|
+
const nonNullMembers = propertyType.types.filter(
|
|
3191
|
+
(member) => !(member.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined))
|
|
3192
|
+
);
|
|
3193
|
+
if (nonNullMembers.length > 0 && nonNullMembers.every((member) => member.isStringLiteral())) {
|
|
3194
|
+
diagnostics.push(
|
|
3195
|
+
makeAnalysisDiagnostic(
|
|
3196
|
+
"INVALID_TAG_ARGUMENT",
|
|
3197
|
+
"Discriminator resolution for union-valued identity properties is out of scope for v1.",
|
|
3198
|
+
provenance
|
|
3199
|
+
)
|
|
3200
|
+
);
|
|
3201
|
+
return null;
|
|
2536
3202
|
}
|
|
2537
3203
|
}
|
|
2538
|
-
return
|
|
3204
|
+
return void 0;
|
|
2539
3205
|
}
|
|
2540
|
-
function
|
|
2541
|
-
|
|
3206
|
+
function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
3207
|
+
const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
3208
|
+
if (declaration === null) {
|
|
3209
|
+
return void 0;
|
|
3210
|
+
}
|
|
3211
|
+
const metadata = resolveNodeMetadata(
|
|
3212
|
+
metadataPolicy,
|
|
3213
|
+
"type",
|
|
3214
|
+
getDiscriminatorLogicalName(boundType, declaration, checker),
|
|
3215
|
+
declaration,
|
|
3216
|
+
{
|
|
3217
|
+
checker,
|
|
3218
|
+
declaration,
|
|
3219
|
+
subjectType: boundType
|
|
3220
|
+
}
|
|
3221
|
+
);
|
|
3222
|
+
return metadata?.apiName;
|
|
2542
3223
|
}
|
|
2543
3224
|
function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2544
3225
|
if (seen.has(type)) {
|
|
@@ -2565,7 +3246,7 @@ function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__
|
|
|
2565
3246
|
}
|
|
2566
3247
|
return null;
|
|
2567
3248
|
}
|
|
2568
|
-
function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics) {
|
|
3249
|
+
function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, diagnostics, metadataPolicy) {
|
|
2569
3250
|
if (boundType === null) {
|
|
2570
3251
|
diagnostics.push(
|
|
2571
3252
|
makeAnalysisDiagnostic(
|
|
@@ -2594,9 +3275,22 @@ function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics)
|
|
|
2594
3275
|
return null;
|
|
2595
3276
|
}
|
|
2596
3277
|
}
|
|
2597
|
-
const
|
|
2598
|
-
|
|
2599
|
-
|
|
3278
|
+
const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
|
|
3279
|
+
boundType,
|
|
3280
|
+
fieldName,
|
|
3281
|
+
checker,
|
|
3282
|
+
provenance,
|
|
3283
|
+
diagnostics
|
|
3284
|
+
);
|
|
3285
|
+
if (literalIdentityValue !== void 0) {
|
|
3286
|
+
return literalIdentityValue;
|
|
3287
|
+
}
|
|
3288
|
+
const apiName = resolveDiscriminatorApiName(boundType, checker, metadataPolicy);
|
|
3289
|
+
if (apiName?.source === "explicit") {
|
|
3290
|
+
return apiName.value;
|
|
3291
|
+
}
|
|
3292
|
+
if (apiName?.source === "inferred") {
|
|
3293
|
+
return apiName.value;
|
|
2600
3294
|
}
|
|
2601
3295
|
diagnostics.push(
|
|
2602
3296
|
makeAnalysisDiagnostic(
|
|
@@ -2613,7 +3307,15 @@ function getDeclarationName(node) {
|
|
|
2613
3307
|
}
|
|
2614
3308
|
return "anonymous";
|
|
2615
3309
|
}
|
|
2616
|
-
function
|
|
3310
|
+
function getResolvedTypeArguments(type) {
|
|
3311
|
+
return (isTypeReference(type) ? type.typeArguments : void 0) ?? type.aliasTypeArguments ?? [];
|
|
3312
|
+
}
|
|
3313
|
+
function getDiscriminatorLogicalName(type, declaration, checker) {
|
|
3314
|
+
const baseName = getDeclarationName(declaration);
|
|
3315
|
+
const typeArguments = getResolvedTypeArguments(type);
|
|
3316
|
+
return typeArguments.length === 0 ? baseName : buildInstantiatedReferenceName(baseName, typeArguments, checker);
|
|
3317
|
+
}
|
|
3318
|
+
function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checker, file, diagnostics, metadataPolicy) {
|
|
2617
3319
|
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2618
3320
|
if (directive === null) {
|
|
2619
3321
|
return [...fields];
|
|
@@ -2625,9 +3327,11 @@ function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checke
|
|
|
2625
3327
|
checker,
|
|
2626
3328
|
directive.typeParameterName
|
|
2627
3329
|
),
|
|
3330
|
+
directive.fieldName,
|
|
2628
3331
|
checker,
|
|
2629
3332
|
directive.provenance,
|
|
2630
|
-
diagnostics
|
|
3333
|
+
diagnostics,
|
|
3334
|
+
metadataPolicy
|
|
2631
3335
|
);
|
|
2632
3336
|
if (discriminatorValue === null) {
|
|
2633
3337
|
return [...fields];
|
|
@@ -2648,7 +3352,7 @@ function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
|
|
|
2648
3352
|
).filter((value) => value !== "");
|
|
2649
3353
|
return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
|
|
2650
3354
|
}
|
|
2651
|
-
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3355
|
+
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy, extensionRegistry, diagnostics) {
|
|
2652
3356
|
const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2653
3357
|
if (typeNode === void 0) {
|
|
2654
3358
|
return [];
|
|
@@ -2668,13 +3372,14 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
|
|
|
2668
3372
|
typeRegistry,
|
|
2669
3373
|
visiting,
|
|
2670
3374
|
argumentNode,
|
|
3375
|
+
metadataPolicy,
|
|
2671
3376
|
extensionRegistry,
|
|
2672
3377
|
diagnostics
|
|
2673
3378
|
)
|
|
2674
3379
|
};
|
|
2675
3380
|
});
|
|
2676
3381
|
}
|
|
2677
|
-
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics) {
|
|
3382
|
+
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics, metadataPolicy) {
|
|
2678
3383
|
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2679
3384
|
if (directive === null) {
|
|
2680
3385
|
return properties;
|
|
@@ -2686,9 +3391,11 @@ function applyDiscriminatorToObjectProperties(properties, node, subjectType, che
|
|
|
2686
3391
|
checker,
|
|
2687
3392
|
directive.typeParameterName
|
|
2688
3393
|
),
|
|
3394
|
+
directive.fieldName,
|
|
2689
3395
|
checker,
|
|
2690
3396
|
directive.provenance,
|
|
2691
|
-
diagnostics
|
|
3397
|
+
diagnostics,
|
|
3398
|
+
metadataPolicy
|
|
2692
3399
|
);
|
|
2693
3400
|
if (discriminatorValue === null) {
|
|
2694
3401
|
return properties;
|
|
@@ -2703,7 +3410,7 @@ function applyDiscriminatorToObjectProperties(properties, node, subjectType, che
|
|
|
2703
3410
|
} : property
|
|
2704
3411
|
);
|
|
2705
3412
|
}
|
|
2706
|
-
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
3413
|
+
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
|
|
2707
3414
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2708
3415
|
return null;
|
|
2709
3416
|
}
|
|
@@ -2718,6 +3425,7 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2718
3425
|
typeRegistry,
|
|
2719
3426
|
visiting,
|
|
2720
3427
|
prop,
|
|
3428
|
+
metadataPolicy,
|
|
2721
3429
|
extensionRegistry,
|
|
2722
3430
|
diagnostics
|
|
2723
3431
|
);
|
|
@@ -2741,9 +3449,16 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2741
3449
|
annotations.push(defaultAnnotation);
|
|
2742
3450
|
}
|
|
2743
3451
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
3452
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
|
|
3453
|
+
checker,
|
|
3454
|
+
declaration: prop,
|
|
3455
|
+
subjectType: tsType,
|
|
3456
|
+
hostType
|
|
3457
|
+
});
|
|
2744
3458
|
return {
|
|
2745
3459
|
kind: "field",
|
|
2746
3460
|
name,
|
|
3461
|
+
...metadata !== void 0 && { metadata },
|
|
2747
3462
|
type,
|
|
2748
3463
|
required: !optional,
|
|
2749
3464
|
constraints,
|
|
@@ -2751,7 +3466,7 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2751
3466
|
provenance
|
|
2752
3467
|
};
|
|
2753
3468
|
}
|
|
2754
|
-
function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
3469
|
+
function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
|
|
2755
3470
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2756
3471
|
return null;
|
|
2757
3472
|
}
|
|
@@ -2766,6 +3481,7 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2766
3481
|
typeRegistry,
|
|
2767
3482
|
visiting,
|
|
2768
3483
|
prop,
|
|
3484
|
+
metadataPolicy,
|
|
2769
3485
|
extensionRegistry,
|
|
2770
3486
|
diagnostics
|
|
2771
3487
|
);
|
|
@@ -2785,9 +3501,16 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2785
3501
|
let annotations = [];
|
|
2786
3502
|
annotations.push(...docResult.annotations);
|
|
2787
3503
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
3504
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
|
|
3505
|
+
checker,
|
|
3506
|
+
declaration: prop,
|
|
3507
|
+
subjectType: tsType,
|
|
3508
|
+
hostType
|
|
3509
|
+
});
|
|
2788
3510
|
return {
|
|
2789
3511
|
kind: "field",
|
|
2790
3512
|
name,
|
|
3513
|
+
...metadata !== void 0 && { metadata },
|
|
2791
3514
|
type,
|
|
2792
3515
|
required: !optional,
|
|
2793
3516
|
constraints,
|
|
@@ -2912,7 +3635,7 @@ function getTypeNodeRegistrationName(typeNode) {
|
|
|
2912
3635
|
}
|
|
2913
3636
|
return null;
|
|
2914
3637
|
}
|
|
2915
|
-
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3638
|
+
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2916
3639
|
const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
|
|
2917
3640
|
if (customType) {
|
|
2918
3641
|
return customType;
|
|
@@ -2924,6 +3647,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2924
3647
|
typeRegistry,
|
|
2925
3648
|
visiting,
|
|
2926
3649
|
sourceNode,
|
|
3650
|
+
metadataPolicy,
|
|
2927
3651
|
extensionRegistry,
|
|
2928
3652
|
diagnostics
|
|
2929
3653
|
);
|
|
@@ -2968,6 +3692,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2968
3692
|
typeRegistry,
|
|
2969
3693
|
visiting,
|
|
2970
3694
|
sourceNode,
|
|
3695
|
+
metadataPolicy,
|
|
2971
3696
|
extensionRegistry,
|
|
2972
3697
|
diagnostics
|
|
2973
3698
|
);
|
|
@@ -2980,6 +3705,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2980
3705
|
typeRegistry,
|
|
2981
3706
|
visiting,
|
|
2982
3707
|
sourceNode,
|
|
3708
|
+
metadataPolicy,
|
|
2983
3709
|
extensionRegistry,
|
|
2984
3710
|
diagnostics
|
|
2985
3711
|
);
|
|
@@ -2992,13 +3718,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2992
3718
|
typeRegistry,
|
|
2993
3719
|
visiting,
|
|
2994
3720
|
sourceNode,
|
|
3721
|
+
metadataPolicy,
|
|
2995
3722
|
extensionRegistry,
|
|
2996
3723
|
diagnostics
|
|
2997
3724
|
);
|
|
2998
3725
|
}
|
|
2999
3726
|
return { kind: "primitive", primitiveKind: "string" };
|
|
3000
3727
|
}
|
|
3001
|
-
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3728
|
+
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3002
3729
|
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
|
|
3003
3730
|
return null;
|
|
3004
3731
|
}
|
|
@@ -3018,14 +3745,21 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
|
|
|
3018
3745
|
file,
|
|
3019
3746
|
makeParseOptions(extensionRegistry)
|
|
3020
3747
|
);
|
|
3748
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "type", aliasName, aliasDecl, {
|
|
3749
|
+
checker,
|
|
3750
|
+
declaration: aliasDecl,
|
|
3751
|
+
subjectType: aliasType
|
|
3752
|
+
});
|
|
3021
3753
|
typeRegistry[aliasName] = {
|
|
3022
3754
|
name: aliasName,
|
|
3755
|
+
...metadata !== void 0 && { metadata },
|
|
3023
3756
|
type: resolveAliasedPrimitiveTarget(
|
|
3024
3757
|
aliasType,
|
|
3025
3758
|
checker,
|
|
3026
3759
|
file,
|
|
3027
3760
|
typeRegistry,
|
|
3028
3761
|
visiting,
|
|
3762
|
+
metadataPolicy,
|
|
3029
3763
|
extensionRegistry,
|
|
3030
3764
|
diagnostics
|
|
3031
3765
|
),
|
|
@@ -3054,7 +3788,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
|
|
|
3054
3788
|
const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
|
|
3055
3789
|
return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
|
|
3056
3790
|
}
|
|
3057
|
-
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3791
|
+
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3058
3792
|
const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
|
|
3059
3793
|
if (nestedAliasDecl !== void 0) {
|
|
3060
3794
|
return resolveAliasedPrimitiveTarget(
|
|
@@ -3063,6 +3797,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
3063
3797
|
file,
|
|
3064
3798
|
typeRegistry,
|
|
3065
3799
|
visiting,
|
|
3800
|
+
metadataPolicy,
|
|
3066
3801
|
extensionRegistry,
|
|
3067
3802
|
diagnostics
|
|
3068
3803
|
);
|
|
@@ -3074,11 +3809,12 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
3074
3809
|
typeRegistry,
|
|
3075
3810
|
visiting,
|
|
3076
3811
|
void 0,
|
|
3812
|
+
metadataPolicy,
|
|
3077
3813
|
extensionRegistry,
|
|
3078
3814
|
diagnostics
|
|
3079
3815
|
);
|
|
3080
3816
|
}
|
|
3081
|
-
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3817
|
+
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3082
3818
|
const typeName = getNamedTypeName(type);
|
|
3083
3819
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
3084
3820
|
if (typeName && typeName in typeRegistry) {
|
|
@@ -3113,8 +3849,14 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3113
3849
|
return result;
|
|
3114
3850
|
}
|
|
3115
3851
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3852
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", typeName, namedDecl, {
|
|
3853
|
+
checker,
|
|
3854
|
+
declaration: namedDecl,
|
|
3855
|
+
subjectType: type
|
|
3856
|
+
}) : void 0;
|
|
3116
3857
|
typeRegistry[typeName] = {
|
|
3117
3858
|
name: typeName,
|
|
3859
|
+
...metadata !== void 0 && { metadata },
|
|
3118
3860
|
type: result,
|
|
3119
3861
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3120
3862
|
provenance: provenanceForDeclaration(namedDecl ?? sourceNode, file)
|
|
@@ -3168,6 +3910,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3168
3910
|
typeRegistry,
|
|
3169
3911
|
visiting,
|
|
3170
3912
|
nonNullMembers[0].sourceNode ?? sourceNode,
|
|
3913
|
+
metadataPolicy,
|
|
3171
3914
|
extensionRegistry,
|
|
3172
3915
|
diagnostics
|
|
3173
3916
|
);
|
|
@@ -3185,6 +3928,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3185
3928
|
typeRegistry,
|
|
3186
3929
|
visiting,
|
|
3187
3930
|
memberSourceNode ?? sourceNode,
|
|
3931
|
+
metadataPolicy,
|
|
3188
3932
|
extensionRegistry,
|
|
3189
3933
|
diagnostics
|
|
3190
3934
|
)
|
|
@@ -3194,7 +3938,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3194
3938
|
}
|
|
3195
3939
|
return registerNamed({ kind: "union", members });
|
|
3196
3940
|
}
|
|
3197
|
-
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3941
|
+
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3198
3942
|
const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
|
|
3199
3943
|
const elementType = typeArgs?.[0];
|
|
3200
3944
|
const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
|
|
@@ -3205,12 +3949,13 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3205
3949
|
typeRegistry,
|
|
3206
3950
|
visiting,
|
|
3207
3951
|
elementSourceNode,
|
|
3952
|
+
metadataPolicy,
|
|
3208
3953
|
extensionRegistry,
|
|
3209
3954
|
diagnostics
|
|
3210
3955
|
) : { kind: "primitive", primitiveKind: "string" };
|
|
3211
3956
|
return { kind: "array", items };
|
|
3212
3957
|
}
|
|
3213
|
-
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3958
|
+
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3214
3959
|
if (type.getProperties().length > 0) {
|
|
3215
3960
|
return null;
|
|
3216
3961
|
}
|
|
@@ -3225,6 +3970,7 @@ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, exten
|
|
|
3225
3970
|
typeRegistry,
|
|
3226
3971
|
visiting,
|
|
3227
3972
|
void 0,
|
|
3973
|
+
metadataPolicy,
|
|
3228
3974
|
extensionRegistry,
|
|
3229
3975
|
diagnostics
|
|
3230
3976
|
);
|
|
@@ -3255,7 +4001,22 @@ function typeNodeContainsReference(type, targetName) {
|
|
|
3255
4001
|
}
|
|
3256
4002
|
}
|
|
3257
4003
|
}
|
|
3258
|
-
function
|
|
4004
|
+
function shouldEmitResolvedObjectProperty(property, declaration) {
|
|
4005
|
+
if (property.name.startsWith("__@")) {
|
|
4006
|
+
return false;
|
|
4007
|
+
}
|
|
4008
|
+
if (declaration !== void 0 && "name" in declaration && declaration.name !== void 0) {
|
|
4009
|
+
const name = declaration.name;
|
|
4010
|
+
if (ts3.isComputedPropertyName(name) || ts3.isPrivateIdentifier(name)) {
|
|
4011
|
+
return false;
|
|
4012
|
+
}
|
|
4013
|
+
if (!ts3.isIdentifier(name) && !ts3.isStringLiteral(name) && !ts3.isNumericLiteral(name)) {
|
|
4014
|
+
return false;
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
return true;
|
|
4018
|
+
}
|
|
4019
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3259
4020
|
const collectedDiagnostics = diagnostics ?? [];
|
|
3260
4021
|
const typeName = getNamedTypeName(type);
|
|
3261
4022
|
const namedTypeName = typeName ?? void 0;
|
|
@@ -3267,6 +4028,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3267
4028
|
typeRegistry,
|
|
3268
4029
|
visiting,
|
|
3269
4030
|
sourceNode,
|
|
4031
|
+
metadataPolicy,
|
|
3270
4032
|
extensionRegistry,
|
|
3271
4033
|
collectedDiagnostics
|
|
3272
4034
|
);
|
|
@@ -3317,6 +4079,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3317
4079
|
file,
|
|
3318
4080
|
typeRegistry,
|
|
3319
4081
|
visiting,
|
|
4082
|
+
metadataPolicy,
|
|
3320
4083
|
extensionRegistry,
|
|
3321
4084
|
collectedDiagnostics
|
|
3322
4085
|
);
|
|
@@ -3329,8 +4092,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3329
4092
|
return recordNode;
|
|
3330
4093
|
}
|
|
3331
4094
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
4095
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
|
|
4096
|
+
checker,
|
|
4097
|
+
declaration: namedDecl,
|
|
4098
|
+
subjectType: type
|
|
4099
|
+
}) : void 0;
|
|
3332
4100
|
typeRegistry[registryTypeName] = {
|
|
3333
4101
|
name: registryTypeName,
|
|
4102
|
+
...metadata !== void 0 && { metadata },
|
|
3334
4103
|
type: recordNode,
|
|
3335
4104
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3336
4105
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
@@ -3350,12 +4119,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3350
4119
|
file,
|
|
3351
4120
|
typeRegistry,
|
|
3352
4121
|
visiting,
|
|
4122
|
+
metadataPolicy,
|
|
3353
4123
|
collectedDiagnostics,
|
|
3354
4124
|
extensionRegistry
|
|
3355
4125
|
);
|
|
3356
4126
|
for (const prop of type.getProperties()) {
|
|
3357
4127
|
const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
3358
4128
|
if (!declaration) continue;
|
|
4129
|
+
if (!shouldEmitResolvedObjectProperty(prop, declaration)) continue;
|
|
3359
4130
|
const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);
|
|
3360
4131
|
const optional = !!(prop.flags & ts3.SymbolFlags.Optional);
|
|
3361
4132
|
const propTypeNode = resolveTypeNode(
|
|
@@ -3365,12 +4136,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3365
4136
|
typeRegistry,
|
|
3366
4137
|
visiting,
|
|
3367
4138
|
declaration,
|
|
4139
|
+
metadataPolicy,
|
|
3368
4140
|
extensionRegistry,
|
|
3369
4141
|
collectedDiagnostics
|
|
3370
4142
|
);
|
|
3371
4143
|
const fieldNodeInfo = fieldInfoMap?.get(prop.name);
|
|
3372
4144
|
properties.push({
|
|
3373
4145
|
name: prop.name,
|
|
4146
|
+
...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
|
|
3374
4147
|
type: propTypeNode,
|
|
3375
4148
|
optional,
|
|
3376
4149
|
constraints: fieldNodeInfo?.constraints ?? [],
|
|
@@ -3387,14 +4160,21 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3387
4160
|
type,
|
|
3388
4161
|
checker,
|
|
3389
4162
|
file,
|
|
3390
|
-
collectedDiagnostics
|
|
4163
|
+
collectedDiagnostics,
|
|
4164
|
+
metadataPolicy
|
|
3391
4165
|
) : properties,
|
|
3392
4166
|
additionalProperties: true
|
|
3393
4167
|
};
|
|
3394
4168
|
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3395
4169
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
4170
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
|
|
4171
|
+
checker,
|
|
4172
|
+
declaration: namedDecl,
|
|
4173
|
+
subjectType: type
|
|
4174
|
+
}) : void 0;
|
|
3396
4175
|
typeRegistry[registryTypeName] = {
|
|
3397
4176
|
name: registryTypeName,
|
|
4177
|
+
...metadata !== void 0 && { metadata },
|
|
3398
4178
|
type: objectNode,
|
|
3399
4179
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3400
4180
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
@@ -3407,7 +4187,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3407
4187
|
}
|
|
3408
4188
|
return objectNode;
|
|
3409
4189
|
}
|
|
3410
|
-
function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visiting, diagnostics, extensionRegistry) {
|
|
4190
|
+
function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visiting, metadataPolicy, diagnostics, extensionRegistry) {
|
|
3411
4191
|
const symbols = [type.getSymbol(), type.aliasSymbol].filter(
|
|
3412
4192
|
(s) => s?.declarations != null && s.declarations.length > 0
|
|
3413
4193
|
);
|
|
@@ -3428,10 +4208,12 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3428
4208
|
visiting,
|
|
3429
4209
|
diagnostics,
|
|
3430
4210
|
hostType,
|
|
4211
|
+
metadataPolicy,
|
|
3431
4212
|
extensionRegistry
|
|
3432
4213
|
);
|
|
3433
4214
|
if (fieldNode) {
|
|
3434
4215
|
map.set(fieldNode.name, {
|
|
4216
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
3435
4217
|
constraints: [...fieldNode.constraints],
|
|
3436
4218
|
annotations: [...fieldNode.annotations],
|
|
3437
4219
|
provenance: fieldNode.provenance
|
|
@@ -3449,6 +4231,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3449
4231
|
file,
|
|
3450
4232
|
typeRegistry,
|
|
3451
4233
|
visiting,
|
|
4234
|
+
metadataPolicy,
|
|
3452
4235
|
checker.getTypeAtLocation(interfaceDecl),
|
|
3453
4236
|
diagnostics,
|
|
3454
4237
|
extensionRegistry
|
|
@@ -3462,6 +4245,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3462
4245
|
file,
|
|
3463
4246
|
typeRegistry,
|
|
3464
4247
|
visiting,
|
|
4248
|
+
metadataPolicy,
|
|
3465
4249
|
checker.getTypeAtLocation(typeAliasDecl),
|
|
3466
4250
|
diagnostics,
|
|
3467
4251
|
extensionRegistry
|
|
@@ -3513,7 +4297,7 @@ function isNullishTypeNode(typeNode) {
|
|
|
3513
4297
|
}
|
|
3514
4298
|
return ts3.isLiteralTypeNode(typeNode) && (typeNode.literal.kind === ts3.SyntaxKind.NullKeyword || typeNode.literal.kind === ts3.SyntaxKind.UndefinedKeyword);
|
|
3515
4299
|
}
|
|
3516
|
-
function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, hostType, diagnostics, extensionRegistry) {
|
|
4300
|
+
function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, metadataPolicy, hostType, diagnostics, extensionRegistry) {
|
|
3517
4301
|
const map = /* @__PURE__ */ new Map();
|
|
3518
4302
|
for (const member of members) {
|
|
3519
4303
|
if (ts3.isPropertySignature(member)) {
|
|
@@ -3525,10 +4309,12 @@ function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, h
|
|
|
3525
4309
|
visiting,
|
|
3526
4310
|
diagnostics,
|
|
3527
4311
|
hostType,
|
|
4312
|
+
metadataPolicy,
|
|
3528
4313
|
extensionRegistry
|
|
3529
4314
|
);
|
|
3530
4315
|
if (fieldNode) {
|
|
3531
4316
|
map.set(fieldNode.name, {
|
|
4317
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
3532
4318
|
constraints: [...fieldNode.constraints],
|
|
3533
4319
|
annotations: [...fieldNode.annotations],
|
|
3534
4320
|
provenance: fieldNode.provenance
|
|
@@ -3559,6 +4345,7 @@ function extractTypeAliasConstraintNodes(typeNode, checker, file, extensionRegis
|
|
|
3559
4345
|
{},
|
|
3560
4346
|
/* @__PURE__ */ new Set(),
|
|
3561
4347
|
aliasDecl.type,
|
|
4348
|
+
void 0,
|
|
3562
4349
|
extensionRegistry
|
|
3563
4350
|
);
|
|
3564
4351
|
const constraints = extractJSDocConstraintNodes(
|
|
@@ -3744,19 +4531,37 @@ function findInterfaceByName(sourceFile, interfaceName) {
|
|
|
3744
4531
|
function findTypeAliasByName(sourceFile, aliasName) {
|
|
3745
4532
|
return findNodeByName(sourceFile, aliasName, ts4.isTypeAliasDeclaration, (n) => n.name.text);
|
|
3746
4533
|
}
|
|
3747
|
-
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry) {
|
|
4534
|
+
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy) {
|
|
3748
4535
|
const ctx = createProgramContext(filePath);
|
|
3749
|
-
return analyzeNamedTypeToIRFromProgramContext(
|
|
4536
|
+
return analyzeNamedTypeToIRFromProgramContext(
|
|
4537
|
+
ctx,
|
|
4538
|
+
filePath,
|
|
4539
|
+
typeName,
|
|
4540
|
+
extensionRegistry,
|
|
4541
|
+
metadataPolicy
|
|
4542
|
+
);
|
|
3750
4543
|
}
|
|
3751
|
-
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry) {
|
|
4544
|
+
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy) {
|
|
3752
4545
|
const analysisFilePath = path.resolve(filePath);
|
|
3753
4546
|
const classDecl = findClassByName(ctx.sourceFile, typeName);
|
|
3754
4547
|
if (classDecl !== null) {
|
|
3755
|
-
return analyzeClassToIR(
|
|
4548
|
+
return analyzeClassToIR(
|
|
4549
|
+
classDecl,
|
|
4550
|
+
ctx.checker,
|
|
4551
|
+
analysisFilePath,
|
|
4552
|
+
extensionRegistry,
|
|
4553
|
+
metadataPolicy
|
|
4554
|
+
);
|
|
3756
4555
|
}
|
|
3757
4556
|
const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
|
|
3758
4557
|
if (interfaceDecl !== null) {
|
|
3759
|
-
return analyzeInterfaceToIR(
|
|
4558
|
+
return analyzeInterfaceToIR(
|
|
4559
|
+
interfaceDecl,
|
|
4560
|
+
ctx.checker,
|
|
4561
|
+
analysisFilePath,
|
|
4562
|
+
extensionRegistry,
|
|
4563
|
+
metadataPolicy
|
|
4564
|
+
);
|
|
3760
4565
|
}
|
|
3761
4566
|
const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
|
|
3762
4567
|
if (typeAlias !== null) {
|
|
@@ -3764,7 +4569,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
|
|
|
3764
4569
|
typeAlias,
|
|
3765
4570
|
ctx.checker,
|
|
3766
4571
|
analysisFilePath,
|
|
3767
|
-
extensionRegistry
|
|
4572
|
+
extensionRegistry,
|
|
4573
|
+
metadataPolicy
|
|
3768
4574
|
);
|
|
3769
4575
|
if (result.ok) {
|
|
3770
4576
|
return result.analysis;
|
|
@@ -3857,7 +4663,11 @@ function generateClassSchemas(analysis, source, options) {
|
|
|
3857
4663
|
if (errorDiagnostics !== void 0 && errorDiagnostics.length > 0) {
|
|
3858
4664
|
throw new Error(formatValidationError(errorDiagnostics));
|
|
3859
4665
|
}
|
|
3860
|
-
const ir = canonicalizeTSDoc(
|
|
4666
|
+
const ir = canonicalizeTSDoc(
|
|
4667
|
+
analysis,
|
|
4668
|
+
source,
|
|
4669
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
4670
|
+
);
|
|
3861
4671
|
const validationResult = validateIR(ir, {
|
|
3862
4672
|
...options?.extensionRegistry !== void 0 && {
|
|
3863
4673
|
extensionRegistry: options.extensionRegistry
|
|
@@ -3894,13 +4704,15 @@ function generateSchemasFromClass(options) {
|
|
|
3894
4704
|
classDecl,
|
|
3895
4705
|
ctx.checker,
|
|
3896
4706
|
options.filePath,
|
|
3897
|
-
options.extensionRegistry
|
|
4707
|
+
options.extensionRegistry,
|
|
4708
|
+
options.metadata
|
|
3898
4709
|
);
|
|
3899
4710
|
return generateClassSchemas(
|
|
3900
4711
|
analysis,
|
|
3901
4712
|
{ file: options.filePath },
|
|
3902
4713
|
{
|
|
3903
4714
|
extensionRegistry: options.extensionRegistry,
|
|
4715
|
+
metadata: options.metadata,
|
|
3904
4716
|
vendorPrefix: options.vendorPrefix
|
|
3905
4717
|
}
|
|
3906
4718
|
);
|
|
@@ -3918,13 +4730,15 @@ function generateSchemasFromProgram(options) {
|
|
|
3918
4730
|
ctx,
|
|
3919
4731
|
options.filePath,
|
|
3920
4732
|
options.typeName,
|
|
3921
|
-
options.extensionRegistry
|
|
4733
|
+
options.extensionRegistry,
|
|
4734
|
+
options.metadata
|
|
3922
4735
|
);
|
|
3923
4736
|
return generateClassSchemas(
|
|
3924
4737
|
analysis,
|
|
3925
4738
|
{ file: options.filePath },
|
|
3926
4739
|
{
|
|
3927
4740
|
extensionRegistry: options.extensionRegistry,
|
|
4741
|
+
metadata: options.metadata,
|
|
3928
4742
|
vendorPrefix: options.vendorPrefix
|
|
3929
4743
|
}
|
|
3930
4744
|
);
|
|
@@ -3933,16 +4747,28 @@ function generateSchemasFromProgram(options) {
|
|
|
3933
4747
|
// src/generators/mixed-authoring.ts
|
|
3934
4748
|
function buildMixedAuthoringSchemas(options) {
|
|
3935
4749
|
const { filePath, typeName, overlays, ...schemaOptions } = options;
|
|
3936
|
-
const analysis = analyzeNamedTypeToIR(
|
|
3937
|
-
|
|
3938
|
-
|
|
4750
|
+
const analysis = analyzeNamedTypeToIR(
|
|
4751
|
+
filePath,
|
|
4752
|
+
typeName,
|
|
4753
|
+
schemaOptions.extensionRegistry,
|
|
4754
|
+
schemaOptions.metadata
|
|
4755
|
+
);
|
|
4756
|
+
const composedAnalysis = composeAnalysisWithOverlays(analysis, overlays, schemaOptions.metadata);
|
|
4757
|
+
const ir = canonicalizeTSDoc(
|
|
4758
|
+
composedAnalysis,
|
|
4759
|
+
{ file: filePath },
|
|
4760
|
+
schemaOptions.metadata !== void 0 ? { metadata: schemaOptions.metadata } : void 0
|
|
4761
|
+
);
|
|
3939
4762
|
return {
|
|
3940
4763
|
jsonSchema: generateJsonSchemaFromIR(ir, schemaOptions),
|
|
3941
4764
|
uiSchema: generateUiSchemaFromIR(ir)
|
|
3942
4765
|
};
|
|
3943
4766
|
}
|
|
3944
|
-
function composeAnalysisWithOverlays(analysis, overlays) {
|
|
3945
|
-
const overlayIR = canonicalizeChainDSL(
|
|
4767
|
+
function composeAnalysisWithOverlays(analysis, overlays, metadata) {
|
|
4768
|
+
const overlayIR = canonicalizeChainDSL(
|
|
4769
|
+
overlays,
|
|
4770
|
+
metadata !== void 0 ? { metadata } : void 0
|
|
4771
|
+
);
|
|
3946
4772
|
const overlayFields = collectOverlayFields(overlayIR.elements);
|
|
3947
4773
|
if (overlayFields.length === 0) {
|
|
3948
4774
|
return analysis;
|
|
@@ -3998,8 +4824,10 @@ function collectOverlayFields(elements) {
|
|
|
3998
4824
|
}
|
|
3999
4825
|
function mergeFieldOverlay(baseField, overlayField, typeRegistry) {
|
|
4000
4826
|
assertSupportedOverlayField(baseField, overlayField);
|
|
4827
|
+
const metadata = mergeResolvedMetadata(baseField.metadata, overlayField.metadata);
|
|
4001
4828
|
return {
|
|
4002
4829
|
...baseField,
|
|
4830
|
+
...metadata !== void 0 && { metadata },
|
|
4003
4831
|
type: mergeFieldType(baseField, overlayField, typeRegistry),
|
|
4004
4832
|
annotations: mergeAnnotations(baseField.annotations, overlayField.annotations)
|
|
4005
4833
|
};
|
|
@@ -4110,12 +4938,12 @@ function annotationKey(annotation) {
|
|
|
4110
4938
|
function buildFormSchemas(form, options) {
|
|
4111
4939
|
return {
|
|
4112
4940
|
jsonSchema: generateJsonSchema(form, options),
|
|
4113
|
-
uiSchema: generateUiSchema(form)
|
|
4941
|
+
uiSchema: generateUiSchema(form, options)
|
|
4114
4942
|
};
|
|
4115
4943
|
}
|
|
4116
4944
|
function writeSchemas(form, options) {
|
|
4117
|
-
const { outDir, name = "schema", indent = 2, vendorPrefix } = options;
|
|
4118
|
-
const buildOptions = vendorPrefix === void 0 ? void 0 : { vendorPrefix };
|
|
4945
|
+
const { outDir, name = "schema", indent = 2, vendorPrefix, metadata } = options;
|
|
4946
|
+
const buildOptions = vendorPrefix === void 0 && metadata === void 0 ? void 0 : { vendorPrefix, metadata };
|
|
4119
4947
|
const { jsonSchema, uiSchema: uiSchema2 } = buildFormSchemas(form, buildOptions);
|
|
4120
4948
|
if (!fs.existsSync(outDir)) {
|
|
4121
4949
|
fs.mkdirSync(outDir, { recursive: true });
|