@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.js
CHANGED
|
@@ -1,5 +1,314 @@
|
|
|
1
1
|
// src/canonicalize/chain-dsl-canonicalizer.ts
|
|
2
|
-
import { IR_VERSION } from "@formspec/core/internals";
|
|
2
|
+
import { IR_VERSION, _getFormSpecMetadataPolicy } from "@formspec/core/internals";
|
|
3
|
+
|
|
4
|
+
// src/metadata/policy.ts
|
|
5
|
+
var NOOP_INFLECT = () => "";
|
|
6
|
+
function normalizePluralization(input) {
|
|
7
|
+
if (input?.mode === "infer-if-missing") {
|
|
8
|
+
return {
|
|
9
|
+
mode: "infer-if-missing",
|
|
10
|
+
infer: () => "",
|
|
11
|
+
inflect: input.inflect
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (input?.mode === "require-explicit") {
|
|
15
|
+
return {
|
|
16
|
+
mode: "require-explicit",
|
|
17
|
+
infer: () => "",
|
|
18
|
+
inflect: NOOP_INFLECT
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
mode: "disabled",
|
|
23
|
+
infer: () => "",
|
|
24
|
+
inflect: NOOP_INFLECT
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function normalizeScalarPolicy(input) {
|
|
28
|
+
if (input?.mode === "infer-if-missing") {
|
|
29
|
+
return {
|
|
30
|
+
mode: "infer-if-missing",
|
|
31
|
+
infer: input.infer,
|
|
32
|
+
pluralization: normalizePluralization(input.pluralization)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (input?.mode === "require-explicit") {
|
|
36
|
+
return {
|
|
37
|
+
mode: "require-explicit",
|
|
38
|
+
infer: () => "",
|
|
39
|
+
pluralization: normalizePluralization(input.pluralization)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
mode: "disabled",
|
|
44
|
+
infer: () => "",
|
|
45
|
+
pluralization: normalizePluralization(input?.pluralization)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function normalizeDeclarationPolicy(input) {
|
|
49
|
+
return {
|
|
50
|
+
apiName: normalizeScalarPolicy(input?.apiName),
|
|
51
|
+
displayName: normalizeScalarPolicy(input?.displayName)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function normalizeMetadataPolicy(input) {
|
|
55
|
+
return {
|
|
56
|
+
type: normalizeDeclarationPolicy(input?.type),
|
|
57
|
+
field: normalizeDeclarationPolicy(input?.field),
|
|
58
|
+
method: normalizeDeclarationPolicy(input?.method)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getDeclarationMetadataPolicy(policy, declarationKind) {
|
|
62
|
+
return policy[declarationKind];
|
|
63
|
+
}
|
|
64
|
+
function makeMetadataContext(surface, declarationKind, logicalName, buildContext) {
|
|
65
|
+
return {
|
|
66
|
+
surface,
|
|
67
|
+
declarationKind,
|
|
68
|
+
logicalName,
|
|
69
|
+
...buildContext !== void 0 && { buildContext }
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/metadata/resolve.ts
|
|
74
|
+
function toExplicitScalar(value) {
|
|
75
|
+
return value !== void 0 && value.trim() !== "" ? { value, source: "explicit" } : void 0;
|
|
76
|
+
}
|
|
77
|
+
function toExplicitResolvedMetadata(explicit) {
|
|
78
|
+
if (explicit === void 0) {
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
const apiName = toExplicitScalar(explicit.apiName);
|
|
82
|
+
const displayName = toExplicitScalar(explicit.displayName);
|
|
83
|
+
const apiNamePlural = toExplicitScalar(explicit.apiNamePlural);
|
|
84
|
+
const displayNamePlural = toExplicitScalar(explicit.displayNamePlural);
|
|
85
|
+
const metadata = {
|
|
86
|
+
...apiName !== void 0 && { apiName },
|
|
87
|
+
...displayName !== void 0 && { displayName },
|
|
88
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
89
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
90
|
+
};
|
|
91
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
92
|
+
}
|
|
93
|
+
function resolveScalar(current, policy, context, metadataLabel) {
|
|
94
|
+
if (current !== void 0) {
|
|
95
|
+
return current;
|
|
96
|
+
}
|
|
97
|
+
if (policy.mode === "require-explicit") {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Metadata policy requires explicit ${metadataLabel} for ${context.declarationKind} "${context.logicalName}" on the ${context.surface} surface.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (policy.mode !== "infer-if-missing") {
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
const inferredValue = policy.infer(context);
|
|
106
|
+
return inferredValue.trim() !== "" ? { value: inferredValue, source: "inferred" } : void 0;
|
|
107
|
+
}
|
|
108
|
+
function resolvePlural(current, singular, policy, context, metadataLabel) {
|
|
109
|
+
if (current !== void 0) {
|
|
110
|
+
return current;
|
|
111
|
+
}
|
|
112
|
+
if (policy.mode === "require-explicit") {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Metadata policy requires explicit ${metadataLabel} for ${context.declarationKind} "${context.logicalName}" on the ${context.surface} surface.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (singular === void 0 || policy.mode !== "infer-if-missing") {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
const pluralValue = policy.inflect({ ...context, singular: singular.value });
|
|
121
|
+
return pluralValue.trim() !== "" ? { value: pluralValue, source: "inferred" } : void 0;
|
|
122
|
+
}
|
|
123
|
+
function resolveResolvedMetadata(current, policy, context) {
|
|
124
|
+
const apiName = resolveScalar(current?.apiName, policy.apiName, context, "apiName");
|
|
125
|
+
const displayName = resolveScalar(
|
|
126
|
+
current?.displayName,
|
|
127
|
+
policy.displayName,
|
|
128
|
+
context,
|
|
129
|
+
"displayName"
|
|
130
|
+
);
|
|
131
|
+
const apiNamePlural = resolvePlural(
|
|
132
|
+
current?.apiNamePlural,
|
|
133
|
+
apiName,
|
|
134
|
+
policy.apiName.pluralization,
|
|
135
|
+
context,
|
|
136
|
+
"apiNamePlural"
|
|
137
|
+
);
|
|
138
|
+
const displayNamePlural = resolvePlural(
|
|
139
|
+
current?.displayNamePlural,
|
|
140
|
+
displayName,
|
|
141
|
+
policy.displayName.pluralization,
|
|
142
|
+
context,
|
|
143
|
+
"displayNamePlural"
|
|
144
|
+
);
|
|
145
|
+
if (apiName === void 0 && displayName === void 0 && apiNamePlural === void 0 && displayNamePlural === void 0) {
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
...apiName !== void 0 && { apiName },
|
|
150
|
+
...displayName !== void 0 && { displayName },
|
|
151
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
152
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function pickResolvedMetadataValue(baseValue, overlayValue) {
|
|
156
|
+
if (overlayValue?.source === "explicit") {
|
|
157
|
+
return overlayValue;
|
|
158
|
+
}
|
|
159
|
+
if (baseValue?.source === "explicit") {
|
|
160
|
+
return baseValue;
|
|
161
|
+
}
|
|
162
|
+
return baseValue ?? overlayValue;
|
|
163
|
+
}
|
|
164
|
+
function resolveTypeNodeMetadata(type, options) {
|
|
165
|
+
switch (type.kind) {
|
|
166
|
+
case "array":
|
|
167
|
+
return {
|
|
168
|
+
...type,
|
|
169
|
+
items: resolveTypeNodeMetadata(type.items, options)
|
|
170
|
+
};
|
|
171
|
+
case "object":
|
|
172
|
+
return {
|
|
173
|
+
...type,
|
|
174
|
+
properties: type.properties.map((property) => resolveObjectPropertyMetadata(property, options))
|
|
175
|
+
};
|
|
176
|
+
case "record":
|
|
177
|
+
return {
|
|
178
|
+
...type,
|
|
179
|
+
valueType: resolveTypeNodeMetadata(type.valueType, options)
|
|
180
|
+
};
|
|
181
|
+
case "union":
|
|
182
|
+
return {
|
|
183
|
+
...type,
|
|
184
|
+
members: type.members.map((member) => resolveTypeNodeMetadata(member, options))
|
|
185
|
+
};
|
|
186
|
+
case "reference":
|
|
187
|
+
case "primitive":
|
|
188
|
+
case "enum":
|
|
189
|
+
case "dynamic":
|
|
190
|
+
case "custom":
|
|
191
|
+
return type;
|
|
192
|
+
default: {
|
|
193
|
+
const _exhaustive = type;
|
|
194
|
+
return _exhaustive;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function resolveObjectPropertyMetadata(property, options) {
|
|
199
|
+
const metadata = resolveResolvedMetadata(property.metadata, options.policy.field, {
|
|
200
|
+
surface: options.surface,
|
|
201
|
+
declarationKind: "field",
|
|
202
|
+
logicalName: property.name,
|
|
203
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
...property,
|
|
207
|
+
...metadata !== void 0 && { metadata },
|
|
208
|
+
type: resolveTypeNodeMetadata(property.type, options)
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function resolveFieldMetadataNode(field, options) {
|
|
212
|
+
const metadata = resolveResolvedMetadata(field.metadata, options.policy.field, {
|
|
213
|
+
surface: options.surface,
|
|
214
|
+
declarationKind: "field",
|
|
215
|
+
logicalName: field.name,
|
|
216
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
...field,
|
|
220
|
+
...metadata !== void 0 && { metadata },
|
|
221
|
+
type: resolveTypeNodeMetadata(field.type, options)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function resolveFormElementMetadata(element, options) {
|
|
225
|
+
switch (element.kind) {
|
|
226
|
+
case "field":
|
|
227
|
+
return resolveFieldMetadataNode(element, options);
|
|
228
|
+
case "group":
|
|
229
|
+
return {
|
|
230
|
+
...element,
|
|
231
|
+
elements: element.elements.map((child) => resolveFormElementMetadata(child, options))
|
|
232
|
+
};
|
|
233
|
+
case "conditional":
|
|
234
|
+
return {
|
|
235
|
+
...element,
|
|
236
|
+
elements: element.elements.map((child) => resolveFormElementMetadata(child, options))
|
|
237
|
+
};
|
|
238
|
+
default: {
|
|
239
|
+
const _exhaustive = element;
|
|
240
|
+
return _exhaustive;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function resolveTypeDefinitionMetadata(typeDefinition, options) {
|
|
245
|
+
const metadata = resolveResolvedMetadata(typeDefinition.metadata, options.policy.type, {
|
|
246
|
+
surface: options.surface,
|
|
247
|
+
declarationKind: "type",
|
|
248
|
+
logicalName: typeDefinition.name,
|
|
249
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
250
|
+
});
|
|
251
|
+
return {
|
|
252
|
+
...typeDefinition,
|
|
253
|
+
...metadata !== void 0 && { metadata },
|
|
254
|
+
type: resolveTypeNodeMetadata(typeDefinition.type, options)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function resolveMetadata(explicit, policy, context) {
|
|
258
|
+
return resolveResolvedMetadata(toExplicitResolvedMetadata(explicit), policy, context);
|
|
259
|
+
}
|
|
260
|
+
function mergeResolvedMetadata(baseMetadata, overlayMetadata) {
|
|
261
|
+
const apiName = pickResolvedMetadataValue(baseMetadata?.apiName, overlayMetadata?.apiName);
|
|
262
|
+
const displayName = pickResolvedMetadataValue(
|
|
263
|
+
baseMetadata?.displayName,
|
|
264
|
+
overlayMetadata?.displayName
|
|
265
|
+
);
|
|
266
|
+
const apiNamePlural = pickResolvedMetadataValue(
|
|
267
|
+
baseMetadata?.apiNamePlural,
|
|
268
|
+
overlayMetadata?.apiNamePlural
|
|
269
|
+
);
|
|
270
|
+
const displayNamePlural = pickResolvedMetadataValue(
|
|
271
|
+
baseMetadata?.displayNamePlural,
|
|
272
|
+
overlayMetadata?.displayNamePlural
|
|
273
|
+
);
|
|
274
|
+
if (apiName === void 0 && displayName === void 0 && apiNamePlural === void 0 && displayNamePlural === void 0) {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
...apiName !== void 0 && { apiName },
|
|
279
|
+
...displayName !== void 0 && { displayName },
|
|
280
|
+
...apiNamePlural !== void 0 && { apiNamePlural },
|
|
281
|
+
...displayNamePlural !== void 0 && { displayNamePlural }
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function getSerializedName(logicalName, metadata) {
|
|
285
|
+
return metadata?.apiName?.value ?? logicalName;
|
|
286
|
+
}
|
|
287
|
+
function getDisplayName(metadata) {
|
|
288
|
+
return metadata?.displayName?.value;
|
|
289
|
+
}
|
|
290
|
+
function resolveFormIRMetadata(ir, options) {
|
|
291
|
+
const rootLogicalName = options.rootLogicalName ?? ir.name ?? "FormSpec";
|
|
292
|
+
const metadata = resolveResolvedMetadata(ir.metadata, options.policy.type, {
|
|
293
|
+
surface: options.surface,
|
|
294
|
+
declarationKind: "type",
|
|
295
|
+
logicalName: rootLogicalName,
|
|
296
|
+
...options.buildContext !== void 0 && { buildContext: options.buildContext }
|
|
297
|
+
});
|
|
298
|
+
return {
|
|
299
|
+
...ir,
|
|
300
|
+
...metadata !== void 0 && { metadata },
|
|
301
|
+
elements: ir.elements.map((element) => resolveFormElementMetadata(element, options)),
|
|
302
|
+
typeRegistry: Object.fromEntries(
|
|
303
|
+
Object.entries(ir.typeRegistry).map(([name, definition]) => [
|
|
304
|
+
name,
|
|
305
|
+
resolveTypeDefinitionMetadata(definition, options)
|
|
306
|
+
])
|
|
307
|
+
)
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/canonicalize/chain-dsl-canonicalizer.ts
|
|
3
312
|
var CHAIN_DSL_PROVENANCE = {
|
|
4
313
|
surface: "chain-dsl",
|
|
5
314
|
file: "",
|
|
@@ -15,57 +324,60 @@ function isConditional(el) {
|
|
|
15
324
|
function isField(el) {
|
|
16
325
|
return el._type === "field";
|
|
17
326
|
}
|
|
18
|
-
function canonicalizeChainDSL(form) {
|
|
327
|
+
function canonicalizeChainDSL(form, options) {
|
|
328
|
+
const metadataPolicy = normalizeMetadataPolicy(
|
|
329
|
+
options?.metadata ?? _getFormSpecMetadataPolicy(form)
|
|
330
|
+
);
|
|
19
331
|
return {
|
|
20
332
|
kind: "form-ir",
|
|
21
333
|
irVersion: IR_VERSION,
|
|
22
|
-
elements: canonicalizeElements(form.elements),
|
|
334
|
+
elements: canonicalizeElements(form.elements, metadataPolicy),
|
|
23
335
|
rootAnnotations: [],
|
|
24
336
|
typeRegistry: {},
|
|
25
337
|
provenance: CHAIN_DSL_PROVENANCE
|
|
26
338
|
};
|
|
27
339
|
}
|
|
28
|
-
function canonicalizeElements(elements) {
|
|
29
|
-
return elements.map(canonicalizeElement);
|
|
340
|
+
function canonicalizeElements(elements, metadataPolicy) {
|
|
341
|
+
return elements.map((element) => canonicalizeElement(element, metadataPolicy));
|
|
30
342
|
}
|
|
31
|
-
function canonicalizeElement(element) {
|
|
343
|
+
function canonicalizeElement(element, metadataPolicy) {
|
|
32
344
|
if (isField(element)) {
|
|
33
|
-
return canonicalizeField(element);
|
|
345
|
+
return canonicalizeField(element, metadataPolicy);
|
|
34
346
|
}
|
|
35
347
|
if (isGroup(element)) {
|
|
36
|
-
return canonicalizeGroup(element);
|
|
348
|
+
return canonicalizeGroup(element, metadataPolicy);
|
|
37
349
|
}
|
|
38
350
|
if (isConditional(element)) {
|
|
39
|
-
return canonicalizeConditional(element);
|
|
351
|
+
return canonicalizeConditional(element, metadataPolicy);
|
|
40
352
|
}
|
|
41
353
|
const _exhaustive = element;
|
|
42
354
|
throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);
|
|
43
355
|
}
|
|
44
|
-
function canonicalizeField(field) {
|
|
356
|
+
function canonicalizeField(field, metadataPolicy) {
|
|
45
357
|
switch (field._field) {
|
|
46
358
|
case "text":
|
|
47
|
-
return canonicalizeTextField(field);
|
|
359
|
+
return canonicalizeTextField(field, metadataPolicy);
|
|
48
360
|
case "number":
|
|
49
|
-
return canonicalizeNumberField(field);
|
|
361
|
+
return canonicalizeNumberField(field, metadataPolicy);
|
|
50
362
|
case "boolean":
|
|
51
|
-
return canonicalizeBooleanField(field);
|
|
363
|
+
return canonicalizeBooleanField(field, metadataPolicy);
|
|
52
364
|
case "enum":
|
|
53
|
-
return canonicalizeStaticEnumField(field);
|
|
365
|
+
return canonicalizeStaticEnumField(field, metadataPolicy);
|
|
54
366
|
case "dynamic_enum":
|
|
55
|
-
return canonicalizeDynamicEnumField(field);
|
|
367
|
+
return canonicalizeDynamicEnumField(field, metadataPolicy);
|
|
56
368
|
case "dynamic_schema":
|
|
57
|
-
return canonicalizeDynamicSchemaField(field);
|
|
369
|
+
return canonicalizeDynamicSchemaField(field, metadataPolicy);
|
|
58
370
|
case "array":
|
|
59
|
-
return canonicalizeArrayField(field);
|
|
371
|
+
return canonicalizeArrayField(field, metadataPolicy);
|
|
60
372
|
case "object":
|
|
61
|
-
return canonicalizeObjectField(field);
|
|
373
|
+
return canonicalizeObjectField(field, metadataPolicy);
|
|
62
374
|
default: {
|
|
63
375
|
const _exhaustive = field;
|
|
64
376
|
throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);
|
|
65
377
|
}
|
|
66
378
|
}
|
|
67
379
|
}
|
|
68
|
-
function canonicalizeTextField(field) {
|
|
380
|
+
function canonicalizeTextField(field, metadataPolicy) {
|
|
69
381
|
const type = { kind: "primitive", primitiveKind: "string" };
|
|
70
382
|
const constraints = [];
|
|
71
383
|
if (field.minLength !== void 0) {
|
|
@@ -97,13 +409,14 @@ function canonicalizeTextField(field) {
|
|
|
97
409
|
}
|
|
98
410
|
return buildFieldNode(
|
|
99
411
|
field.name,
|
|
412
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
100
413
|
type,
|
|
101
414
|
field.required,
|
|
102
|
-
buildAnnotations(field
|
|
415
|
+
buildAnnotations(getExplicitDisplayName(field), field.placeholder),
|
|
103
416
|
constraints
|
|
104
417
|
);
|
|
105
418
|
}
|
|
106
|
-
function canonicalizeNumberField(field) {
|
|
419
|
+
function canonicalizeNumberField(field, metadataPolicy) {
|
|
107
420
|
const type = { kind: "primitive", primitiveKind: "number" };
|
|
108
421
|
const constraints = [];
|
|
109
422
|
if (field.min !== void 0) {
|
|
@@ -135,17 +448,24 @@ function canonicalizeNumberField(field) {
|
|
|
135
448
|
}
|
|
136
449
|
return buildFieldNode(
|
|
137
450
|
field.name,
|
|
451
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
138
452
|
type,
|
|
139
453
|
field.required,
|
|
140
|
-
buildAnnotations(field
|
|
454
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
141
455
|
constraints
|
|
142
456
|
);
|
|
143
457
|
}
|
|
144
|
-
function canonicalizeBooleanField(field) {
|
|
458
|
+
function canonicalizeBooleanField(field, metadataPolicy) {
|
|
145
459
|
const type = { kind: "primitive", primitiveKind: "boolean" };
|
|
146
|
-
return buildFieldNode(
|
|
460
|
+
return buildFieldNode(
|
|
461
|
+
field.name,
|
|
462
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
463
|
+
type,
|
|
464
|
+
field.required,
|
|
465
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
466
|
+
);
|
|
147
467
|
}
|
|
148
|
-
function canonicalizeStaticEnumField(field) {
|
|
468
|
+
function canonicalizeStaticEnumField(field, metadataPolicy) {
|
|
149
469
|
const members = field.options.map((opt) => {
|
|
150
470
|
if (typeof opt === "string") {
|
|
151
471
|
return { value: opt };
|
|
@@ -153,28 +473,46 @@ function canonicalizeStaticEnumField(field) {
|
|
|
153
473
|
return { value: opt.id, displayName: opt.label };
|
|
154
474
|
});
|
|
155
475
|
const type = { kind: "enum", members };
|
|
156
|
-
return buildFieldNode(
|
|
476
|
+
return buildFieldNode(
|
|
477
|
+
field.name,
|
|
478
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
479
|
+
type,
|
|
480
|
+
field.required,
|
|
481
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
482
|
+
);
|
|
157
483
|
}
|
|
158
|
-
function canonicalizeDynamicEnumField(field) {
|
|
484
|
+
function canonicalizeDynamicEnumField(field, metadataPolicy) {
|
|
159
485
|
const type = {
|
|
160
486
|
kind: "dynamic",
|
|
161
487
|
dynamicKind: "enum",
|
|
162
488
|
sourceKey: field.source,
|
|
163
489
|
parameterFields: field.params ? [...field.params] : []
|
|
164
490
|
};
|
|
165
|
-
return buildFieldNode(
|
|
491
|
+
return buildFieldNode(
|
|
492
|
+
field.name,
|
|
493
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
494
|
+
type,
|
|
495
|
+
field.required,
|
|
496
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
497
|
+
);
|
|
166
498
|
}
|
|
167
|
-
function canonicalizeDynamicSchemaField(field) {
|
|
499
|
+
function canonicalizeDynamicSchemaField(field, metadataPolicy) {
|
|
168
500
|
const type = {
|
|
169
501
|
kind: "dynamic",
|
|
170
502
|
dynamicKind: "schema",
|
|
171
503
|
sourceKey: field.schemaSource,
|
|
172
504
|
parameterFields: []
|
|
173
505
|
};
|
|
174
|
-
return buildFieldNode(
|
|
506
|
+
return buildFieldNode(
|
|
507
|
+
field.name,
|
|
508
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
509
|
+
type,
|
|
510
|
+
field.required,
|
|
511
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
512
|
+
);
|
|
175
513
|
}
|
|
176
|
-
function canonicalizeArrayField(field) {
|
|
177
|
-
const itemProperties = buildObjectProperties(field.items);
|
|
514
|
+
function canonicalizeArrayField(field, metadataPolicy) {
|
|
515
|
+
const itemProperties = buildObjectProperties(field.items, metadataPolicy);
|
|
178
516
|
const itemsType = {
|
|
179
517
|
kind: "object",
|
|
180
518
|
properties: itemProperties,
|
|
@@ -202,37 +540,44 @@ function canonicalizeArrayField(field) {
|
|
|
202
540
|
}
|
|
203
541
|
return buildFieldNode(
|
|
204
542
|
field.name,
|
|
543
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
205
544
|
type,
|
|
206
545
|
field.required,
|
|
207
|
-
buildAnnotations(field
|
|
546
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
208
547
|
constraints
|
|
209
548
|
);
|
|
210
549
|
}
|
|
211
|
-
function canonicalizeObjectField(field) {
|
|
212
|
-
const properties = buildObjectProperties(field.properties);
|
|
550
|
+
function canonicalizeObjectField(field, metadataPolicy) {
|
|
551
|
+
const properties = buildObjectProperties(field.properties, metadataPolicy);
|
|
213
552
|
const type = {
|
|
214
553
|
kind: "object",
|
|
215
554
|
properties,
|
|
216
555
|
additionalProperties: true
|
|
217
556
|
};
|
|
218
|
-
return buildFieldNode(
|
|
557
|
+
return buildFieldNode(
|
|
558
|
+
field.name,
|
|
559
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
560
|
+
type,
|
|
561
|
+
field.required,
|
|
562
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
563
|
+
);
|
|
219
564
|
}
|
|
220
|
-
function canonicalizeGroup(g) {
|
|
565
|
+
function canonicalizeGroup(g, metadataPolicy) {
|
|
221
566
|
return {
|
|
222
567
|
kind: "group",
|
|
223
568
|
label: g.label,
|
|
224
|
-
elements: canonicalizeElements(g.elements),
|
|
569
|
+
elements: canonicalizeElements(g.elements, metadataPolicy),
|
|
225
570
|
provenance: CHAIN_DSL_PROVENANCE
|
|
226
571
|
};
|
|
227
572
|
}
|
|
228
|
-
function canonicalizeConditional(c) {
|
|
573
|
+
function canonicalizeConditional(c, metadataPolicy) {
|
|
229
574
|
return {
|
|
230
575
|
kind: "conditional",
|
|
231
576
|
fieldName: c.field,
|
|
232
577
|
// Conditional values from the chain DSL are JSON-serializable primitives
|
|
233
578
|
// (strings, numbers, booleans) produced by the `is()` predicate helper.
|
|
234
579
|
value: assertJsonValue(c.value),
|
|
235
|
-
elements: canonicalizeElements(c.elements),
|
|
580
|
+
elements: canonicalizeElements(c.elements, metadataPolicy),
|
|
236
581
|
provenance: CHAIN_DSL_PROVENANCE
|
|
237
582
|
};
|
|
238
583
|
}
|
|
@@ -252,10 +597,11 @@ function assertJsonValue(v) {
|
|
|
252
597
|
}
|
|
253
598
|
throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);
|
|
254
599
|
}
|
|
255
|
-
function buildFieldNode(name, type, required, annotations, constraints = []) {
|
|
600
|
+
function buildFieldNode(name, metadata, type, required, annotations, constraints = []) {
|
|
256
601
|
return {
|
|
257
602
|
kind: "field",
|
|
258
603
|
name,
|
|
604
|
+
...metadata !== void 0 && { metadata },
|
|
259
605
|
type,
|
|
260
606
|
required: required === true,
|
|
261
607
|
constraints,
|
|
@@ -285,13 +631,14 @@ function buildAnnotations(label, placeholder) {
|
|
|
285
631
|
}
|
|
286
632
|
return annotations;
|
|
287
633
|
}
|
|
288
|
-
function buildObjectProperties(elements, insideConditional = false) {
|
|
634
|
+
function buildObjectProperties(elements, metadataPolicy, insideConditional = false) {
|
|
289
635
|
const properties = [];
|
|
290
636
|
for (const el of elements) {
|
|
291
637
|
if (isField(el)) {
|
|
292
|
-
const fieldNode = canonicalizeField(el);
|
|
638
|
+
const fieldNode = canonicalizeField(el, metadataPolicy);
|
|
293
639
|
properties.push({
|
|
294
640
|
name: fieldNode.name,
|
|
641
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
295
642
|
type: fieldNode.type,
|
|
296
643
|
// Fields inside a conditional branch are always optional in the
|
|
297
644
|
// data schema, regardless of their `required` flag — the condition
|
|
@@ -302,17 +649,34 @@ function buildObjectProperties(elements, insideConditional = false) {
|
|
|
302
649
|
provenance: CHAIN_DSL_PROVENANCE
|
|
303
650
|
});
|
|
304
651
|
} else if (isGroup(el)) {
|
|
305
|
-
properties.push(...buildObjectProperties(el.elements, insideConditional));
|
|
652
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, insideConditional));
|
|
306
653
|
} else if (isConditional(el)) {
|
|
307
|
-
properties.push(...buildObjectProperties(el.elements, true));
|
|
654
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, true));
|
|
308
655
|
}
|
|
309
656
|
}
|
|
310
657
|
return properties;
|
|
311
658
|
}
|
|
659
|
+
function getExplicitDisplayName(field) {
|
|
660
|
+
if (field.label !== void 0 && field.displayName !== void 0) {
|
|
661
|
+
throw new Error('Chain DSL fields cannot specify both "label" and "displayName".');
|
|
662
|
+
}
|
|
663
|
+
return field.displayName ?? field.label;
|
|
664
|
+
}
|
|
665
|
+
function resolveFieldMetadata(logicalName, field, metadataPolicy) {
|
|
666
|
+
const displayName = getExplicitDisplayName(field);
|
|
667
|
+
return resolveMetadata(
|
|
668
|
+
{
|
|
669
|
+
...field.apiName !== void 0 && { apiName: field.apiName },
|
|
670
|
+
...displayName !== void 0 && { displayName }
|
|
671
|
+
},
|
|
672
|
+
getDeclarationMetadataPolicy(metadataPolicy, "field"),
|
|
673
|
+
makeMetadataContext("chain-dsl", "field", logicalName)
|
|
674
|
+
);
|
|
675
|
+
}
|
|
312
676
|
|
|
313
677
|
// src/canonicalize/tsdoc-canonicalizer.ts
|
|
314
678
|
import { IR_VERSION as IR_VERSION2 } from "@formspec/core/internals";
|
|
315
|
-
function canonicalizeTSDoc(analysis, source) {
|
|
679
|
+
function canonicalizeTSDoc(analysis, source, options) {
|
|
316
680
|
const file = source?.file ?? "";
|
|
317
681
|
const provenance = {
|
|
318
682
|
surface: "tsdoc",
|
|
@@ -321,15 +685,21 @@ function canonicalizeTSDoc(analysis, source) {
|
|
|
321
685
|
column: 0
|
|
322
686
|
};
|
|
323
687
|
const elements = assembleElements(analysis.fields, analysis.fieldLayouts, provenance);
|
|
324
|
-
|
|
688
|
+
const ir = {
|
|
325
689
|
kind: "form-ir",
|
|
690
|
+
name: analysis.name,
|
|
326
691
|
irVersion: IR_VERSION2,
|
|
327
692
|
elements,
|
|
693
|
+
...analysis.metadata !== void 0 && { metadata: analysis.metadata },
|
|
328
694
|
typeRegistry: analysis.typeRegistry,
|
|
329
695
|
...analysis.annotations !== void 0 && analysis.annotations.length > 0 && { rootAnnotations: analysis.annotations },
|
|
330
696
|
...analysis.annotations !== void 0 && analysis.annotations.length > 0 && { annotations: analysis.annotations },
|
|
331
697
|
provenance
|
|
332
698
|
};
|
|
699
|
+
return resolveFormIRMetadata(ir, {
|
|
700
|
+
policy: normalizeMetadataPolicy(options?.metadata),
|
|
701
|
+
surface: "tsdoc"
|
|
702
|
+
});
|
|
333
703
|
}
|
|
334
704
|
function assembleElements(fields, layouts, provenance) {
|
|
335
705
|
const elements = [];
|
|
@@ -386,6 +756,120 @@ function wrapInConditional(field, layout, provenance) {
|
|
|
386
756
|
return conditional;
|
|
387
757
|
}
|
|
388
758
|
|
|
759
|
+
// src/metadata/collision-guards.ts
|
|
760
|
+
function assertUniqueSerializedNames(entries, scope) {
|
|
761
|
+
const seen = /* @__PURE__ */ new Map();
|
|
762
|
+
for (const entry of entries) {
|
|
763
|
+
const previous = seen.get(entry.serializedName);
|
|
764
|
+
if (previous !== void 0) {
|
|
765
|
+
if (previous.logicalName === entry.logicalName && previous.category === entry.category) {
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
throw new Error(
|
|
769
|
+
`Serialized name collision in ${scope}: ${previous.category} "${previous.logicalName}" and ${entry.category} "${entry.logicalName}" both resolve to "${entry.serializedName}".`
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
seen.set(entry.serializedName, entry);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
function collectFlattenedFields(elements) {
|
|
776
|
+
const fields = [];
|
|
777
|
+
for (const element of elements) {
|
|
778
|
+
switch (element.kind) {
|
|
779
|
+
case "field":
|
|
780
|
+
fields.push(element);
|
|
781
|
+
break;
|
|
782
|
+
case "group":
|
|
783
|
+
case "conditional":
|
|
784
|
+
fields.push(...collectFlattenedFields(element.elements));
|
|
785
|
+
break;
|
|
786
|
+
default: {
|
|
787
|
+
const exhaustive = element;
|
|
788
|
+
void exhaustive;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return fields;
|
|
793
|
+
}
|
|
794
|
+
function validateObjectProperties(properties, scope) {
|
|
795
|
+
assertUniqueSerializedNames(
|
|
796
|
+
properties.map((property) => ({
|
|
797
|
+
logicalName: property.name,
|
|
798
|
+
serializedName: getSerializedName(property.name, property.metadata),
|
|
799
|
+
category: "object property"
|
|
800
|
+
})),
|
|
801
|
+
scope
|
|
802
|
+
);
|
|
803
|
+
for (const property of properties) {
|
|
804
|
+
validateTypeNode(
|
|
805
|
+
property.type,
|
|
806
|
+
`${scope}.${getSerializedName(property.name, property.metadata)}`
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function validateTypeNode(type, scope) {
|
|
811
|
+
switch (type.kind) {
|
|
812
|
+
case "array":
|
|
813
|
+
validateTypeNode(type.items, `${scope}[]`);
|
|
814
|
+
break;
|
|
815
|
+
case "object":
|
|
816
|
+
validateObjectProperties(type.properties, scope);
|
|
817
|
+
break;
|
|
818
|
+
case "record":
|
|
819
|
+
validateTypeNode(type.valueType, `${scope}.*`);
|
|
820
|
+
break;
|
|
821
|
+
case "union":
|
|
822
|
+
type.members.forEach((member, index) => {
|
|
823
|
+
validateTypeNode(member, `${scope}|${String(index)}`);
|
|
824
|
+
});
|
|
825
|
+
break;
|
|
826
|
+
case "reference":
|
|
827
|
+
case "primitive":
|
|
828
|
+
case "enum":
|
|
829
|
+
case "dynamic":
|
|
830
|
+
case "custom":
|
|
831
|
+
break;
|
|
832
|
+
default: {
|
|
833
|
+
const exhaustive = type;
|
|
834
|
+
void exhaustive;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
function validateTypeDefinitions(typeRegistry) {
|
|
839
|
+
const definitions = Object.values(typeRegistry);
|
|
840
|
+
assertUniqueSerializedNames(
|
|
841
|
+
definitions.map((definition) => ({
|
|
842
|
+
logicalName: definition.name,
|
|
843
|
+
serializedName: getSerializedName(definition.name, definition.metadata),
|
|
844
|
+
category: "type definition"
|
|
845
|
+
})),
|
|
846
|
+
"$defs"
|
|
847
|
+
);
|
|
848
|
+
for (const definition of definitions) {
|
|
849
|
+
validateTypeDefinition(definition);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
function validateTypeDefinition(definition) {
|
|
853
|
+
validateTypeNode(
|
|
854
|
+
definition.type,
|
|
855
|
+
`type "${getSerializedName(definition.name, definition.metadata)}"`
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
function assertNoSerializedNameCollisions(ir) {
|
|
859
|
+
assertUniqueSerializedNames(
|
|
860
|
+
collectFlattenedFields(ir.elements).map((field) => ({
|
|
861
|
+
logicalName: field.name,
|
|
862
|
+
serializedName: getSerializedName(field.name, field.metadata),
|
|
863
|
+
category: "field"
|
|
864
|
+
})),
|
|
865
|
+
"form root"
|
|
866
|
+
);
|
|
867
|
+
for (const field of collectFlattenedFields(ir.elements)) {
|
|
868
|
+
validateTypeNode(field.type, `field "${getSerializedName(field.name, field.metadata)}"`);
|
|
869
|
+
}
|
|
870
|
+
validateTypeDefinitions(ir.typeRegistry);
|
|
871
|
+
}
|
|
872
|
+
|
|
389
873
|
// src/json-schema/ir-generator.ts
|
|
390
874
|
function makeContext(options) {
|
|
391
875
|
const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
|
|
@@ -396,19 +880,33 @@ function makeContext(options) {
|
|
|
396
880
|
}
|
|
397
881
|
return {
|
|
398
882
|
defs: {},
|
|
883
|
+
typeNameMap: {},
|
|
884
|
+
typeRegistry: {},
|
|
399
885
|
extensionRegistry: options?.extensionRegistry,
|
|
400
886
|
vendorPrefix
|
|
401
887
|
};
|
|
402
888
|
}
|
|
403
889
|
function generateJsonSchemaFromIR(ir, options) {
|
|
404
|
-
|
|
890
|
+
assertNoSerializedNameCollisions(ir);
|
|
891
|
+
const ctx = {
|
|
892
|
+
...makeContext(options),
|
|
893
|
+
typeRegistry: ir.typeRegistry,
|
|
894
|
+
typeNameMap: Object.fromEntries(
|
|
895
|
+
Object.entries(ir.typeRegistry).map(([name, typeDef]) => [
|
|
896
|
+
name,
|
|
897
|
+
getSerializedName(name, typeDef.metadata)
|
|
898
|
+
])
|
|
899
|
+
)
|
|
900
|
+
};
|
|
405
901
|
for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {
|
|
406
|
-
ctx.
|
|
902
|
+
const schemaName = ctx.typeNameMap[name] ?? name;
|
|
903
|
+
ctx.defs[schemaName] = generateTypeNode(typeDef.type, ctx);
|
|
904
|
+
applyResolvedMetadata(ctx.defs[schemaName], typeDef.metadata);
|
|
407
905
|
if (typeDef.constraints && typeDef.constraints.length > 0) {
|
|
408
|
-
applyConstraints(ctx.defs[
|
|
906
|
+
applyConstraints(ctx.defs[schemaName], typeDef.constraints, ctx);
|
|
409
907
|
}
|
|
410
908
|
if (typeDef.annotations && typeDef.annotations.length > 0) {
|
|
411
|
-
applyAnnotations(ctx.defs[
|
|
909
|
+
applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx);
|
|
412
910
|
}
|
|
413
911
|
}
|
|
414
912
|
const properties = {};
|
|
@@ -421,6 +919,7 @@ function generateJsonSchemaFromIR(ir, options) {
|
|
|
421
919
|
properties,
|
|
422
920
|
...uniqueRequired.length > 0 && { required: uniqueRequired }
|
|
423
921
|
};
|
|
922
|
+
applyResolvedMetadata(result, ir.metadata);
|
|
424
923
|
if (ir.annotations && ir.annotations.length > 0) {
|
|
425
924
|
applyAnnotations(result, ir.annotations, ctx);
|
|
426
925
|
}
|
|
@@ -433,9 +932,9 @@ function collectFields(elements, properties, required, ctx) {
|
|
|
433
932
|
for (const element of elements) {
|
|
434
933
|
switch (element.kind) {
|
|
435
934
|
case "field":
|
|
436
|
-
properties[element.name] = generateFieldSchema(element, ctx);
|
|
935
|
+
properties[getSerializedName(element.name, element.metadata)] = generateFieldSchema(element, ctx);
|
|
437
936
|
if (element.required) {
|
|
438
|
-
required.push(element.name);
|
|
937
|
+
required.push(getSerializedName(element.name, element.metadata));
|
|
439
938
|
}
|
|
440
939
|
break;
|
|
441
940
|
case "group":
|
|
@@ -479,6 +978,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
479
978
|
rootAnnotations.push(annotation);
|
|
480
979
|
}
|
|
481
980
|
}
|
|
981
|
+
applyResolvedMetadata(schema, field.metadata);
|
|
482
982
|
applyAnnotations(schema, rootAnnotations, ctx);
|
|
483
983
|
if (itemStringSchema !== void 0) {
|
|
484
984
|
applyAnnotations(itemStringSchema, itemAnnotations, ctx);
|
|
@@ -486,7 +986,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
486
986
|
if (pathConstraints.length === 0) {
|
|
487
987
|
return schema;
|
|
488
988
|
}
|
|
489
|
-
return applyPathTargetedConstraints(schema, pathConstraints, ctx);
|
|
989
|
+
return applyPathTargetedConstraints(schema, pathConstraints, ctx, field.type);
|
|
490
990
|
}
|
|
491
991
|
function isStringItemConstraint(constraint) {
|
|
492
992
|
switch (constraint.constraintKind) {
|
|
@@ -498,9 +998,11 @@ function isStringItemConstraint(constraint) {
|
|
|
498
998
|
return false;
|
|
499
999
|
}
|
|
500
1000
|
}
|
|
501
|
-
function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
1001
|
+
function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
|
|
502
1002
|
if (schema.type === "array" && schema.items) {
|
|
503
|
-
|
|
1003
|
+
const referencedType = typeNode?.kind === "reference" ? resolveReferencedType(typeNode, ctx) : void 0;
|
|
1004
|
+
const nestedType = typeNode?.kind === "array" ? typeNode.items : referencedType?.kind === "array" ? referencedType.items : void 0;
|
|
1005
|
+
schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx, nestedType);
|
|
504
1006
|
return schema;
|
|
505
1007
|
}
|
|
506
1008
|
const byTarget = /* @__PURE__ */ new Map();
|
|
@@ -515,7 +1017,7 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
|
515
1017
|
for (const [target, constraints] of byTarget) {
|
|
516
1018
|
const subSchema = {};
|
|
517
1019
|
applyConstraints(subSchema, constraints, ctx);
|
|
518
|
-
propertyOverrides[target] = subSchema;
|
|
1020
|
+
propertyOverrides[resolveSerializedPropertyName(target, typeNode, ctx)] = subSchema;
|
|
519
1021
|
}
|
|
520
1022
|
if (schema.$ref) {
|
|
521
1023
|
const { $ref, ...rest } = schema;
|
|
@@ -563,7 +1065,7 @@ function generateTypeNode(type, ctx) {
|
|
|
563
1065
|
case "union":
|
|
564
1066
|
return generateUnionType(type, ctx);
|
|
565
1067
|
case "reference":
|
|
566
|
-
return generateReferenceType(type);
|
|
1068
|
+
return generateReferenceType(type, ctx);
|
|
567
1069
|
case "dynamic":
|
|
568
1070
|
return generateDynamicType(type);
|
|
569
1071
|
case "custom":
|
|
@@ -604,9 +1106,10 @@ function generateObjectType(type, ctx) {
|
|
|
604
1106
|
const properties = {};
|
|
605
1107
|
const required = [];
|
|
606
1108
|
for (const prop of type.properties) {
|
|
607
|
-
|
|
1109
|
+
const propertyName = getSerializedName(prop.name, prop.metadata);
|
|
1110
|
+
properties[propertyName] = generatePropertySchema(prop, ctx);
|
|
608
1111
|
if (!prop.optional) {
|
|
609
|
-
required.push(
|
|
1112
|
+
required.push(propertyName);
|
|
610
1113
|
}
|
|
611
1114
|
}
|
|
612
1115
|
const schema = { type: "object", properties };
|
|
@@ -627,6 +1130,7 @@ function generateRecordType(type, ctx) {
|
|
|
627
1130
|
function generatePropertySchema(prop, ctx) {
|
|
628
1131
|
const schema = generateTypeNode(prop.type, ctx);
|
|
629
1132
|
applyConstraints(schema, prop.constraints, ctx);
|
|
1133
|
+
applyResolvedMetadata(schema, prop.metadata);
|
|
630
1134
|
applyAnnotations(schema, prop.annotations, ctx);
|
|
631
1135
|
return schema;
|
|
632
1136
|
}
|
|
@@ -655,8 +1159,28 @@ function isNullableUnion(type) {
|
|
|
655
1159
|
).length;
|
|
656
1160
|
return nullCount === 1;
|
|
657
1161
|
}
|
|
658
|
-
function generateReferenceType(type) {
|
|
659
|
-
return { $ref: `#/$defs/${type.name}` };
|
|
1162
|
+
function generateReferenceType(type, ctx) {
|
|
1163
|
+
return { $ref: `#/$defs/${ctx.typeNameMap[type.name] ?? type.name}` };
|
|
1164
|
+
}
|
|
1165
|
+
function applyResolvedMetadata(schema, metadata) {
|
|
1166
|
+
const displayName = getDisplayName(metadata);
|
|
1167
|
+
if (displayName !== void 0) {
|
|
1168
|
+
schema.title = displayName;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
function resolveReferencedType(type, ctx) {
|
|
1172
|
+
return ctx.typeRegistry[type.name]?.type;
|
|
1173
|
+
}
|
|
1174
|
+
function resolveSerializedPropertyName(logicalName, typeNode, ctx) {
|
|
1175
|
+
if (typeNode?.kind === "object") {
|
|
1176
|
+
const property = typeNode.properties.find((candidate) => candidate.name === logicalName);
|
|
1177
|
+
return property === void 0 ? logicalName : getSerializedName(property.name, property.metadata);
|
|
1178
|
+
}
|
|
1179
|
+
if (typeNode?.kind === "reference") {
|
|
1180
|
+
const referencedType = resolveReferencedType(typeNode, ctx);
|
|
1181
|
+
return referencedType === void 0 ? logicalName : resolveSerializedPropertyName(logicalName, referencedType, ctx);
|
|
1182
|
+
}
|
|
1183
|
+
return logicalName;
|
|
660
1184
|
}
|
|
661
1185
|
function generateDynamicType(type) {
|
|
662
1186
|
if (type.dynamicKind === "enum") {
|
|
@@ -736,7 +1260,7 @@ function applyAnnotations(schema, annotations, ctx) {
|
|
|
736
1260
|
for (const annotation of annotations) {
|
|
737
1261
|
switch (annotation.annotationKind) {
|
|
738
1262
|
case "displayName":
|
|
739
|
-
schema.title
|
|
1263
|
+
schema.title ??= annotation.value;
|
|
740
1264
|
break;
|
|
741
1265
|
case "description":
|
|
742
1266
|
schema.description = annotation.value;
|
|
@@ -823,7 +1347,10 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
|
|
|
823
1347
|
|
|
824
1348
|
// src/json-schema/generator.ts
|
|
825
1349
|
function generateJsonSchema(form, options) {
|
|
826
|
-
const ir = canonicalizeChainDSL(
|
|
1350
|
+
const ir = canonicalizeChainDSL(
|
|
1351
|
+
form,
|
|
1352
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1353
|
+
);
|
|
827
1354
|
const internalOptions = options?.vendorPrefix === void 0 ? void 0 : { vendorPrefix: options.vendorPrefix };
|
|
828
1355
|
return generateJsonSchemaFromIR(ir, internalOptions);
|
|
829
1356
|
}
|
|
@@ -993,13 +1520,21 @@ function combineRules(parentRule, childRule) {
|
|
|
993
1520
|
}
|
|
994
1521
|
};
|
|
995
1522
|
}
|
|
996
|
-
function
|
|
997
|
-
const
|
|
1523
|
+
function getFieldDisplayName(field) {
|
|
1524
|
+
const resolvedDisplayName = getDisplayName(field.metadata);
|
|
1525
|
+
if (resolvedDisplayName !== void 0) {
|
|
1526
|
+
return resolvedDisplayName;
|
|
1527
|
+
}
|
|
1528
|
+
return field.annotations.find((annotation) => annotation.annotationKind === "displayName")?.value;
|
|
1529
|
+
}
|
|
1530
|
+
function fieldNodeToControl(field, fieldNameMap, parentRule) {
|
|
998
1531
|
const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === "placeholder");
|
|
1532
|
+
const serializedName = fieldNameMap.get(field.name) ?? getSerializedName(field.name, field.metadata);
|
|
1533
|
+
const displayName = getFieldDisplayName(field);
|
|
999
1534
|
const control = {
|
|
1000
1535
|
type: "Control",
|
|
1001
|
-
scope: fieldToScope(
|
|
1002
|
-
...
|
|
1536
|
+
scope: fieldToScope(serializedName),
|
|
1537
|
+
...displayName !== void 0 && { label: displayName },
|
|
1003
1538
|
...placeholderAnnotation !== void 0 && {
|
|
1004
1539
|
options: { placeholder: placeholderAnnotation.value }
|
|
1005
1540
|
},
|
|
@@ -1007,30 +1542,30 @@ function fieldNodeToControl(field, parentRule) {
|
|
|
1007
1542
|
};
|
|
1008
1543
|
return control;
|
|
1009
1544
|
}
|
|
1010
|
-
function groupNodeToLayout(group, parentRule) {
|
|
1545
|
+
function groupNodeToLayout(group, fieldNameMap, parentRule) {
|
|
1011
1546
|
return {
|
|
1012
1547
|
type: "Group",
|
|
1013
1548
|
label: group.label,
|
|
1014
|
-
elements: irElementsToUiSchema(group.elements, parentRule),
|
|
1549
|
+
elements: irElementsToUiSchema(group.elements, fieldNameMap, parentRule),
|
|
1015
1550
|
...parentRule !== void 0 && { rule: parentRule }
|
|
1016
1551
|
};
|
|
1017
1552
|
}
|
|
1018
|
-
function irElementsToUiSchema(elements, parentRule) {
|
|
1553
|
+
function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
1019
1554
|
const result = [];
|
|
1020
1555
|
for (const element of elements) {
|
|
1021
1556
|
switch (element.kind) {
|
|
1022
1557
|
case "field": {
|
|
1023
|
-
result.push(fieldNodeToControl(element, parentRule));
|
|
1558
|
+
result.push(fieldNodeToControl(element, fieldNameMap, parentRule));
|
|
1024
1559
|
break;
|
|
1025
1560
|
}
|
|
1026
1561
|
case "group": {
|
|
1027
|
-
result.push(groupNodeToLayout(element, parentRule));
|
|
1562
|
+
result.push(groupNodeToLayout(element, fieldNameMap, parentRule));
|
|
1028
1563
|
break;
|
|
1029
1564
|
}
|
|
1030
1565
|
case "conditional": {
|
|
1031
|
-
const newRule = createShowRule(element.fieldName, element.value);
|
|
1566
|
+
const newRule = createShowRule(fieldNameMap.get(element.fieldName) ?? element.fieldName, element.value);
|
|
1032
1567
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
1033
|
-
const childElements = irElementsToUiSchema(element.elements, combinedRule);
|
|
1568
|
+
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
1034
1569
|
result.push(...childElements);
|
|
1035
1570
|
break;
|
|
1036
1571
|
}
|
|
@@ -1044,16 +1579,42 @@ function irElementsToUiSchema(elements, parentRule) {
|
|
|
1044
1579
|
return result;
|
|
1045
1580
|
}
|
|
1046
1581
|
function generateUiSchemaFromIR(ir) {
|
|
1582
|
+
assertNoSerializedNameCollisions(ir);
|
|
1583
|
+
const fieldNameMap = collectFieldNameMap(ir.elements);
|
|
1047
1584
|
const result = {
|
|
1048
1585
|
type: "VerticalLayout",
|
|
1049
|
-
elements: irElementsToUiSchema(ir.elements)
|
|
1586
|
+
elements: irElementsToUiSchema(ir.elements, fieldNameMap)
|
|
1050
1587
|
};
|
|
1051
1588
|
return parseOrThrow(uiSchema, result, "UI Schema");
|
|
1052
1589
|
}
|
|
1590
|
+
function collectFieldNameMap(elements) {
|
|
1591
|
+
const map = /* @__PURE__ */ new Map();
|
|
1592
|
+
for (const element of elements) {
|
|
1593
|
+
switch (element.kind) {
|
|
1594
|
+
case "field":
|
|
1595
|
+
map.set(element.name, getSerializedName(element.name, element.metadata));
|
|
1596
|
+
break;
|
|
1597
|
+
case "group":
|
|
1598
|
+
case "conditional":
|
|
1599
|
+
for (const [key, value] of collectFieldNameMap(element.elements)) {
|
|
1600
|
+
map.set(key, value);
|
|
1601
|
+
}
|
|
1602
|
+
break;
|
|
1603
|
+
default: {
|
|
1604
|
+
const _exhaustive = element;
|
|
1605
|
+
void _exhaustive;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
return map;
|
|
1610
|
+
}
|
|
1053
1611
|
|
|
1054
1612
|
// src/ui-schema/generator.ts
|
|
1055
|
-
function generateUiSchema(form) {
|
|
1056
|
-
const ir = canonicalizeChainDSL(
|
|
1613
|
+
function generateUiSchema(form, options) {
|
|
1614
|
+
const ir = canonicalizeChainDSL(
|
|
1615
|
+
form,
|
|
1616
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1617
|
+
);
|
|
1057
1618
|
return generateUiSchemaFromIR(ir);
|
|
1058
1619
|
}
|
|
1059
1620
|
|
|
@@ -2117,7 +2678,76 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
|
|
|
2117
2678
|
...hostType !== void 0 && { hostType }
|
|
2118
2679
|
};
|
|
2119
2680
|
}
|
|
2120
|
-
function
|
|
2681
|
+
function makeExplicitScalarMetadata(value) {
|
|
2682
|
+
return value === void 0 || value === "" ? void 0 : { value, source: "explicit" };
|
|
2683
|
+
}
|
|
2684
|
+
function extractExplicitMetadata(node) {
|
|
2685
|
+
let apiName;
|
|
2686
|
+
let displayName;
|
|
2687
|
+
let apiNamePlural;
|
|
2688
|
+
let displayNamePlural;
|
|
2689
|
+
for (const tag of getLeadingParsedTags(node)) {
|
|
2690
|
+
const value = tag.argumentText.trim();
|
|
2691
|
+
if (value === "") {
|
|
2692
|
+
continue;
|
|
2693
|
+
}
|
|
2694
|
+
if (tag.normalizedTagName === "apiName") {
|
|
2695
|
+
if (tag.target === null) {
|
|
2696
|
+
apiName ??= value;
|
|
2697
|
+
} else if (tag.target.kind === "variant") {
|
|
2698
|
+
if (tag.target.rawText === "singular") {
|
|
2699
|
+
apiName ??= value;
|
|
2700
|
+
} else if (tag.target.rawText === "plural") {
|
|
2701
|
+
apiNamePlural ??= value;
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
continue;
|
|
2705
|
+
}
|
|
2706
|
+
if (tag.normalizedTagName === "displayName") {
|
|
2707
|
+
if (tag.target === null) {
|
|
2708
|
+
displayName ??= value;
|
|
2709
|
+
} else if (tag.target.kind === "variant") {
|
|
2710
|
+
if (tag.target.rawText === "singular") {
|
|
2711
|
+
displayName ??= value;
|
|
2712
|
+
} else if (tag.target.rawText === "plural") {
|
|
2713
|
+
displayNamePlural ??= value;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
const resolvedApiName = makeExplicitScalarMetadata(apiName);
|
|
2719
|
+
const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
|
|
2720
|
+
const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
|
|
2721
|
+
const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
|
|
2722
|
+
const metadata = {
|
|
2723
|
+
...resolvedApiName !== void 0 && { apiName: resolvedApiName },
|
|
2724
|
+
...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
|
|
2725
|
+
...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
|
|
2726
|
+
...resolvedDisplayNamePlural !== void 0 && {
|
|
2727
|
+
displayNamePlural: resolvedDisplayNamePlural
|
|
2728
|
+
}
|
|
2729
|
+
};
|
|
2730
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
2731
|
+
}
|
|
2732
|
+
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
|
|
2733
|
+
const explicit = extractExplicitMetadata(node);
|
|
2734
|
+
return resolveMetadata(
|
|
2735
|
+
{
|
|
2736
|
+
...explicit?.apiName !== void 0 && { apiName: explicit.apiName.value },
|
|
2737
|
+
...explicit?.displayName !== void 0 && { displayName: explicit.displayName.value },
|
|
2738
|
+
...explicit?.apiNamePlural !== void 0 && {
|
|
2739
|
+
apiNamePlural: explicit.apiNamePlural.value
|
|
2740
|
+
},
|
|
2741
|
+
...explicit?.displayNamePlural !== void 0 && {
|
|
2742
|
+
displayNamePlural: explicit.displayNamePlural.value
|
|
2743
|
+
}
|
|
2744
|
+
},
|
|
2745
|
+
getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
|
|
2746
|
+
makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
|
|
2747
|
+
);
|
|
2748
|
+
}
|
|
2749
|
+
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2750
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2121
2751
|
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
2122
2752
|
const fields = [];
|
|
2123
2753
|
const fieldLayouts = [];
|
|
@@ -2144,6 +2774,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2144
2774
|
visiting,
|
|
2145
2775
|
diagnostics,
|
|
2146
2776
|
classType,
|
|
2777
|
+
normalizedMetadataPolicy,
|
|
2147
2778
|
extensionRegistry
|
|
2148
2779
|
);
|
|
2149
2780
|
if (fieldNode) {
|
|
@@ -2168,10 +2799,18 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2168
2799
|
classType,
|
|
2169
2800
|
checker,
|
|
2170
2801
|
file,
|
|
2171
|
-
diagnostics
|
|
2802
|
+
diagnostics,
|
|
2803
|
+
normalizedMetadataPolicy
|
|
2172
2804
|
);
|
|
2805
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, classDecl, {
|
|
2806
|
+
checker,
|
|
2807
|
+
declaration: classDecl,
|
|
2808
|
+
subjectType: classType,
|
|
2809
|
+
hostType: classType
|
|
2810
|
+
});
|
|
2173
2811
|
return {
|
|
2174
2812
|
name,
|
|
2813
|
+
...metadata !== void 0 && { metadata },
|
|
2175
2814
|
fields: specializedFields,
|
|
2176
2815
|
fieldLayouts,
|
|
2177
2816
|
typeRegistry,
|
|
@@ -2181,7 +2820,8 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry) {
|
|
|
2181
2820
|
staticMethods
|
|
2182
2821
|
};
|
|
2183
2822
|
}
|
|
2184
|
-
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry) {
|
|
2823
|
+
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2824
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2185
2825
|
const name = interfaceDecl.name.text;
|
|
2186
2826
|
const fields = [];
|
|
2187
2827
|
const typeRegistry = {};
|
|
@@ -2205,6 +2845,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2205
2845
|
visiting,
|
|
2206
2846
|
diagnostics,
|
|
2207
2847
|
interfaceType,
|
|
2848
|
+
normalizedMetadataPolicy,
|
|
2208
2849
|
extensionRegistry
|
|
2209
2850
|
);
|
|
2210
2851
|
if (fieldNode) {
|
|
@@ -2218,11 +2859,19 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2218
2859
|
interfaceType,
|
|
2219
2860
|
checker,
|
|
2220
2861
|
file,
|
|
2221
|
-
diagnostics
|
|
2862
|
+
diagnostics,
|
|
2863
|
+
normalizedMetadataPolicy
|
|
2222
2864
|
);
|
|
2223
2865
|
const fieldLayouts = specializedFields.map(() => ({}));
|
|
2866
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, interfaceDecl, {
|
|
2867
|
+
checker,
|
|
2868
|
+
declaration: interfaceDecl,
|
|
2869
|
+
subjectType: interfaceType,
|
|
2870
|
+
hostType: interfaceType
|
|
2871
|
+
});
|
|
2224
2872
|
return {
|
|
2225
2873
|
name,
|
|
2874
|
+
...metadata !== void 0 && { metadata },
|
|
2226
2875
|
fields: specializedFields,
|
|
2227
2876
|
fieldLayouts,
|
|
2228
2877
|
typeRegistry,
|
|
@@ -2232,7 +2881,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
2232
2881
|
staticMethods: []
|
|
2233
2882
|
};
|
|
2234
2883
|
}
|
|
2235
|
-
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry) {
|
|
2884
|
+
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
2236
2885
|
if (!ts3.isTypeLiteralNode(typeAlias.type)) {
|
|
2237
2886
|
const sourceFile = typeAlias.getSourceFile();
|
|
2238
2887
|
const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
|
|
@@ -2242,6 +2891,8 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2242
2891
|
error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`
|
|
2243
2892
|
};
|
|
2244
2893
|
}
|
|
2894
|
+
const typeLiteral = typeAlias.type;
|
|
2895
|
+
const normalizedMetadataPolicy = normalizeMetadataPolicy(metadataPolicy);
|
|
2245
2896
|
const name = typeAlias.name.text;
|
|
2246
2897
|
const fields = [];
|
|
2247
2898
|
const typeRegistry = {};
|
|
@@ -2255,7 +2906,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2255
2906
|
const annotations = [...typeAliasDoc.annotations];
|
|
2256
2907
|
diagnostics.push(...typeAliasDoc.diagnostics);
|
|
2257
2908
|
const visiting = /* @__PURE__ */ new Set();
|
|
2258
|
-
for (const member of
|
|
2909
|
+
for (const member of typeLiteral.members) {
|
|
2259
2910
|
if (ts3.isPropertySignature(member)) {
|
|
2260
2911
|
const fieldNode = analyzeInterfacePropertyToIR(
|
|
2261
2912
|
member,
|
|
@@ -2265,6 +2916,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2265
2916
|
visiting,
|
|
2266
2917
|
diagnostics,
|
|
2267
2918
|
aliasType,
|
|
2919
|
+
normalizedMetadataPolicy,
|
|
2268
2920
|
extensionRegistry
|
|
2269
2921
|
);
|
|
2270
2922
|
if (fieldNode) {
|
|
@@ -2278,12 +2930,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry)
|
|
|
2278
2930
|
aliasType,
|
|
2279
2931
|
checker,
|
|
2280
2932
|
file,
|
|
2281
|
-
diagnostics
|
|
2933
|
+
diagnostics,
|
|
2934
|
+
normalizedMetadataPolicy
|
|
2282
2935
|
);
|
|
2936
|
+
const metadata = resolveNodeMetadata(normalizedMetadataPolicy, "type", name, typeAlias, {
|
|
2937
|
+
checker,
|
|
2938
|
+
declaration: typeAlias,
|
|
2939
|
+
subjectType: aliasType,
|
|
2940
|
+
hostType: aliasType
|
|
2941
|
+
});
|
|
2283
2942
|
return {
|
|
2284
2943
|
ok: true,
|
|
2285
2944
|
analysis: {
|
|
2286
2945
|
name,
|
|
2946
|
+
...metadata !== void 0 && { metadata },
|
|
2287
2947
|
fields: specializedFields,
|
|
2288
2948
|
fieldLayouts: specializedFields.map(() => ({})),
|
|
2289
2949
|
typeRegistry,
|
|
@@ -2323,31 +2983,20 @@ function getLeadingParsedTags(node) {
|
|
|
2323
2983
|
}
|
|
2324
2984
|
return parsedTags;
|
|
2325
2985
|
}
|
|
2326
|
-
function
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
return member;
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2333
|
-
return null;
|
|
2334
|
-
}
|
|
2335
|
-
if (ts3.isInterfaceDeclaration(node)) {
|
|
2336
|
-
for (const member of node.members) {
|
|
2337
|
-
if (ts3.isPropertySignature(member) && ts3.isIdentifier(member.name) && member.name.text === fieldName) {
|
|
2338
|
-
return member;
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2986
|
+
function resolveDiscriminatorProperty(node, checker, fieldName) {
|
|
2987
|
+
const subjectType = checker.getTypeAtLocation(node);
|
|
2988
|
+
const propertySymbol = subjectType.getProperty(fieldName);
|
|
2989
|
+
if (propertySymbol === void 0) {
|
|
2341
2990
|
return null;
|
|
2342
2991
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2992
|
+
const declaration = propertySymbol.valueDeclaration ?? propertySymbol.declarations?.find(
|
|
2993
|
+
(candidate) => ts3.isPropertyDeclaration(candidate) || ts3.isPropertySignature(candidate)
|
|
2994
|
+
) ?? propertySymbol.declarations?.[0];
|
|
2995
|
+
return {
|
|
2996
|
+
declaration,
|
|
2997
|
+
type: checker.getTypeOfSymbolAtLocation(propertySymbol, declaration ?? node),
|
|
2998
|
+
optional: !!(propertySymbol.flags & ts3.SymbolFlags.Optional) || declaration !== void 0 && "questionToken" in declaration && declaration.questionToken !== void 0
|
|
2999
|
+
};
|
|
2351
3000
|
}
|
|
2352
3001
|
function isLocalTypeParameterName(node, typeParameterName) {
|
|
2353
3002
|
return node.typeParameters?.some((typeParameter) => typeParameter.name.text === typeParameterName) ?? false;
|
|
@@ -2440,8 +3089,8 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
|
2440
3089
|
);
|
|
2441
3090
|
return null;
|
|
2442
3091
|
}
|
|
2443
|
-
const
|
|
2444
|
-
if (
|
|
3092
|
+
const property = resolveDiscriminatorProperty(node, checker, directive.fieldName);
|
|
3093
|
+
if (property === null) {
|
|
2445
3094
|
diagnostics.push(
|
|
2446
3095
|
makeAnalysisDiagnostic(
|
|
2447
3096
|
"UNKNOWN_PATH_TARGET",
|
|
@@ -2451,36 +3100,35 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
|
2451
3100
|
);
|
|
2452
3101
|
return null;
|
|
2453
3102
|
}
|
|
2454
|
-
if (
|
|
3103
|
+
if (property.optional) {
|
|
2455
3104
|
diagnostics.push(
|
|
2456
3105
|
makeAnalysisDiagnostic(
|
|
2457
3106
|
"TYPE_MISMATCH",
|
|
2458
3107
|
`Discriminator field "${directive.fieldName}" must be required; optional discriminator fields are not supported.`,
|
|
2459
3108
|
directive.provenance,
|
|
2460
|
-
[provenanceForNode(
|
|
3109
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2461
3110
|
)
|
|
2462
3111
|
);
|
|
2463
3112
|
return null;
|
|
2464
3113
|
}
|
|
2465
|
-
|
|
2466
|
-
if (isNullishSemanticType(propertyType)) {
|
|
3114
|
+
if (isNullishSemanticType(property.type)) {
|
|
2467
3115
|
diagnostics.push(
|
|
2468
3116
|
makeAnalysisDiagnostic(
|
|
2469
3117
|
"TYPE_MISMATCH",
|
|
2470
3118
|
`Discriminator field "${directive.fieldName}" must not be nullable.`,
|
|
2471
3119
|
directive.provenance,
|
|
2472
|
-
[provenanceForNode(
|
|
3120
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2473
3121
|
)
|
|
2474
3122
|
);
|
|
2475
3123
|
return null;
|
|
2476
3124
|
}
|
|
2477
|
-
if (!isStringLikeSemanticType(
|
|
3125
|
+
if (!isStringLikeSemanticType(property.type)) {
|
|
2478
3126
|
diagnostics.push(
|
|
2479
3127
|
makeAnalysisDiagnostic(
|
|
2480
3128
|
"TYPE_MISMATCH",
|
|
2481
3129
|
`Discriminator field "${directive.fieldName}" must be string-like.`,
|
|
2482
3130
|
directive.provenance,
|
|
2483
|
-
[provenanceForNode(
|
|
3131
|
+
property.declaration !== void 0 ? [provenanceForNode(property.declaration, file)] : []
|
|
2484
3132
|
)
|
|
2485
3133
|
);
|
|
2486
3134
|
return null;
|
|
@@ -2501,25 +3149,58 @@ function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typ
|
|
|
2501
3149
|
const localTypeParameter = node.typeParameters?.[typeParameterIndex];
|
|
2502
3150
|
return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
|
|
2503
3151
|
}
|
|
2504
|
-
function
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
3152
|
+
function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker, provenance, diagnostics) {
|
|
3153
|
+
const propertySymbol = boundType.getProperty(fieldName);
|
|
3154
|
+
if (propertySymbol === void 0) {
|
|
3155
|
+
return void 0;
|
|
3156
|
+
}
|
|
3157
|
+
const declaration = propertySymbol.valueDeclaration ?? propertySymbol.declarations?.[0];
|
|
3158
|
+
const anchorNode = declaration ?? boundType.symbol.declarations?.[0] ?? null;
|
|
3159
|
+
const resolvedAnchorNode = anchorNode ?? resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
3160
|
+
if (resolvedAnchorNode === null) {
|
|
3161
|
+
return void 0;
|
|
3162
|
+
}
|
|
3163
|
+
const propertyType = checker.getTypeOfSymbolAtLocation(
|
|
3164
|
+
propertySymbol,
|
|
3165
|
+
resolvedAnchorNode
|
|
3166
|
+
);
|
|
3167
|
+
if (propertyType.isStringLiteral()) {
|
|
3168
|
+
return propertyType.value;
|
|
3169
|
+
}
|
|
3170
|
+
if (propertyType.isUnion()) {
|
|
3171
|
+
const nonNullMembers = propertyType.types.filter(
|
|
3172
|
+
(member) => !(member.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined))
|
|
3173
|
+
);
|
|
3174
|
+
if (nonNullMembers.length > 0 && nonNullMembers.every((member) => member.isStringLiteral())) {
|
|
3175
|
+
diagnostics.push(
|
|
3176
|
+
makeAnalysisDiagnostic(
|
|
3177
|
+
"INVALID_TAG_ARGUMENT",
|
|
3178
|
+
"Discriminator resolution for union-valued identity properties is out of scope for v1.",
|
|
3179
|
+
provenance
|
|
3180
|
+
)
|
|
3181
|
+
);
|
|
3182
|
+
return null;
|
|
2517
3183
|
}
|
|
2518
3184
|
}
|
|
2519
|
-
return
|
|
3185
|
+
return void 0;
|
|
2520
3186
|
}
|
|
2521
|
-
function
|
|
2522
|
-
|
|
3187
|
+
function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
3188
|
+
const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
3189
|
+
if (declaration === null) {
|
|
3190
|
+
return void 0;
|
|
3191
|
+
}
|
|
3192
|
+
const metadata = resolveNodeMetadata(
|
|
3193
|
+
metadataPolicy,
|
|
3194
|
+
"type",
|
|
3195
|
+
getDiscriminatorLogicalName(boundType, declaration, checker),
|
|
3196
|
+
declaration,
|
|
3197
|
+
{
|
|
3198
|
+
checker,
|
|
3199
|
+
declaration,
|
|
3200
|
+
subjectType: boundType
|
|
3201
|
+
}
|
|
3202
|
+
);
|
|
3203
|
+
return metadata?.apiName;
|
|
2523
3204
|
}
|
|
2524
3205
|
function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2525
3206
|
if (seen.has(type)) {
|
|
@@ -2546,7 +3227,7 @@ function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__
|
|
|
2546
3227
|
}
|
|
2547
3228
|
return null;
|
|
2548
3229
|
}
|
|
2549
|
-
function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics) {
|
|
3230
|
+
function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, diagnostics, metadataPolicy) {
|
|
2550
3231
|
if (boundType === null) {
|
|
2551
3232
|
diagnostics.push(
|
|
2552
3233
|
makeAnalysisDiagnostic(
|
|
@@ -2575,9 +3256,22 @@ function resolveDiscriminatorValue(boundType, checker, provenance, diagnostics)
|
|
|
2575
3256
|
return null;
|
|
2576
3257
|
}
|
|
2577
3258
|
}
|
|
2578
|
-
const
|
|
2579
|
-
|
|
2580
|
-
|
|
3259
|
+
const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
|
|
3260
|
+
boundType,
|
|
3261
|
+
fieldName,
|
|
3262
|
+
checker,
|
|
3263
|
+
provenance,
|
|
3264
|
+
diagnostics
|
|
3265
|
+
);
|
|
3266
|
+
if (literalIdentityValue !== void 0) {
|
|
3267
|
+
return literalIdentityValue;
|
|
3268
|
+
}
|
|
3269
|
+
const apiName = resolveDiscriminatorApiName(boundType, checker, metadataPolicy);
|
|
3270
|
+
if (apiName?.source === "explicit") {
|
|
3271
|
+
return apiName.value;
|
|
3272
|
+
}
|
|
3273
|
+
if (apiName?.source === "inferred") {
|
|
3274
|
+
return apiName.value;
|
|
2581
3275
|
}
|
|
2582
3276
|
diagnostics.push(
|
|
2583
3277
|
makeAnalysisDiagnostic(
|
|
@@ -2594,7 +3288,15 @@ function getDeclarationName(node) {
|
|
|
2594
3288
|
}
|
|
2595
3289
|
return "anonymous";
|
|
2596
3290
|
}
|
|
2597
|
-
function
|
|
3291
|
+
function getResolvedTypeArguments(type) {
|
|
3292
|
+
return (isTypeReference(type) ? type.typeArguments : void 0) ?? type.aliasTypeArguments ?? [];
|
|
3293
|
+
}
|
|
3294
|
+
function getDiscriminatorLogicalName(type, declaration, checker) {
|
|
3295
|
+
const baseName = getDeclarationName(declaration);
|
|
3296
|
+
const typeArguments = getResolvedTypeArguments(type);
|
|
3297
|
+
return typeArguments.length === 0 ? baseName : buildInstantiatedReferenceName(baseName, typeArguments, checker);
|
|
3298
|
+
}
|
|
3299
|
+
function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checker, file, diagnostics, metadataPolicy) {
|
|
2598
3300
|
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2599
3301
|
if (directive === null) {
|
|
2600
3302
|
return [...fields];
|
|
@@ -2606,9 +3308,11 @@ function applyDeclarationDiscriminatorToFields(fields, node, subjectType, checke
|
|
|
2606
3308
|
checker,
|
|
2607
3309
|
directive.typeParameterName
|
|
2608
3310
|
),
|
|
3311
|
+
directive.fieldName,
|
|
2609
3312
|
checker,
|
|
2610
3313
|
directive.provenance,
|
|
2611
|
-
diagnostics
|
|
3314
|
+
diagnostics,
|
|
3315
|
+
metadataPolicy
|
|
2612
3316
|
);
|
|
2613
3317
|
if (discriminatorValue === null) {
|
|
2614
3318
|
return [...fields];
|
|
@@ -2629,7 +3333,7 @@ function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
|
|
|
2629
3333
|
).filter((value) => value !== "");
|
|
2630
3334
|
return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
|
|
2631
3335
|
}
|
|
2632
|
-
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3336
|
+
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy, extensionRegistry, diagnostics) {
|
|
2633
3337
|
const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2634
3338
|
if (typeNode === void 0) {
|
|
2635
3339
|
return [];
|
|
@@ -2649,13 +3353,14 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
|
|
|
2649
3353
|
typeRegistry,
|
|
2650
3354
|
visiting,
|
|
2651
3355
|
argumentNode,
|
|
3356
|
+
metadataPolicy,
|
|
2652
3357
|
extensionRegistry,
|
|
2653
3358
|
diagnostics
|
|
2654
3359
|
)
|
|
2655
3360
|
};
|
|
2656
3361
|
});
|
|
2657
3362
|
}
|
|
2658
|
-
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics) {
|
|
3363
|
+
function applyDiscriminatorToObjectProperties(properties, node, subjectType, checker, file, diagnostics, metadataPolicy) {
|
|
2659
3364
|
const directive = validateDiscriminatorDirective(node, checker, file, diagnostics);
|
|
2660
3365
|
if (directive === null) {
|
|
2661
3366
|
return properties;
|
|
@@ -2667,9 +3372,11 @@ function applyDiscriminatorToObjectProperties(properties, node, subjectType, che
|
|
|
2667
3372
|
checker,
|
|
2668
3373
|
directive.typeParameterName
|
|
2669
3374
|
),
|
|
3375
|
+
directive.fieldName,
|
|
2670
3376
|
checker,
|
|
2671
3377
|
directive.provenance,
|
|
2672
|
-
diagnostics
|
|
3378
|
+
diagnostics,
|
|
3379
|
+
metadataPolicy
|
|
2673
3380
|
);
|
|
2674
3381
|
if (discriminatorValue === null) {
|
|
2675
3382
|
return properties;
|
|
@@ -2684,7 +3391,7 @@ function applyDiscriminatorToObjectProperties(properties, node, subjectType, che
|
|
|
2684
3391
|
} : property
|
|
2685
3392
|
);
|
|
2686
3393
|
}
|
|
2687
|
-
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
3394
|
+
function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
|
|
2688
3395
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2689
3396
|
return null;
|
|
2690
3397
|
}
|
|
@@ -2699,6 +3406,7 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2699
3406
|
typeRegistry,
|
|
2700
3407
|
visiting,
|
|
2701
3408
|
prop,
|
|
3409
|
+
metadataPolicy,
|
|
2702
3410
|
extensionRegistry,
|
|
2703
3411
|
diagnostics
|
|
2704
3412
|
);
|
|
@@ -2722,9 +3430,16 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2722
3430
|
annotations.push(defaultAnnotation);
|
|
2723
3431
|
}
|
|
2724
3432
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
3433
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
|
|
3434
|
+
checker,
|
|
3435
|
+
declaration: prop,
|
|
3436
|
+
subjectType: tsType,
|
|
3437
|
+
hostType
|
|
3438
|
+
});
|
|
2725
3439
|
return {
|
|
2726
3440
|
kind: "field",
|
|
2727
3441
|
name,
|
|
3442
|
+
...metadata !== void 0 && { metadata },
|
|
2728
3443
|
type,
|
|
2729
3444
|
required: !optional,
|
|
2730
3445
|
constraints,
|
|
@@ -2732,7 +3447,7 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2732
3447
|
provenance
|
|
2733
3448
|
};
|
|
2734
3449
|
}
|
|
2735
|
-
function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, extensionRegistry) {
|
|
3450
|
+
function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
|
|
2736
3451
|
if (!ts3.isIdentifier(prop.name)) {
|
|
2737
3452
|
return null;
|
|
2738
3453
|
}
|
|
@@ -2747,6 +3462,7 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2747
3462
|
typeRegistry,
|
|
2748
3463
|
visiting,
|
|
2749
3464
|
prop,
|
|
3465
|
+
metadataPolicy,
|
|
2750
3466
|
extensionRegistry,
|
|
2751
3467
|
diagnostics
|
|
2752
3468
|
);
|
|
@@ -2766,9 +3482,16 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2766
3482
|
let annotations = [];
|
|
2767
3483
|
annotations.push(...docResult.annotations);
|
|
2768
3484
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
3485
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "field", name, prop, {
|
|
3486
|
+
checker,
|
|
3487
|
+
declaration: prop,
|
|
3488
|
+
subjectType: tsType,
|
|
3489
|
+
hostType
|
|
3490
|
+
});
|
|
2769
3491
|
return {
|
|
2770
3492
|
kind: "field",
|
|
2771
3493
|
name,
|
|
3494
|
+
...metadata !== void 0 && { metadata },
|
|
2772
3495
|
type,
|
|
2773
3496
|
required: !optional,
|
|
2774
3497
|
constraints,
|
|
@@ -2893,7 +3616,7 @@ function getTypeNodeRegistrationName(typeNode) {
|
|
|
2893
3616
|
}
|
|
2894
3617
|
return null;
|
|
2895
3618
|
}
|
|
2896
|
-
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3619
|
+
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2897
3620
|
const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
|
|
2898
3621
|
if (customType) {
|
|
2899
3622
|
return customType;
|
|
@@ -2905,6 +3628,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2905
3628
|
typeRegistry,
|
|
2906
3629
|
visiting,
|
|
2907
3630
|
sourceNode,
|
|
3631
|
+
metadataPolicy,
|
|
2908
3632
|
extensionRegistry,
|
|
2909
3633
|
diagnostics
|
|
2910
3634
|
);
|
|
@@ -2949,6 +3673,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2949
3673
|
typeRegistry,
|
|
2950
3674
|
visiting,
|
|
2951
3675
|
sourceNode,
|
|
3676
|
+
metadataPolicy,
|
|
2952
3677
|
extensionRegistry,
|
|
2953
3678
|
diagnostics
|
|
2954
3679
|
);
|
|
@@ -2961,6 +3686,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2961
3686
|
typeRegistry,
|
|
2962
3687
|
visiting,
|
|
2963
3688
|
sourceNode,
|
|
3689
|
+
metadataPolicy,
|
|
2964
3690
|
extensionRegistry,
|
|
2965
3691
|
diagnostics
|
|
2966
3692
|
);
|
|
@@ -2973,13 +3699,14 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2973
3699
|
typeRegistry,
|
|
2974
3700
|
visiting,
|
|
2975
3701
|
sourceNode,
|
|
3702
|
+
metadataPolicy,
|
|
2976
3703
|
extensionRegistry,
|
|
2977
3704
|
diagnostics
|
|
2978
3705
|
);
|
|
2979
3706
|
}
|
|
2980
3707
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2981
3708
|
}
|
|
2982
|
-
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3709
|
+
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2983
3710
|
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
|
|
2984
3711
|
return null;
|
|
2985
3712
|
}
|
|
@@ -2999,14 +3726,21 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
|
|
|
2999
3726
|
file,
|
|
3000
3727
|
makeParseOptions(extensionRegistry)
|
|
3001
3728
|
);
|
|
3729
|
+
const metadata = resolveNodeMetadata(metadataPolicy, "type", aliasName, aliasDecl, {
|
|
3730
|
+
checker,
|
|
3731
|
+
declaration: aliasDecl,
|
|
3732
|
+
subjectType: aliasType
|
|
3733
|
+
});
|
|
3002
3734
|
typeRegistry[aliasName] = {
|
|
3003
3735
|
name: aliasName,
|
|
3736
|
+
...metadata !== void 0 && { metadata },
|
|
3004
3737
|
type: resolveAliasedPrimitiveTarget(
|
|
3005
3738
|
aliasType,
|
|
3006
3739
|
checker,
|
|
3007
3740
|
file,
|
|
3008
3741
|
typeRegistry,
|
|
3009
3742
|
visiting,
|
|
3743
|
+
metadataPolicy,
|
|
3010
3744
|
extensionRegistry,
|
|
3011
3745
|
diagnostics
|
|
3012
3746
|
),
|
|
@@ -3035,7 +3769,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
|
|
|
3035
3769
|
const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
|
|
3036
3770
|
return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
|
|
3037
3771
|
}
|
|
3038
|
-
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3772
|
+
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3039
3773
|
const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
|
|
3040
3774
|
if (nestedAliasDecl !== void 0) {
|
|
3041
3775
|
return resolveAliasedPrimitiveTarget(
|
|
@@ -3044,6 +3778,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
3044
3778
|
file,
|
|
3045
3779
|
typeRegistry,
|
|
3046
3780
|
visiting,
|
|
3781
|
+
metadataPolicy,
|
|
3047
3782
|
extensionRegistry,
|
|
3048
3783
|
diagnostics
|
|
3049
3784
|
);
|
|
@@ -3055,11 +3790,12 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
3055
3790
|
typeRegistry,
|
|
3056
3791
|
visiting,
|
|
3057
3792
|
void 0,
|
|
3793
|
+
metadataPolicy,
|
|
3058
3794
|
extensionRegistry,
|
|
3059
3795
|
diagnostics
|
|
3060
3796
|
);
|
|
3061
3797
|
}
|
|
3062
|
-
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3798
|
+
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3063
3799
|
const typeName = getNamedTypeName(type);
|
|
3064
3800
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
3065
3801
|
if (typeName && typeName in typeRegistry) {
|
|
@@ -3094,8 +3830,14 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3094
3830
|
return result;
|
|
3095
3831
|
}
|
|
3096
3832
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3833
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", typeName, namedDecl, {
|
|
3834
|
+
checker,
|
|
3835
|
+
declaration: namedDecl,
|
|
3836
|
+
subjectType: type
|
|
3837
|
+
}) : void 0;
|
|
3097
3838
|
typeRegistry[typeName] = {
|
|
3098
3839
|
name: typeName,
|
|
3840
|
+
...metadata !== void 0 && { metadata },
|
|
3099
3841
|
type: result,
|
|
3100
3842
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3101
3843
|
provenance: provenanceForDeclaration(namedDecl ?? sourceNode, file)
|
|
@@ -3149,6 +3891,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3149
3891
|
typeRegistry,
|
|
3150
3892
|
visiting,
|
|
3151
3893
|
nonNullMembers[0].sourceNode ?? sourceNode,
|
|
3894
|
+
metadataPolicy,
|
|
3152
3895
|
extensionRegistry,
|
|
3153
3896
|
diagnostics
|
|
3154
3897
|
);
|
|
@@ -3166,6 +3909,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3166
3909
|
typeRegistry,
|
|
3167
3910
|
visiting,
|
|
3168
3911
|
memberSourceNode ?? sourceNode,
|
|
3912
|
+
metadataPolicy,
|
|
3169
3913
|
extensionRegistry,
|
|
3170
3914
|
diagnostics
|
|
3171
3915
|
)
|
|
@@ -3175,7 +3919,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3175
3919
|
}
|
|
3176
3920
|
return registerNamed({ kind: "union", members });
|
|
3177
3921
|
}
|
|
3178
|
-
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, extensionRegistry, diagnostics) {
|
|
3922
|
+
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3179
3923
|
const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
|
|
3180
3924
|
const elementType = typeArgs?.[0];
|
|
3181
3925
|
const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
|
|
@@ -3186,12 +3930,13 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
3186
3930
|
typeRegistry,
|
|
3187
3931
|
visiting,
|
|
3188
3932
|
elementSourceNode,
|
|
3933
|
+
metadataPolicy,
|
|
3189
3934
|
extensionRegistry,
|
|
3190
3935
|
diagnostics
|
|
3191
3936
|
) : { kind: "primitive", primitiveKind: "string" };
|
|
3192
3937
|
return { kind: "array", items };
|
|
3193
3938
|
}
|
|
3194
|
-
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, extensionRegistry, diagnostics) {
|
|
3939
|
+
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3195
3940
|
if (type.getProperties().length > 0) {
|
|
3196
3941
|
return null;
|
|
3197
3942
|
}
|
|
@@ -3206,6 +3951,7 @@ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, exten
|
|
|
3206
3951
|
typeRegistry,
|
|
3207
3952
|
visiting,
|
|
3208
3953
|
void 0,
|
|
3954
|
+
metadataPolicy,
|
|
3209
3955
|
extensionRegistry,
|
|
3210
3956
|
diagnostics
|
|
3211
3957
|
);
|
|
@@ -3236,7 +3982,22 @@ function typeNodeContainsReference(type, targetName) {
|
|
|
3236
3982
|
}
|
|
3237
3983
|
}
|
|
3238
3984
|
}
|
|
3239
|
-
function
|
|
3985
|
+
function shouldEmitResolvedObjectProperty(property, declaration) {
|
|
3986
|
+
if (property.name.startsWith("__@")) {
|
|
3987
|
+
return false;
|
|
3988
|
+
}
|
|
3989
|
+
if (declaration !== void 0 && "name" in declaration && declaration.name !== void 0) {
|
|
3990
|
+
const name = declaration.name;
|
|
3991
|
+
if (ts3.isComputedPropertyName(name) || ts3.isPrivateIdentifier(name)) {
|
|
3992
|
+
return false;
|
|
3993
|
+
}
|
|
3994
|
+
if (!ts3.isIdentifier(name) && !ts3.isStringLiteral(name) && !ts3.isNumericLiteral(name)) {
|
|
3995
|
+
return false;
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
return true;
|
|
3999
|
+
}
|
|
4000
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = normalizeMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
3240
4001
|
const collectedDiagnostics = diagnostics ?? [];
|
|
3241
4002
|
const typeName = getNamedTypeName(type);
|
|
3242
4003
|
const namedTypeName = typeName ?? void 0;
|
|
@@ -3248,6 +4009,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3248
4009
|
typeRegistry,
|
|
3249
4010
|
visiting,
|
|
3250
4011
|
sourceNode,
|
|
4012
|
+
metadataPolicy,
|
|
3251
4013
|
extensionRegistry,
|
|
3252
4014
|
collectedDiagnostics
|
|
3253
4015
|
);
|
|
@@ -3298,6 +4060,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3298
4060
|
file,
|
|
3299
4061
|
typeRegistry,
|
|
3300
4062
|
visiting,
|
|
4063
|
+
metadataPolicy,
|
|
3301
4064
|
extensionRegistry,
|
|
3302
4065
|
collectedDiagnostics
|
|
3303
4066
|
);
|
|
@@ -3310,8 +4073,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3310
4073
|
return recordNode;
|
|
3311
4074
|
}
|
|
3312
4075
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
4076
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
|
|
4077
|
+
checker,
|
|
4078
|
+
declaration: namedDecl,
|
|
4079
|
+
subjectType: type
|
|
4080
|
+
}) : void 0;
|
|
3313
4081
|
typeRegistry[registryTypeName] = {
|
|
3314
4082
|
name: registryTypeName,
|
|
4083
|
+
...metadata !== void 0 && { metadata },
|
|
3315
4084
|
type: recordNode,
|
|
3316
4085
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3317
4086
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
@@ -3331,12 +4100,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3331
4100
|
file,
|
|
3332
4101
|
typeRegistry,
|
|
3333
4102
|
visiting,
|
|
4103
|
+
metadataPolicy,
|
|
3334
4104
|
collectedDiagnostics,
|
|
3335
4105
|
extensionRegistry
|
|
3336
4106
|
);
|
|
3337
4107
|
for (const prop of type.getProperties()) {
|
|
3338
4108
|
const declaration = prop.valueDeclaration ?? prop.declarations?.[0];
|
|
3339
4109
|
if (!declaration) continue;
|
|
4110
|
+
if (!shouldEmitResolvedObjectProperty(prop, declaration)) continue;
|
|
3340
4111
|
const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);
|
|
3341
4112
|
const optional = !!(prop.flags & ts3.SymbolFlags.Optional);
|
|
3342
4113
|
const propTypeNode = resolveTypeNode(
|
|
@@ -3346,12 +4117,14 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3346
4117
|
typeRegistry,
|
|
3347
4118
|
visiting,
|
|
3348
4119
|
declaration,
|
|
4120
|
+
metadataPolicy,
|
|
3349
4121
|
extensionRegistry,
|
|
3350
4122
|
collectedDiagnostics
|
|
3351
4123
|
);
|
|
3352
4124
|
const fieldNodeInfo = fieldInfoMap?.get(prop.name);
|
|
3353
4125
|
properties.push({
|
|
3354
4126
|
name: prop.name,
|
|
4127
|
+
...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
|
|
3355
4128
|
type: propTypeNode,
|
|
3356
4129
|
optional,
|
|
3357
4130
|
constraints: fieldNodeInfo?.constraints ?? [],
|
|
@@ -3368,14 +4141,21 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3368
4141
|
type,
|
|
3369
4142
|
checker,
|
|
3370
4143
|
file,
|
|
3371
|
-
collectedDiagnostics
|
|
4144
|
+
collectedDiagnostics,
|
|
4145
|
+
metadataPolicy
|
|
3372
4146
|
) : properties,
|
|
3373
4147
|
additionalProperties: true
|
|
3374
4148
|
};
|
|
3375
4149
|
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3376
4150
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
4151
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(metadataPolicy, "type", registryTypeName, namedDecl, {
|
|
4152
|
+
checker,
|
|
4153
|
+
declaration: namedDecl,
|
|
4154
|
+
subjectType: type
|
|
4155
|
+
}) : void 0;
|
|
3377
4156
|
typeRegistry[registryTypeName] = {
|
|
3378
4157
|
name: registryTypeName,
|
|
4158
|
+
...metadata !== void 0 && { metadata },
|
|
3379
4159
|
type: objectNode,
|
|
3380
4160
|
...annotations !== void 0 && annotations.length > 0 && { annotations },
|
|
3381
4161
|
provenance: provenanceForDeclaration(namedDecl, file)
|
|
@@ -3388,7 +4168,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3388
4168
|
}
|
|
3389
4169
|
return objectNode;
|
|
3390
4170
|
}
|
|
3391
|
-
function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visiting, diagnostics, extensionRegistry) {
|
|
4171
|
+
function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visiting, metadataPolicy, diagnostics, extensionRegistry) {
|
|
3392
4172
|
const symbols = [type.getSymbol(), type.aliasSymbol].filter(
|
|
3393
4173
|
(s) => s?.declarations != null && s.declarations.length > 0
|
|
3394
4174
|
);
|
|
@@ -3409,10 +4189,12 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3409
4189
|
visiting,
|
|
3410
4190
|
diagnostics,
|
|
3411
4191
|
hostType,
|
|
4192
|
+
metadataPolicy,
|
|
3412
4193
|
extensionRegistry
|
|
3413
4194
|
);
|
|
3414
4195
|
if (fieldNode) {
|
|
3415
4196
|
map.set(fieldNode.name, {
|
|
4197
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
3416
4198
|
constraints: [...fieldNode.constraints],
|
|
3417
4199
|
annotations: [...fieldNode.annotations],
|
|
3418
4200
|
provenance: fieldNode.provenance
|
|
@@ -3430,6 +4212,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3430
4212
|
file,
|
|
3431
4213
|
typeRegistry,
|
|
3432
4214
|
visiting,
|
|
4215
|
+
metadataPolicy,
|
|
3433
4216
|
checker.getTypeAtLocation(interfaceDecl),
|
|
3434
4217
|
diagnostics,
|
|
3435
4218
|
extensionRegistry
|
|
@@ -3443,6 +4226,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3443
4226
|
file,
|
|
3444
4227
|
typeRegistry,
|
|
3445
4228
|
visiting,
|
|
4229
|
+
metadataPolicy,
|
|
3446
4230
|
checker.getTypeAtLocation(typeAliasDecl),
|
|
3447
4231
|
diagnostics,
|
|
3448
4232
|
extensionRegistry
|
|
@@ -3494,7 +4278,7 @@ function isNullishTypeNode(typeNode) {
|
|
|
3494
4278
|
}
|
|
3495
4279
|
return ts3.isLiteralTypeNode(typeNode) && (typeNode.literal.kind === ts3.SyntaxKind.NullKeyword || typeNode.literal.kind === ts3.SyntaxKind.UndefinedKeyword);
|
|
3496
4280
|
}
|
|
3497
|
-
function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, hostType, diagnostics, extensionRegistry) {
|
|
4281
|
+
function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, metadataPolicy, hostType, diagnostics, extensionRegistry) {
|
|
3498
4282
|
const map = /* @__PURE__ */ new Map();
|
|
3499
4283
|
for (const member of members) {
|
|
3500
4284
|
if (ts3.isPropertySignature(member)) {
|
|
@@ -3506,10 +4290,12 @@ function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, h
|
|
|
3506
4290
|
visiting,
|
|
3507
4291
|
diagnostics,
|
|
3508
4292
|
hostType,
|
|
4293
|
+
metadataPolicy,
|
|
3509
4294
|
extensionRegistry
|
|
3510
4295
|
);
|
|
3511
4296
|
if (fieldNode) {
|
|
3512
4297
|
map.set(fieldNode.name, {
|
|
4298
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
3513
4299
|
constraints: [...fieldNode.constraints],
|
|
3514
4300
|
annotations: [...fieldNode.annotations],
|
|
3515
4301
|
provenance: fieldNode.provenance
|
|
@@ -3540,6 +4326,7 @@ function extractTypeAliasConstraintNodes(typeNode, checker, file, extensionRegis
|
|
|
3540
4326
|
{},
|
|
3541
4327
|
/* @__PURE__ */ new Set(),
|
|
3542
4328
|
aliasDecl.type,
|
|
4329
|
+
void 0,
|
|
3543
4330
|
extensionRegistry
|
|
3544
4331
|
);
|
|
3545
4332
|
const constraints = extractJSDocConstraintNodes(
|
|
@@ -3725,19 +4512,37 @@ function findInterfaceByName(sourceFile, interfaceName) {
|
|
|
3725
4512
|
function findTypeAliasByName(sourceFile, aliasName) {
|
|
3726
4513
|
return findNodeByName(sourceFile, aliasName, ts4.isTypeAliasDeclaration, (n) => n.name.text);
|
|
3727
4514
|
}
|
|
3728
|
-
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry) {
|
|
4515
|
+
function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy) {
|
|
3729
4516
|
const ctx = createProgramContext(filePath);
|
|
3730
|
-
return analyzeNamedTypeToIRFromProgramContext(
|
|
4517
|
+
return analyzeNamedTypeToIRFromProgramContext(
|
|
4518
|
+
ctx,
|
|
4519
|
+
filePath,
|
|
4520
|
+
typeName,
|
|
4521
|
+
extensionRegistry,
|
|
4522
|
+
metadataPolicy
|
|
4523
|
+
);
|
|
3731
4524
|
}
|
|
3732
|
-
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry) {
|
|
4525
|
+
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy) {
|
|
3733
4526
|
const analysisFilePath = path.resolve(filePath);
|
|
3734
4527
|
const classDecl = findClassByName(ctx.sourceFile, typeName);
|
|
3735
4528
|
if (classDecl !== null) {
|
|
3736
|
-
return analyzeClassToIR(
|
|
4529
|
+
return analyzeClassToIR(
|
|
4530
|
+
classDecl,
|
|
4531
|
+
ctx.checker,
|
|
4532
|
+
analysisFilePath,
|
|
4533
|
+
extensionRegistry,
|
|
4534
|
+
metadataPolicy
|
|
4535
|
+
);
|
|
3737
4536
|
}
|
|
3738
4537
|
const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
|
|
3739
4538
|
if (interfaceDecl !== null) {
|
|
3740
|
-
return analyzeInterfaceToIR(
|
|
4539
|
+
return analyzeInterfaceToIR(
|
|
4540
|
+
interfaceDecl,
|
|
4541
|
+
ctx.checker,
|
|
4542
|
+
analysisFilePath,
|
|
4543
|
+
extensionRegistry,
|
|
4544
|
+
metadataPolicy
|
|
4545
|
+
);
|
|
3741
4546
|
}
|
|
3742
4547
|
const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
|
|
3743
4548
|
if (typeAlias !== null) {
|
|
@@ -3745,7 +4550,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
|
|
|
3745
4550
|
typeAlias,
|
|
3746
4551
|
ctx.checker,
|
|
3747
4552
|
analysisFilePath,
|
|
3748
|
-
extensionRegistry
|
|
4553
|
+
extensionRegistry,
|
|
4554
|
+
metadataPolicy
|
|
3749
4555
|
);
|
|
3750
4556
|
if (result.ok) {
|
|
3751
4557
|
return result.analysis;
|
|
@@ -3840,7 +4646,11 @@ function generateClassSchemas(analysis, source, options) {
|
|
|
3840
4646
|
if (errorDiagnostics !== void 0 && errorDiagnostics.length > 0) {
|
|
3841
4647
|
throw new Error(formatValidationError(errorDiagnostics));
|
|
3842
4648
|
}
|
|
3843
|
-
const ir = canonicalizeTSDoc(
|
|
4649
|
+
const ir = canonicalizeTSDoc(
|
|
4650
|
+
analysis,
|
|
4651
|
+
source,
|
|
4652
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
4653
|
+
);
|
|
3844
4654
|
const validationResult = validateIR(ir, {
|
|
3845
4655
|
...options?.extensionRegistry !== void 0 && {
|
|
3846
4656
|
extensionRegistry: options.extensionRegistry
|
|
@@ -3877,13 +4687,15 @@ function generateSchemasFromClass(options) {
|
|
|
3877
4687
|
classDecl,
|
|
3878
4688
|
ctx.checker,
|
|
3879
4689
|
options.filePath,
|
|
3880
|
-
options.extensionRegistry
|
|
4690
|
+
options.extensionRegistry,
|
|
4691
|
+
options.metadata
|
|
3881
4692
|
);
|
|
3882
4693
|
return generateClassSchemas(
|
|
3883
4694
|
analysis,
|
|
3884
4695
|
{ file: options.filePath },
|
|
3885
4696
|
{
|
|
3886
4697
|
extensionRegistry: options.extensionRegistry,
|
|
4698
|
+
metadata: options.metadata,
|
|
3887
4699
|
vendorPrefix: options.vendorPrefix
|
|
3888
4700
|
}
|
|
3889
4701
|
);
|
|
@@ -3901,13 +4713,15 @@ function generateSchemasFromProgram(options) {
|
|
|
3901
4713
|
ctx,
|
|
3902
4714
|
options.filePath,
|
|
3903
4715
|
options.typeName,
|
|
3904
|
-
options.extensionRegistry
|
|
4716
|
+
options.extensionRegistry,
|
|
4717
|
+
options.metadata
|
|
3905
4718
|
);
|
|
3906
4719
|
return generateClassSchemas(
|
|
3907
4720
|
analysis,
|
|
3908
4721
|
{ file: options.filePath },
|
|
3909
4722
|
{
|
|
3910
4723
|
extensionRegistry: options.extensionRegistry,
|
|
4724
|
+
metadata: options.metadata,
|
|
3911
4725
|
vendorPrefix: options.vendorPrefix
|
|
3912
4726
|
}
|
|
3913
4727
|
);
|
|
@@ -3916,16 +4730,28 @@ function generateSchemasFromProgram(options) {
|
|
|
3916
4730
|
// src/generators/mixed-authoring.ts
|
|
3917
4731
|
function buildMixedAuthoringSchemas(options) {
|
|
3918
4732
|
const { filePath, typeName, overlays, ...schemaOptions } = options;
|
|
3919
|
-
const analysis = analyzeNamedTypeToIR(
|
|
3920
|
-
|
|
3921
|
-
|
|
4733
|
+
const analysis = analyzeNamedTypeToIR(
|
|
4734
|
+
filePath,
|
|
4735
|
+
typeName,
|
|
4736
|
+
schemaOptions.extensionRegistry,
|
|
4737
|
+
schemaOptions.metadata
|
|
4738
|
+
);
|
|
4739
|
+
const composedAnalysis = composeAnalysisWithOverlays(analysis, overlays, schemaOptions.metadata);
|
|
4740
|
+
const ir = canonicalizeTSDoc(
|
|
4741
|
+
composedAnalysis,
|
|
4742
|
+
{ file: filePath },
|
|
4743
|
+
schemaOptions.metadata !== void 0 ? { metadata: schemaOptions.metadata } : void 0
|
|
4744
|
+
);
|
|
3922
4745
|
return {
|
|
3923
4746
|
jsonSchema: generateJsonSchemaFromIR(ir, schemaOptions),
|
|
3924
4747
|
uiSchema: generateUiSchemaFromIR(ir)
|
|
3925
4748
|
};
|
|
3926
4749
|
}
|
|
3927
|
-
function composeAnalysisWithOverlays(analysis, overlays) {
|
|
3928
|
-
const overlayIR = canonicalizeChainDSL(
|
|
4750
|
+
function composeAnalysisWithOverlays(analysis, overlays, metadata) {
|
|
4751
|
+
const overlayIR = canonicalizeChainDSL(
|
|
4752
|
+
overlays,
|
|
4753
|
+
metadata !== void 0 ? { metadata } : void 0
|
|
4754
|
+
);
|
|
3929
4755
|
const overlayFields = collectOverlayFields(overlayIR.elements);
|
|
3930
4756
|
if (overlayFields.length === 0) {
|
|
3931
4757
|
return analysis;
|
|
@@ -3981,8 +4807,10 @@ function collectOverlayFields(elements) {
|
|
|
3981
4807
|
}
|
|
3982
4808
|
function mergeFieldOverlay(baseField, overlayField, typeRegistry) {
|
|
3983
4809
|
assertSupportedOverlayField(baseField, overlayField);
|
|
4810
|
+
const metadata = mergeResolvedMetadata(baseField.metadata, overlayField.metadata);
|
|
3984
4811
|
return {
|
|
3985
4812
|
...baseField,
|
|
4813
|
+
...metadata !== void 0 && { metadata },
|
|
3986
4814
|
type: mergeFieldType(baseField, overlayField, typeRegistry),
|
|
3987
4815
|
annotations: mergeAnnotations(baseField.annotations, overlayField.annotations)
|
|
3988
4816
|
};
|
|
@@ -4093,12 +4921,12 @@ function annotationKey(annotation) {
|
|
|
4093
4921
|
function buildFormSchemas(form, options) {
|
|
4094
4922
|
return {
|
|
4095
4923
|
jsonSchema: generateJsonSchema(form, options),
|
|
4096
|
-
uiSchema: generateUiSchema(form)
|
|
4924
|
+
uiSchema: generateUiSchema(form, options)
|
|
4097
4925
|
};
|
|
4098
4926
|
}
|
|
4099
4927
|
function writeSchemas(form, options) {
|
|
4100
|
-
const { outDir, name = "schema", indent = 2, vendorPrefix } = options;
|
|
4101
|
-
const buildOptions = vendorPrefix === void 0 ? void 0 : { vendorPrefix };
|
|
4928
|
+
const { outDir, name = "schema", indent = 2, vendorPrefix, metadata } = options;
|
|
4929
|
+
const buildOptions = vendorPrefix === void 0 && metadata === void 0 ? void 0 : { vendorPrefix, metadata };
|
|
4102
4930
|
const { jsonSchema, uiSchema: uiSchema2 } = buildFormSchemas(form, buildOptions);
|
|
4103
4931
|
if (!fs.existsSync(outDir)) {
|
|
4104
4932
|
fs.mkdirSync(outDir, { recursive: true });
|