@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/browser.js
CHANGED
|
@@ -1,5 +1,168 @@
|
|
|
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 resolveMetadata(explicit, policy, context) {
|
|
156
|
+
return resolveResolvedMetadata(toExplicitResolvedMetadata(explicit), policy, context);
|
|
157
|
+
}
|
|
158
|
+
function getSerializedName(logicalName, metadata) {
|
|
159
|
+
return metadata?.apiName?.value ?? logicalName;
|
|
160
|
+
}
|
|
161
|
+
function getDisplayName(metadata) {
|
|
162
|
+
return metadata?.displayName?.value;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/canonicalize/chain-dsl-canonicalizer.ts
|
|
3
166
|
var CHAIN_DSL_PROVENANCE = {
|
|
4
167
|
surface: "chain-dsl",
|
|
5
168
|
file: "",
|
|
@@ -15,57 +178,60 @@ function isConditional(el) {
|
|
|
15
178
|
function isField(el) {
|
|
16
179
|
return el._type === "field";
|
|
17
180
|
}
|
|
18
|
-
function canonicalizeChainDSL(form) {
|
|
181
|
+
function canonicalizeChainDSL(form, options) {
|
|
182
|
+
const metadataPolicy = normalizeMetadataPolicy(
|
|
183
|
+
options?.metadata ?? _getFormSpecMetadataPolicy(form)
|
|
184
|
+
);
|
|
19
185
|
return {
|
|
20
186
|
kind: "form-ir",
|
|
21
187
|
irVersion: IR_VERSION,
|
|
22
|
-
elements: canonicalizeElements(form.elements),
|
|
188
|
+
elements: canonicalizeElements(form.elements, metadataPolicy),
|
|
23
189
|
rootAnnotations: [],
|
|
24
190
|
typeRegistry: {},
|
|
25
191
|
provenance: CHAIN_DSL_PROVENANCE
|
|
26
192
|
};
|
|
27
193
|
}
|
|
28
|
-
function canonicalizeElements(elements) {
|
|
29
|
-
return elements.map(canonicalizeElement);
|
|
194
|
+
function canonicalizeElements(elements, metadataPolicy) {
|
|
195
|
+
return elements.map((element) => canonicalizeElement(element, metadataPolicy));
|
|
30
196
|
}
|
|
31
|
-
function canonicalizeElement(element) {
|
|
197
|
+
function canonicalizeElement(element, metadataPolicy) {
|
|
32
198
|
if (isField(element)) {
|
|
33
|
-
return canonicalizeField(element);
|
|
199
|
+
return canonicalizeField(element, metadataPolicy);
|
|
34
200
|
}
|
|
35
201
|
if (isGroup(element)) {
|
|
36
|
-
return canonicalizeGroup(element);
|
|
202
|
+
return canonicalizeGroup(element, metadataPolicy);
|
|
37
203
|
}
|
|
38
204
|
if (isConditional(element)) {
|
|
39
|
-
return canonicalizeConditional(element);
|
|
205
|
+
return canonicalizeConditional(element, metadataPolicy);
|
|
40
206
|
}
|
|
41
207
|
const _exhaustive = element;
|
|
42
208
|
throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);
|
|
43
209
|
}
|
|
44
|
-
function canonicalizeField(field) {
|
|
210
|
+
function canonicalizeField(field, metadataPolicy) {
|
|
45
211
|
switch (field._field) {
|
|
46
212
|
case "text":
|
|
47
|
-
return canonicalizeTextField(field);
|
|
213
|
+
return canonicalizeTextField(field, metadataPolicy);
|
|
48
214
|
case "number":
|
|
49
|
-
return canonicalizeNumberField(field);
|
|
215
|
+
return canonicalizeNumberField(field, metadataPolicy);
|
|
50
216
|
case "boolean":
|
|
51
|
-
return canonicalizeBooleanField(field);
|
|
217
|
+
return canonicalizeBooleanField(field, metadataPolicy);
|
|
52
218
|
case "enum":
|
|
53
|
-
return canonicalizeStaticEnumField(field);
|
|
219
|
+
return canonicalizeStaticEnumField(field, metadataPolicy);
|
|
54
220
|
case "dynamic_enum":
|
|
55
|
-
return canonicalizeDynamicEnumField(field);
|
|
221
|
+
return canonicalizeDynamicEnumField(field, metadataPolicy);
|
|
56
222
|
case "dynamic_schema":
|
|
57
|
-
return canonicalizeDynamicSchemaField(field);
|
|
223
|
+
return canonicalizeDynamicSchemaField(field, metadataPolicy);
|
|
58
224
|
case "array":
|
|
59
|
-
return canonicalizeArrayField(field);
|
|
225
|
+
return canonicalizeArrayField(field, metadataPolicy);
|
|
60
226
|
case "object":
|
|
61
|
-
return canonicalizeObjectField(field);
|
|
227
|
+
return canonicalizeObjectField(field, metadataPolicy);
|
|
62
228
|
default: {
|
|
63
229
|
const _exhaustive = field;
|
|
64
230
|
throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);
|
|
65
231
|
}
|
|
66
232
|
}
|
|
67
233
|
}
|
|
68
|
-
function canonicalizeTextField(field) {
|
|
234
|
+
function canonicalizeTextField(field, metadataPolicy) {
|
|
69
235
|
const type = { kind: "primitive", primitiveKind: "string" };
|
|
70
236
|
const constraints = [];
|
|
71
237
|
if (field.minLength !== void 0) {
|
|
@@ -97,13 +263,14 @@ function canonicalizeTextField(field) {
|
|
|
97
263
|
}
|
|
98
264
|
return buildFieldNode(
|
|
99
265
|
field.name,
|
|
266
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
100
267
|
type,
|
|
101
268
|
field.required,
|
|
102
|
-
buildAnnotations(field
|
|
269
|
+
buildAnnotations(getExplicitDisplayName(field), field.placeholder),
|
|
103
270
|
constraints
|
|
104
271
|
);
|
|
105
272
|
}
|
|
106
|
-
function canonicalizeNumberField(field) {
|
|
273
|
+
function canonicalizeNumberField(field, metadataPolicy) {
|
|
107
274
|
const type = { kind: "primitive", primitiveKind: "number" };
|
|
108
275
|
const constraints = [];
|
|
109
276
|
if (field.min !== void 0) {
|
|
@@ -135,17 +302,24 @@ function canonicalizeNumberField(field) {
|
|
|
135
302
|
}
|
|
136
303
|
return buildFieldNode(
|
|
137
304
|
field.name,
|
|
305
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
138
306
|
type,
|
|
139
307
|
field.required,
|
|
140
|
-
buildAnnotations(field
|
|
308
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
141
309
|
constraints
|
|
142
310
|
);
|
|
143
311
|
}
|
|
144
|
-
function canonicalizeBooleanField(field) {
|
|
312
|
+
function canonicalizeBooleanField(field, metadataPolicy) {
|
|
145
313
|
const type = { kind: "primitive", primitiveKind: "boolean" };
|
|
146
|
-
return buildFieldNode(
|
|
314
|
+
return buildFieldNode(
|
|
315
|
+
field.name,
|
|
316
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
317
|
+
type,
|
|
318
|
+
field.required,
|
|
319
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
320
|
+
);
|
|
147
321
|
}
|
|
148
|
-
function canonicalizeStaticEnumField(field) {
|
|
322
|
+
function canonicalizeStaticEnumField(field, metadataPolicy) {
|
|
149
323
|
const members = field.options.map((opt) => {
|
|
150
324
|
if (typeof opt === "string") {
|
|
151
325
|
return { value: opt };
|
|
@@ -153,28 +327,46 @@ function canonicalizeStaticEnumField(field) {
|
|
|
153
327
|
return { value: opt.id, displayName: opt.label };
|
|
154
328
|
});
|
|
155
329
|
const type = { kind: "enum", members };
|
|
156
|
-
return buildFieldNode(
|
|
330
|
+
return buildFieldNode(
|
|
331
|
+
field.name,
|
|
332
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
333
|
+
type,
|
|
334
|
+
field.required,
|
|
335
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
336
|
+
);
|
|
157
337
|
}
|
|
158
|
-
function canonicalizeDynamicEnumField(field) {
|
|
338
|
+
function canonicalizeDynamicEnumField(field, metadataPolicy) {
|
|
159
339
|
const type = {
|
|
160
340
|
kind: "dynamic",
|
|
161
341
|
dynamicKind: "enum",
|
|
162
342
|
sourceKey: field.source,
|
|
163
343
|
parameterFields: field.params ? [...field.params] : []
|
|
164
344
|
};
|
|
165
|
-
return buildFieldNode(
|
|
345
|
+
return buildFieldNode(
|
|
346
|
+
field.name,
|
|
347
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
348
|
+
type,
|
|
349
|
+
field.required,
|
|
350
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
351
|
+
);
|
|
166
352
|
}
|
|
167
|
-
function canonicalizeDynamicSchemaField(field) {
|
|
353
|
+
function canonicalizeDynamicSchemaField(field, metadataPolicy) {
|
|
168
354
|
const type = {
|
|
169
355
|
kind: "dynamic",
|
|
170
356
|
dynamicKind: "schema",
|
|
171
357
|
sourceKey: field.schemaSource,
|
|
172
358
|
parameterFields: []
|
|
173
359
|
};
|
|
174
|
-
return buildFieldNode(
|
|
360
|
+
return buildFieldNode(
|
|
361
|
+
field.name,
|
|
362
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
363
|
+
type,
|
|
364
|
+
field.required,
|
|
365
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
366
|
+
);
|
|
175
367
|
}
|
|
176
|
-
function canonicalizeArrayField(field) {
|
|
177
|
-
const itemProperties = buildObjectProperties(field.items);
|
|
368
|
+
function canonicalizeArrayField(field, metadataPolicy) {
|
|
369
|
+
const itemProperties = buildObjectProperties(field.items, metadataPolicy);
|
|
178
370
|
const itemsType = {
|
|
179
371
|
kind: "object",
|
|
180
372
|
properties: itemProperties,
|
|
@@ -202,37 +394,44 @@ function canonicalizeArrayField(field) {
|
|
|
202
394
|
}
|
|
203
395
|
return buildFieldNode(
|
|
204
396
|
field.name,
|
|
397
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
205
398
|
type,
|
|
206
399
|
field.required,
|
|
207
|
-
buildAnnotations(field
|
|
400
|
+
buildAnnotations(getExplicitDisplayName(field)),
|
|
208
401
|
constraints
|
|
209
402
|
);
|
|
210
403
|
}
|
|
211
|
-
function canonicalizeObjectField(field) {
|
|
212
|
-
const properties = buildObjectProperties(field.properties);
|
|
404
|
+
function canonicalizeObjectField(field, metadataPolicy) {
|
|
405
|
+
const properties = buildObjectProperties(field.properties, metadataPolicy);
|
|
213
406
|
const type = {
|
|
214
407
|
kind: "object",
|
|
215
408
|
properties,
|
|
216
409
|
additionalProperties: true
|
|
217
410
|
};
|
|
218
|
-
return buildFieldNode(
|
|
411
|
+
return buildFieldNode(
|
|
412
|
+
field.name,
|
|
413
|
+
resolveFieldMetadata(field.name, field, metadataPolicy),
|
|
414
|
+
type,
|
|
415
|
+
field.required,
|
|
416
|
+
buildAnnotations(getExplicitDisplayName(field))
|
|
417
|
+
);
|
|
219
418
|
}
|
|
220
|
-
function canonicalizeGroup(g) {
|
|
419
|
+
function canonicalizeGroup(g, metadataPolicy) {
|
|
221
420
|
return {
|
|
222
421
|
kind: "group",
|
|
223
422
|
label: g.label,
|
|
224
|
-
elements: canonicalizeElements(g.elements),
|
|
423
|
+
elements: canonicalizeElements(g.elements, metadataPolicy),
|
|
225
424
|
provenance: CHAIN_DSL_PROVENANCE
|
|
226
425
|
};
|
|
227
426
|
}
|
|
228
|
-
function canonicalizeConditional(c) {
|
|
427
|
+
function canonicalizeConditional(c, metadataPolicy) {
|
|
229
428
|
return {
|
|
230
429
|
kind: "conditional",
|
|
231
430
|
fieldName: c.field,
|
|
232
431
|
// Conditional values from the chain DSL are JSON-serializable primitives
|
|
233
432
|
// (strings, numbers, booleans) produced by the `is()` predicate helper.
|
|
234
433
|
value: assertJsonValue(c.value),
|
|
235
|
-
elements: canonicalizeElements(c.elements),
|
|
434
|
+
elements: canonicalizeElements(c.elements, metadataPolicy),
|
|
236
435
|
provenance: CHAIN_DSL_PROVENANCE
|
|
237
436
|
};
|
|
238
437
|
}
|
|
@@ -252,10 +451,11 @@ function assertJsonValue(v) {
|
|
|
252
451
|
}
|
|
253
452
|
throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);
|
|
254
453
|
}
|
|
255
|
-
function buildFieldNode(name, type, required, annotations, constraints = []) {
|
|
454
|
+
function buildFieldNode(name, metadata, type, required, annotations, constraints = []) {
|
|
256
455
|
return {
|
|
257
456
|
kind: "field",
|
|
258
457
|
name,
|
|
458
|
+
...metadata !== void 0 && { metadata },
|
|
259
459
|
type,
|
|
260
460
|
required: required === true,
|
|
261
461
|
constraints,
|
|
@@ -285,13 +485,14 @@ function buildAnnotations(label, placeholder) {
|
|
|
285
485
|
}
|
|
286
486
|
return annotations;
|
|
287
487
|
}
|
|
288
|
-
function buildObjectProperties(elements, insideConditional = false) {
|
|
488
|
+
function buildObjectProperties(elements, metadataPolicy, insideConditional = false) {
|
|
289
489
|
const properties = [];
|
|
290
490
|
for (const el of elements) {
|
|
291
491
|
if (isField(el)) {
|
|
292
|
-
const fieldNode = canonicalizeField(el);
|
|
492
|
+
const fieldNode = canonicalizeField(el, metadataPolicy);
|
|
293
493
|
properties.push({
|
|
294
494
|
name: fieldNode.name,
|
|
495
|
+
...fieldNode.metadata !== void 0 && { metadata: fieldNode.metadata },
|
|
295
496
|
type: fieldNode.type,
|
|
296
497
|
// Fields inside a conditional branch are always optional in the
|
|
297
498
|
// data schema, regardless of their `required` flag — the condition
|
|
@@ -302,17 +503,148 @@ function buildObjectProperties(elements, insideConditional = false) {
|
|
|
302
503
|
provenance: CHAIN_DSL_PROVENANCE
|
|
303
504
|
});
|
|
304
505
|
} else if (isGroup(el)) {
|
|
305
|
-
properties.push(...buildObjectProperties(el.elements, insideConditional));
|
|
506
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, insideConditional));
|
|
306
507
|
} else if (isConditional(el)) {
|
|
307
|
-
properties.push(...buildObjectProperties(el.elements, true));
|
|
508
|
+
properties.push(...buildObjectProperties(el.elements, metadataPolicy, true));
|
|
308
509
|
}
|
|
309
510
|
}
|
|
310
511
|
return properties;
|
|
311
512
|
}
|
|
513
|
+
function getExplicitDisplayName(field) {
|
|
514
|
+
if (field.label !== void 0 && field.displayName !== void 0) {
|
|
515
|
+
throw new Error('Chain DSL fields cannot specify both "label" and "displayName".');
|
|
516
|
+
}
|
|
517
|
+
return field.displayName ?? field.label;
|
|
518
|
+
}
|
|
519
|
+
function resolveFieldMetadata(logicalName, field, metadataPolicy) {
|
|
520
|
+
const displayName = getExplicitDisplayName(field);
|
|
521
|
+
return resolveMetadata(
|
|
522
|
+
{
|
|
523
|
+
...field.apiName !== void 0 && { apiName: field.apiName },
|
|
524
|
+
...displayName !== void 0 && { displayName }
|
|
525
|
+
},
|
|
526
|
+
getDeclarationMetadataPolicy(metadataPolicy, "field"),
|
|
527
|
+
makeMetadataContext("chain-dsl", "field", logicalName)
|
|
528
|
+
);
|
|
529
|
+
}
|
|
312
530
|
|
|
313
531
|
// src/canonicalize/tsdoc-canonicalizer.ts
|
|
314
532
|
import { IR_VERSION as IR_VERSION2 } from "@formspec/core/internals";
|
|
315
533
|
|
|
534
|
+
// src/metadata/collision-guards.ts
|
|
535
|
+
function assertUniqueSerializedNames(entries, scope) {
|
|
536
|
+
const seen = /* @__PURE__ */ new Map();
|
|
537
|
+
for (const entry of entries) {
|
|
538
|
+
const previous = seen.get(entry.serializedName);
|
|
539
|
+
if (previous !== void 0) {
|
|
540
|
+
if (previous.logicalName === entry.logicalName && previous.category === entry.category) {
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
throw new Error(
|
|
544
|
+
`Serialized name collision in ${scope}: ${previous.category} "${previous.logicalName}" and ${entry.category} "${entry.logicalName}" both resolve to "${entry.serializedName}".`
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
seen.set(entry.serializedName, entry);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
function collectFlattenedFields(elements) {
|
|
551
|
+
const fields = [];
|
|
552
|
+
for (const element of elements) {
|
|
553
|
+
switch (element.kind) {
|
|
554
|
+
case "field":
|
|
555
|
+
fields.push(element);
|
|
556
|
+
break;
|
|
557
|
+
case "group":
|
|
558
|
+
case "conditional":
|
|
559
|
+
fields.push(...collectFlattenedFields(element.elements));
|
|
560
|
+
break;
|
|
561
|
+
default: {
|
|
562
|
+
const exhaustive = element;
|
|
563
|
+
void exhaustive;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return fields;
|
|
568
|
+
}
|
|
569
|
+
function validateObjectProperties(properties, scope) {
|
|
570
|
+
assertUniqueSerializedNames(
|
|
571
|
+
properties.map((property) => ({
|
|
572
|
+
logicalName: property.name,
|
|
573
|
+
serializedName: getSerializedName(property.name, property.metadata),
|
|
574
|
+
category: "object property"
|
|
575
|
+
})),
|
|
576
|
+
scope
|
|
577
|
+
);
|
|
578
|
+
for (const property of properties) {
|
|
579
|
+
validateTypeNode(
|
|
580
|
+
property.type,
|
|
581
|
+
`${scope}.${getSerializedName(property.name, property.metadata)}`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function validateTypeNode(type, scope) {
|
|
586
|
+
switch (type.kind) {
|
|
587
|
+
case "array":
|
|
588
|
+
validateTypeNode(type.items, `${scope}[]`);
|
|
589
|
+
break;
|
|
590
|
+
case "object":
|
|
591
|
+
validateObjectProperties(type.properties, scope);
|
|
592
|
+
break;
|
|
593
|
+
case "record":
|
|
594
|
+
validateTypeNode(type.valueType, `${scope}.*`);
|
|
595
|
+
break;
|
|
596
|
+
case "union":
|
|
597
|
+
type.members.forEach((member, index) => {
|
|
598
|
+
validateTypeNode(member, `${scope}|${String(index)}`);
|
|
599
|
+
});
|
|
600
|
+
break;
|
|
601
|
+
case "reference":
|
|
602
|
+
case "primitive":
|
|
603
|
+
case "enum":
|
|
604
|
+
case "dynamic":
|
|
605
|
+
case "custom":
|
|
606
|
+
break;
|
|
607
|
+
default: {
|
|
608
|
+
const exhaustive = type;
|
|
609
|
+
void exhaustive;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function validateTypeDefinitions(typeRegistry) {
|
|
614
|
+
const definitions = Object.values(typeRegistry);
|
|
615
|
+
assertUniqueSerializedNames(
|
|
616
|
+
definitions.map((definition) => ({
|
|
617
|
+
logicalName: definition.name,
|
|
618
|
+
serializedName: getSerializedName(definition.name, definition.metadata),
|
|
619
|
+
category: "type definition"
|
|
620
|
+
})),
|
|
621
|
+
"$defs"
|
|
622
|
+
);
|
|
623
|
+
for (const definition of definitions) {
|
|
624
|
+
validateTypeDefinition(definition);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function validateTypeDefinition(definition) {
|
|
628
|
+
validateTypeNode(
|
|
629
|
+
definition.type,
|
|
630
|
+
`type "${getSerializedName(definition.name, definition.metadata)}"`
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
function assertNoSerializedNameCollisions(ir) {
|
|
634
|
+
assertUniqueSerializedNames(
|
|
635
|
+
collectFlattenedFields(ir.elements).map((field) => ({
|
|
636
|
+
logicalName: field.name,
|
|
637
|
+
serializedName: getSerializedName(field.name, field.metadata),
|
|
638
|
+
category: "field"
|
|
639
|
+
})),
|
|
640
|
+
"form root"
|
|
641
|
+
);
|
|
642
|
+
for (const field of collectFlattenedFields(ir.elements)) {
|
|
643
|
+
validateTypeNode(field.type, `field "${getSerializedName(field.name, field.metadata)}"`);
|
|
644
|
+
}
|
|
645
|
+
validateTypeDefinitions(ir.typeRegistry);
|
|
646
|
+
}
|
|
647
|
+
|
|
316
648
|
// src/json-schema/ir-generator.ts
|
|
317
649
|
function makeContext(options) {
|
|
318
650
|
const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
|
|
@@ -323,19 +655,33 @@ function makeContext(options) {
|
|
|
323
655
|
}
|
|
324
656
|
return {
|
|
325
657
|
defs: {},
|
|
658
|
+
typeNameMap: {},
|
|
659
|
+
typeRegistry: {},
|
|
326
660
|
extensionRegistry: options?.extensionRegistry,
|
|
327
661
|
vendorPrefix
|
|
328
662
|
};
|
|
329
663
|
}
|
|
330
664
|
function generateJsonSchemaFromIR(ir, options) {
|
|
331
|
-
|
|
665
|
+
assertNoSerializedNameCollisions(ir);
|
|
666
|
+
const ctx = {
|
|
667
|
+
...makeContext(options),
|
|
668
|
+
typeRegistry: ir.typeRegistry,
|
|
669
|
+
typeNameMap: Object.fromEntries(
|
|
670
|
+
Object.entries(ir.typeRegistry).map(([name, typeDef]) => [
|
|
671
|
+
name,
|
|
672
|
+
getSerializedName(name, typeDef.metadata)
|
|
673
|
+
])
|
|
674
|
+
)
|
|
675
|
+
};
|
|
332
676
|
for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {
|
|
333
|
-
ctx.
|
|
677
|
+
const schemaName = ctx.typeNameMap[name] ?? name;
|
|
678
|
+
ctx.defs[schemaName] = generateTypeNode(typeDef.type, ctx);
|
|
679
|
+
applyResolvedMetadata(ctx.defs[schemaName], typeDef.metadata);
|
|
334
680
|
if (typeDef.constraints && typeDef.constraints.length > 0) {
|
|
335
|
-
applyConstraints(ctx.defs[
|
|
681
|
+
applyConstraints(ctx.defs[schemaName], typeDef.constraints, ctx);
|
|
336
682
|
}
|
|
337
683
|
if (typeDef.annotations && typeDef.annotations.length > 0) {
|
|
338
|
-
applyAnnotations(ctx.defs[
|
|
684
|
+
applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx);
|
|
339
685
|
}
|
|
340
686
|
}
|
|
341
687
|
const properties = {};
|
|
@@ -348,6 +694,7 @@ function generateJsonSchemaFromIR(ir, options) {
|
|
|
348
694
|
properties,
|
|
349
695
|
...uniqueRequired.length > 0 && { required: uniqueRequired }
|
|
350
696
|
};
|
|
697
|
+
applyResolvedMetadata(result, ir.metadata);
|
|
351
698
|
if (ir.annotations && ir.annotations.length > 0) {
|
|
352
699
|
applyAnnotations(result, ir.annotations, ctx);
|
|
353
700
|
}
|
|
@@ -360,9 +707,9 @@ function collectFields(elements, properties, required, ctx) {
|
|
|
360
707
|
for (const element of elements) {
|
|
361
708
|
switch (element.kind) {
|
|
362
709
|
case "field":
|
|
363
|
-
properties[element.name] = generateFieldSchema(element, ctx);
|
|
710
|
+
properties[getSerializedName(element.name, element.metadata)] = generateFieldSchema(element, ctx);
|
|
364
711
|
if (element.required) {
|
|
365
|
-
required.push(element.name);
|
|
712
|
+
required.push(getSerializedName(element.name, element.metadata));
|
|
366
713
|
}
|
|
367
714
|
break;
|
|
368
715
|
case "group":
|
|
@@ -406,6 +753,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
406
753
|
rootAnnotations.push(annotation);
|
|
407
754
|
}
|
|
408
755
|
}
|
|
756
|
+
applyResolvedMetadata(schema, field.metadata);
|
|
409
757
|
applyAnnotations(schema, rootAnnotations, ctx);
|
|
410
758
|
if (itemStringSchema !== void 0) {
|
|
411
759
|
applyAnnotations(itemStringSchema, itemAnnotations, ctx);
|
|
@@ -413,7 +761,7 @@ function generateFieldSchema(field, ctx) {
|
|
|
413
761
|
if (pathConstraints.length === 0) {
|
|
414
762
|
return schema;
|
|
415
763
|
}
|
|
416
|
-
return applyPathTargetedConstraints(schema, pathConstraints, ctx);
|
|
764
|
+
return applyPathTargetedConstraints(schema, pathConstraints, ctx, field.type);
|
|
417
765
|
}
|
|
418
766
|
function isStringItemConstraint(constraint) {
|
|
419
767
|
switch (constraint.constraintKind) {
|
|
@@ -425,9 +773,11 @@ function isStringItemConstraint(constraint) {
|
|
|
425
773
|
return false;
|
|
426
774
|
}
|
|
427
775
|
}
|
|
428
|
-
function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
776
|
+
function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
|
|
429
777
|
if (schema.type === "array" && schema.items) {
|
|
430
|
-
|
|
778
|
+
const referencedType = typeNode?.kind === "reference" ? resolveReferencedType(typeNode, ctx) : void 0;
|
|
779
|
+
const nestedType = typeNode?.kind === "array" ? typeNode.items : referencedType?.kind === "array" ? referencedType.items : void 0;
|
|
780
|
+
schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx, nestedType);
|
|
431
781
|
return schema;
|
|
432
782
|
}
|
|
433
783
|
const byTarget = /* @__PURE__ */ new Map();
|
|
@@ -442,7 +792,7 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
|
|
|
442
792
|
for (const [target, constraints] of byTarget) {
|
|
443
793
|
const subSchema = {};
|
|
444
794
|
applyConstraints(subSchema, constraints, ctx);
|
|
445
|
-
propertyOverrides[target] = subSchema;
|
|
795
|
+
propertyOverrides[resolveSerializedPropertyName(target, typeNode, ctx)] = subSchema;
|
|
446
796
|
}
|
|
447
797
|
if (schema.$ref) {
|
|
448
798
|
const { $ref, ...rest } = schema;
|
|
@@ -490,7 +840,7 @@ function generateTypeNode(type, ctx) {
|
|
|
490
840
|
case "union":
|
|
491
841
|
return generateUnionType(type, ctx);
|
|
492
842
|
case "reference":
|
|
493
|
-
return generateReferenceType(type);
|
|
843
|
+
return generateReferenceType(type, ctx);
|
|
494
844
|
case "dynamic":
|
|
495
845
|
return generateDynamicType(type);
|
|
496
846
|
case "custom":
|
|
@@ -531,9 +881,10 @@ function generateObjectType(type, ctx) {
|
|
|
531
881
|
const properties = {};
|
|
532
882
|
const required = [];
|
|
533
883
|
for (const prop of type.properties) {
|
|
534
|
-
|
|
884
|
+
const propertyName = getSerializedName(prop.name, prop.metadata);
|
|
885
|
+
properties[propertyName] = generatePropertySchema(prop, ctx);
|
|
535
886
|
if (!prop.optional) {
|
|
536
|
-
required.push(
|
|
887
|
+
required.push(propertyName);
|
|
537
888
|
}
|
|
538
889
|
}
|
|
539
890
|
const schema = { type: "object", properties };
|
|
@@ -554,6 +905,7 @@ function generateRecordType(type, ctx) {
|
|
|
554
905
|
function generatePropertySchema(prop, ctx) {
|
|
555
906
|
const schema = generateTypeNode(prop.type, ctx);
|
|
556
907
|
applyConstraints(schema, prop.constraints, ctx);
|
|
908
|
+
applyResolvedMetadata(schema, prop.metadata);
|
|
557
909
|
applyAnnotations(schema, prop.annotations, ctx);
|
|
558
910
|
return schema;
|
|
559
911
|
}
|
|
@@ -582,8 +934,28 @@ function isNullableUnion(type) {
|
|
|
582
934
|
).length;
|
|
583
935
|
return nullCount === 1;
|
|
584
936
|
}
|
|
585
|
-
function generateReferenceType(type) {
|
|
586
|
-
return { $ref: `#/$defs/${type.name}` };
|
|
937
|
+
function generateReferenceType(type, ctx) {
|
|
938
|
+
return { $ref: `#/$defs/${ctx.typeNameMap[type.name] ?? type.name}` };
|
|
939
|
+
}
|
|
940
|
+
function applyResolvedMetadata(schema, metadata) {
|
|
941
|
+
const displayName = getDisplayName(metadata);
|
|
942
|
+
if (displayName !== void 0) {
|
|
943
|
+
schema.title = displayName;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
function resolveReferencedType(type, ctx) {
|
|
947
|
+
return ctx.typeRegistry[type.name]?.type;
|
|
948
|
+
}
|
|
949
|
+
function resolveSerializedPropertyName(logicalName, typeNode, ctx) {
|
|
950
|
+
if (typeNode?.kind === "object") {
|
|
951
|
+
const property = typeNode.properties.find((candidate) => candidate.name === logicalName);
|
|
952
|
+
return property === void 0 ? logicalName : getSerializedName(property.name, property.metadata);
|
|
953
|
+
}
|
|
954
|
+
if (typeNode?.kind === "reference") {
|
|
955
|
+
const referencedType = resolveReferencedType(typeNode, ctx);
|
|
956
|
+
return referencedType === void 0 ? logicalName : resolveSerializedPropertyName(logicalName, referencedType, ctx);
|
|
957
|
+
}
|
|
958
|
+
return logicalName;
|
|
587
959
|
}
|
|
588
960
|
function generateDynamicType(type) {
|
|
589
961
|
if (type.dynamicKind === "enum") {
|
|
@@ -663,7 +1035,7 @@ function applyAnnotations(schema, annotations, ctx) {
|
|
|
663
1035
|
for (const annotation of annotations) {
|
|
664
1036
|
switch (annotation.annotationKind) {
|
|
665
1037
|
case "displayName":
|
|
666
|
-
schema.title
|
|
1038
|
+
schema.title ??= annotation.value;
|
|
667
1039
|
break;
|
|
668
1040
|
case "description":
|
|
669
1041
|
schema.description = annotation.value;
|
|
@@ -750,7 +1122,10 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
|
|
|
750
1122
|
|
|
751
1123
|
// src/json-schema/generator.ts
|
|
752
1124
|
function generateJsonSchema(form, options) {
|
|
753
|
-
const ir = canonicalizeChainDSL(
|
|
1125
|
+
const ir = canonicalizeChainDSL(
|
|
1126
|
+
form,
|
|
1127
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1128
|
+
);
|
|
754
1129
|
const internalOptions = options?.vendorPrefix === void 0 ? void 0 : { vendorPrefix: options.vendorPrefix };
|
|
755
1130
|
return generateJsonSchemaFromIR(ir, internalOptions);
|
|
756
1131
|
}
|
|
@@ -920,13 +1295,21 @@ function combineRules(parentRule, childRule) {
|
|
|
920
1295
|
}
|
|
921
1296
|
};
|
|
922
1297
|
}
|
|
923
|
-
function
|
|
924
|
-
const
|
|
1298
|
+
function getFieldDisplayName(field) {
|
|
1299
|
+
const resolvedDisplayName = getDisplayName(field.metadata);
|
|
1300
|
+
if (resolvedDisplayName !== void 0) {
|
|
1301
|
+
return resolvedDisplayName;
|
|
1302
|
+
}
|
|
1303
|
+
return field.annotations.find((annotation) => annotation.annotationKind === "displayName")?.value;
|
|
1304
|
+
}
|
|
1305
|
+
function fieldNodeToControl(field, fieldNameMap, parentRule) {
|
|
925
1306
|
const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === "placeholder");
|
|
1307
|
+
const serializedName = fieldNameMap.get(field.name) ?? getSerializedName(field.name, field.metadata);
|
|
1308
|
+
const displayName = getFieldDisplayName(field);
|
|
926
1309
|
const control = {
|
|
927
1310
|
type: "Control",
|
|
928
|
-
scope: fieldToScope(
|
|
929
|
-
...
|
|
1311
|
+
scope: fieldToScope(serializedName),
|
|
1312
|
+
...displayName !== void 0 && { label: displayName },
|
|
930
1313
|
...placeholderAnnotation !== void 0 && {
|
|
931
1314
|
options: { placeholder: placeholderAnnotation.value }
|
|
932
1315
|
},
|
|
@@ -934,30 +1317,30 @@ function fieldNodeToControl(field, parentRule) {
|
|
|
934
1317
|
};
|
|
935
1318
|
return control;
|
|
936
1319
|
}
|
|
937
|
-
function groupNodeToLayout(group, parentRule) {
|
|
1320
|
+
function groupNodeToLayout(group, fieldNameMap, parentRule) {
|
|
938
1321
|
return {
|
|
939
1322
|
type: "Group",
|
|
940
1323
|
label: group.label,
|
|
941
|
-
elements: irElementsToUiSchema(group.elements, parentRule),
|
|
1324
|
+
elements: irElementsToUiSchema(group.elements, fieldNameMap, parentRule),
|
|
942
1325
|
...parentRule !== void 0 && { rule: parentRule }
|
|
943
1326
|
};
|
|
944
1327
|
}
|
|
945
|
-
function irElementsToUiSchema(elements, parentRule) {
|
|
1328
|
+
function irElementsToUiSchema(elements, fieldNameMap, parentRule) {
|
|
946
1329
|
const result = [];
|
|
947
1330
|
for (const element of elements) {
|
|
948
1331
|
switch (element.kind) {
|
|
949
1332
|
case "field": {
|
|
950
|
-
result.push(fieldNodeToControl(element, parentRule));
|
|
1333
|
+
result.push(fieldNodeToControl(element, fieldNameMap, parentRule));
|
|
951
1334
|
break;
|
|
952
1335
|
}
|
|
953
1336
|
case "group": {
|
|
954
|
-
result.push(groupNodeToLayout(element, parentRule));
|
|
1337
|
+
result.push(groupNodeToLayout(element, fieldNameMap, parentRule));
|
|
955
1338
|
break;
|
|
956
1339
|
}
|
|
957
1340
|
case "conditional": {
|
|
958
|
-
const newRule = createShowRule(element.fieldName, element.value);
|
|
1341
|
+
const newRule = createShowRule(fieldNameMap.get(element.fieldName) ?? element.fieldName, element.value);
|
|
959
1342
|
const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
|
|
960
|
-
const childElements = irElementsToUiSchema(element.elements, combinedRule);
|
|
1343
|
+
const childElements = irElementsToUiSchema(element.elements, fieldNameMap, combinedRule);
|
|
961
1344
|
result.push(...childElements);
|
|
962
1345
|
break;
|
|
963
1346
|
}
|
|
@@ -971,16 +1354,42 @@ function irElementsToUiSchema(elements, parentRule) {
|
|
|
971
1354
|
return result;
|
|
972
1355
|
}
|
|
973
1356
|
function generateUiSchemaFromIR(ir) {
|
|
1357
|
+
assertNoSerializedNameCollisions(ir);
|
|
1358
|
+
const fieldNameMap = collectFieldNameMap(ir.elements);
|
|
974
1359
|
const result = {
|
|
975
1360
|
type: "VerticalLayout",
|
|
976
|
-
elements: irElementsToUiSchema(ir.elements)
|
|
1361
|
+
elements: irElementsToUiSchema(ir.elements, fieldNameMap)
|
|
977
1362
|
};
|
|
978
1363
|
return parseOrThrow(uiSchema, result, "UI Schema");
|
|
979
1364
|
}
|
|
1365
|
+
function collectFieldNameMap(elements) {
|
|
1366
|
+
const map = /* @__PURE__ */ new Map();
|
|
1367
|
+
for (const element of elements) {
|
|
1368
|
+
switch (element.kind) {
|
|
1369
|
+
case "field":
|
|
1370
|
+
map.set(element.name, getSerializedName(element.name, element.metadata));
|
|
1371
|
+
break;
|
|
1372
|
+
case "group":
|
|
1373
|
+
case "conditional":
|
|
1374
|
+
for (const [key, value] of collectFieldNameMap(element.elements)) {
|
|
1375
|
+
map.set(key, value);
|
|
1376
|
+
}
|
|
1377
|
+
break;
|
|
1378
|
+
default: {
|
|
1379
|
+
const _exhaustive = element;
|
|
1380
|
+
void _exhaustive;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
return map;
|
|
1385
|
+
}
|
|
980
1386
|
|
|
981
1387
|
// src/ui-schema/generator.ts
|
|
982
|
-
function generateUiSchema(form) {
|
|
983
|
-
const ir = canonicalizeChainDSL(
|
|
1388
|
+
function generateUiSchema(form, options) {
|
|
1389
|
+
const ir = canonicalizeChainDSL(
|
|
1390
|
+
form,
|
|
1391
|
+
options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
|
|
1392
|
+
);
|
|
984
1393
|
return generateUiSchemaFromIR(ir);
|
|
985
1394
|
}
|
|
986
1395
|
|
|
@@ -1213,7 +1622,7 @@ function validateIR(ir, options) {
|
|
|
1213
1622
|
function buildFormSchemas(form, options) {
|
|
1214
1623
|
return {
|
|
1215
1624
|
jsonSchema: generateJsonSchema(form, options),
|
|
1216
|
-
uiSchema: generateUiSchema(form)
|
|
1625
|
+
uiSchema: generateUiSchema(form, options)
|
|
1217
1626
|
};
|
|
1218
1627
|
}
|
|
1219
1628
|
export {
|