@formspec/build 0.1.0-alpha.2 → 0.1.0-alpha.20

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.
Files changed (177) hide show
  1. package/README.md +120 -0
  2. package/dist/__tests__/alias-chain-propagation.test.d.ts +9 -0
  3. package/dist/__tests__/alias-chain-propagation.test.d.ts.map +1 -0
  4. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts +2 -0
  5. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts.map +1 -0
  6. package/dist/__tests__/class-schema.test.d.ts +2 -0
  7. package/dist/__tests__/class-schema.test.d.ts.map +1 -0
  8. package/dist/__tests__/constraint-validator.test.d.ts +2 -0
  9. package/dist/__tests__/constraint-validator.test.d.ts.map +1 -0
  10. package/dist/__tests__/date-extension.integration.test.d.ts +2 -0
  11. package/dist/__tests__/date-extension.integration.test.d.ts.map +1 -0
  12. package/dist/__tests__/extension-api.test.d.ts +2 -0
  13. package/dist/__tests__/extension-api.test.d.ts.map +1 -0
  14. package/dist/__tests__/extension-runtime.integration.test.d.ts +2 -0
  15. package/dist/__tests__/extension-runtime.integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/fixtures/alias-chains.d.ts +37 -0
  17. package/dist/__tests__/fixtures/alias-chains.d.ts.map +1 -0
  18. package/dist/__tests__/fixtures/class-schema-regressions.d.ts +87 -0
  19. package/dist/__tests__/fixtures/class-schema-regressions.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/edge-cases.d.ts +132 -0
  21. package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -0
  22. package/dist/__tests__/fixtures/example-a-builtins.d.ts +30 -0
  23. package/dist/__tests__/fixtures/example-a-builtins.d.ts.map +1 -0
  24. package/dist/__tests__/fixtures/example-date-extension.d.ts +12 -0
  25. package/dist/__tests__/fixtures/example-date-extension.d.ts.map +1 -0
  26. package/dist/__tests__/fixtures/example-interface-types.d.ts +102 -0
  27. package/dist/__tests__/fixtures/example-interface-types.d.ts.map +1 -0
  28. package/dist/__tests__/fixtures/example-numeric-extension.d.ts +20 -0
  29. package/dist/__tests__/fixtures/example-numeric-extension.d.ts.map +1 -0
  30. package/dist/__tests__/fixtures/extension-forms.d.ts +7 -0
  31. package/dist/__tests__/fixtures/extension-forms.d.ts.map +1 -0
  32. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts +31 -0
  33. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts.map +1 -0
  34. package/dist/__tests__/fixtures/named-primitive-aliases.d.ts +15 -0
  35. package/dist/__tests__/fixtures/named-primitive-aliases.d.ts.map +1 -0
  36. package/dist/__tests__/fixtures/nested-array-path-constraints.d.ts +14 -0
  37. package/dist/__tests__/fixtures/nested-array-path-constraints.d.ts.map +1 -0
  38. package/dist/__tests__/fixtures/sample-forms.d.ts +65 -0
  39. package/dist/__tests__/fixtures/sample-forms.d.ts.map +1 -0
  40. package/dist/__tests__/generate-schemas.test.d.ts +2 -0
  41. package/dist/__tests__/generate-schemas.test.d.ts.map +1 -0
  42. package/dist/__tests__/guards.test.d.ts +2 -0
  43. package/dist/__tests__/guards.test.d.ts.map +1 -0
  44. package/dist/__tests__/ir-analyzer.test.d.ts +11 -0
  45. package/dist/__tests__/ir-analyzer.test.d.ts.map +1 -0
  46. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts +12 -0
  47. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts.map +1 -0
  48. package/dist/__tests__/ir-json-schema-generator.test.d.ts +11 -0
  49. package/dist/__tests__/ir-json-schema-generator.test.d.ts.map +1 -0
  50. package/dist/__tests__/ir-ui-schema-generator.test.d.ts +2 -0
  51. package/dist/__tests__/ir-ui-schema-generator.test.d.ts.map +1 -0
  52. package/dist/__tests__/mixed-authoring.test.d.ts +2 -0
  53. package/dist/__tests__/mixed-authoring.test.d.ts.map +1 -0
  54. package/dist/__tests__/numeric-extension.integration.test.d.ts +2 -0
  55. package/dist/__tests__/numeric-extension.integration.test.d.ts.map +1 -0
  56. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts +9 -0
  57. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts.map +1 -0
  58. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts +9 -0
  59. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts.map +1 -0
  60. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts +19 -0
  61. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts.map +1 -0
  62. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts +19 -0
  63. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts.map +1 -0
  64. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts +6 -0
  65. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts.map +1 -0
  66. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts +17 -0
  67. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts.map +1 -0
  68. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts +13 -0
  69. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts.map +1 -0
  70. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts +9 -0
  71. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts.map +1 -0
  72. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts +28 -0
  73. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts.map +1 -0
  74. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts +9 -0
  75. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts.map +1 -0
  76. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts +6 -0
  77. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts.map +1 -0
  78. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts +19 -0
  79. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts.map +1 -0
  80. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts +12 -0
  81. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts.map +1 -0
  82. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts +9 -0
  83. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts.map +1 -0
  84. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts +19 -0
  85. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts.map +1 -0
  86. package/dist/__tests__/parity/parity.test.d.ts +18 -0
  87. package/dist/__tests__/parity/parity.test.d.ts.map +1 -0
  88. package/dist/__tests__/parity/utils.d.ts +151 -0
  89. package/dist/__tests__/parity/utils.d.ts.map +1 -0
  90. package/dist/__tests__/path-target-parser.test.d.ts +9 -0
  91. package/dist/__tests__/path-target-parser.test.d.ts.map +1 -0
  92. package/dist/analyzer/class-analyzer.d.ts +100 -0
  93. package/dist/analyzer/class-analyzer.d.ts.map +1 -0
  94. package/dist/analyzer/jsdoc-constraints.d.ts +53 -0
  95. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -0
  96. package/dist/analyzer/program.d.ts +68 -0
  97. package/dist/analyzer/program.d.ts.map +1 -0
  98. package/dist/analyzer/tsdoc-parser.d.ts +122 -0
  99. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -0
  100. package/dist/browser.cjs +1291 -0
  101. package/dist/browser.cjs.map +1 -0
  102. package/dist/browser.d.ts +73 -0
  103. package/dist/browser.d.ts.map +1 -0
  104. package/dist/browser.js +1242 -0
  105. package/dist/browser.js.map +1 -0
  106. package/dist/build.d.ts +996 -0
  107. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts +18 -0
  108. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -0
  109. package/dist/canonicalize/index.d.ts +8 -0
  110. package/dist/canonicalize/index.d.ts.map +1 -0
  111. package/dist/canonicalize/tsdoc-canonicalizer.d.ts +34 -0
  112. package/dist/canonicalize/tsdoc-canonicalizer.d.ts.map +1 -0
  113. package/dist/cli.cjs +3862 -0
  114. package/dist/cli.cjs.map +1 -0
  115. package/dist/cli.js +3826 -103
  116. package/dist/cli.js.map +1 -1
  117. package/dist/extensions/index.d.ts +8 -0
  118. package/dist/extensions/index.d.ts.map +1 -0
  119. package/dist/extensions/registry.d.ts +79 -0
  120. package/dist/extensions/registry.d.ts.map +1 -0
  121. package/dist/generators/class-schema.d.ts +99 -0
  122. package/dist/generators/class-schema.d.ts.map +1 -0
  123. package/dist/generators/method-schema.d.ts +65 -0
  124. package/dist/generators/method-schema.d.ts.map +1 -0
  125. package/dist/generators/mixed-authoring.d.ts +45 -0
  126. package/dist/generators/mixed-authoring.d.ts.map +1 -0
  127. package/dist/index.cjs +3627 -0
  128. package/dist/index.cjs.map +1 -0
  129. package/dist/index.d.ts +33 -8
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +3587 -106
  132. package/dist/index.js.map +1 -1
  133. package/dist/internals.cjs +3371 -0
  134. package/dist/internals.cjs.map +1 -0
  135. package/dist/internals.d.ts +30 -0
  136. package/dist/internals.d.ts.map +1 -0
  137. package/dist/internals.js +3345 -0
  138. package/dist/internals.js.map +1 -0
  139. package/dist/json-schema/generator.d.ts +16 -5
  140. package/dist/json-schema/generator.d.ts.map +1 -1
  141. package/dist/json-schema/ir-generator.d.ts +108 -0
  142. package/dist/json-schema/ir-generator.d.ts.map +1 -0
  143. package/dist/json-schema/schema.d.ts +16 -0
  144. package/dist/json-schema/schema.d.ts.map +1 -0
  145. package/dist/json-schema/types.d.ts +29 -2
  146. package/dist/json-schema/types.d.ts.map +1 -1
  147. package/dist/ui-schema/generator.d.ts +5 -0
  148. package/dist/ui-schema/generator.d.ts.map +1 -1
  149. package/dist/ui-schema/ir-generator.d.ts +53 -0
  150. package/dist/ui-schema/ir-generator.d.ts.map +1 -0
  151. package/dist/ui-schema/schema.d.ts +357 -0
  152. package/dist/ui-schema/schema.d.ts.map +1 -0
  153. package/dist/ui-schema/types.d.ts +8 -73
  154. package/dist/ui-schema/types.d.ts.map +1 -1
  155. package/dist/validate/constraint-validator.d.ts +23 -0
  156. package/dist/validate/constraint-validator.d.ts.map +1 -0
  157. package/dist/validate/index.d.ts +9 -0
  158. package/dist/validate/index.d.ts.map +1 -0
  159. package/package.json +27 -7
  160. package/dist/__tests__/cli.test.js +0 -178
  161. package/dist/__tests__/cli.test.js.map +0 -1
  162. package/dist/__tests__/edge-cases.test.js +0 -217
  163. package/dist/__tests__/edge-cases.test.js.map +0 -1
  164. package/dist/__tests__/generator.test.js +0 -225
  165. package/dist/__tests__/generator.test.js.map +0 -1
  166. package/dist/__tests__/integration.test.js +0 -163
  167. package/dist/__tests__/integration.test.js.map +0 -1
  168. package/dist/__tests__/write-schemas.test.js +0 -196
  169. package/dist/__tests__/write-schemas.test.js.map +0 -1
  170. package/dist/json-schema/generator.js +0 -161
  171. package/dist/json-schema/generator.js.map +0 -1
  172. package/dist/json-schema/types.js +0 -7
  173. package/dist/json-schema/types.js.map +0 -1
  174. package/dist/ui-schema/generator.js +0 -150
  175. package/dist/ui-schema/generator.js.map +0 -1
  176. package/dist/ui-schema/types.js +0 -8
  177. package/dist/ui-schema/types.js.map +0 -1
@@ -0,0 +1,1291 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/browser.ts
21
+ var browser_exports = {};
22
+ __export(browser_exports, {
23
+ buildFormSchemas: () => buildFormSchemas,
24
+ canonicalizeChainDSL: () => canonicalizeChainDSL,
25
+ categorizationSchema: () => categorizationSchema,
26
+ categorySchema: () => categorySchema,
27
+ controlSchema: () => controlSchema,
28
+ createExtensionRegistry: () => createExtensionRegistry,
29
+ generateJsonSchema: () => generateJsonSchema,
30
+ generateJsonSchemaFromIR: () => generateJsonSchemaFromIR,
31
+ generateUiSchema: () => generateUiSchema,
32
+ getSchemaExtension: () => getSchemaExtension,
33
+ groupLayoutSchema: () => groupLayoutSchema,
34
+ horizontalLayoutSchema: () => horizontalLayoutSchema,
35
+ jsonSchema7Schema: () => jsonSchema7Schema,
36
+ jsonSchemaTypeSchema: () => jsonSchemaTypeSchema,
37
+ labelElementSchema: () => labelElementSchema,
38
+ ruleConditionSchema: () => ruleConditionSchema,
39
+ ruleEffectSchema: () => ruleEffectSchema,
40
+ ruleSchema: () => ruleSchema,
41
+ schemaBasedConditionSchema: () => schemaBasedConditionSchema,
42
+ setSchemaExtension: () => setSchemaExtension,
43
+ uiSchemaElementSchema: () => uiSchemaElementSchema,
44
+ uiSchemaElementTypeSchema: () => uiSchemaElementTypeSchema,
45
+ uiSchemaSchema: () => uiSchema,
46
+ validateIR: () => validateIR,
47
+ verticalLayoutSchema: () => verticalLayoutSchema
48
+ });
49
+ module.exports = __toCommonJS(browser_exports);
50
+
51
+ // src/canonicalize/chain-dsl-canonicalizer.ts
52
+ var import_core = require("@formspec/core");
53
+ var CHAIN_DSL_PROVENANCE = {
54
+ surface: "chain-dsl",
55
+ file: "",
56
+ line: 0,
57
+ column: 0
58
+ };
59
+ function isGroup(el) {
60
+ return el._type === "group";
61
+ }
62
+ function isConditional(el) {
63
+ return el._type === "conditional";
64
+ }
65
+ function isField(el) {
66
+ return el._type === "field";
67
+ }
68
+ function canonicalizeChainDSL(form) {
69
+ return {
70
+ kind: "form-ir",
71
+ irVersion: import_core.IR_VERSION,
72
+ elements: canonicalizeElements(form.elements),
73
+ rootAnnotations: [],
74
+ typeRegistry: {},
75
+ provenance: CHAIN_DSL_PROVENANCE
76
+ };
77
+ }
78
+ function canonicalizeElements(elements) {
79
+ return elements.map(canonicalizeElement);
80
+ }
81
+ function canonicalizeElement(element) {
82
+ if (isField(element)) {
83
+ return canonicalizeField(element);
84
+ }
85
+ if (isGroup(element)) {
86
+ return canonicalizeGroup(element);
87
+ }
88
+ if (isConditional(element)) {
89
+ return canonicalizeConditional(element);
90
+ }
91
+ const _exhaustive = element;
92
+ throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);
93
+ }
94
+ function canonicalizeField(field) {
95
+ switch (field._field) {
96
+ case "text":
97
+ return canonicalizeTextField(field);
98
+ case "number":
99
+ return canonicalizeNumberField(field);
100
+ case "boolean":
101
+ return canonicalizeBooleanField(field);
102
+ case "enum":
103
+ return canonicalizeStaticEnumField(field);
104
+ case "dynamic_enum":
105
+ return canonicalizeDynamicEnumField(field);
106
+ case "dynamic_schema":
107
+ return canonicalizeDynamicSchemaField(field);
108
+ case "array":
109
+ return canonicalizeArrayField(field);
110
+ case "object":
111
+ return canonicalizeObjectField(field);
112
+ default: {
113
+ const _exhaustive = field;
114
+ throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);
115
+ }
116
+ }
117
+ }
118
+ function canonicalizeTextField(field) {
119
+ const type = { kind: "primitive", primitiveKind: "string" };
120
+ const constraints = [];
121
+ if (field.minLength !== void 0) {
122
+ const c = {
123
+ kind: "constraint",
124
+ constraintKind: "minLength",
125
+ value: field.minLength,
126
+ provenance: CHAIN_DSL_PROVENANCE
127
+ };
128
+ constraints.push(c);
129
+ }
130
+ if (field.maxLength !== void 0) {
131
+ const c = {
132
+ kind: "constraint",
133
+ constraintKind: "maxLength",
134
+ value: field.maxLength,
135
+ provenance: CHAIN_DSL_PROVENANCE
136
+ };
137
+ constraints.push(c);
138
+ }
139
+ if (field.pattern !== void 0) {
140
+ const c = {
141
+ kind: "constraint",
142
+ constraintKind: "pattern",
143
+ pattern: field.pattern,
144
+ provenance: CHAIN_DSL_PROVENANCE
145
+ };
146
+ constraints.push(c);
147
+ }
148
+ return buildFieldNode(
149
+ field.name,
150
+ type,
151
+ field.required,
152
+ buildAnnotations(field.label, field.placeholder),
153
+ constraints
154
+ );
155
+ }
156
+ function canonicalizeNumberField(field) {
157
+ const type = { kind: "primitive", primitiveKind: "number" };
158
+ const constraints = [];
159
+ if (field.min !== void 0) {
160
+ const c = {
161
+ kind: "constraint",
162
+ constraintKind: "minimum",
163
+ value: field.min,
164
+ provenance: CHAIN_DSL_PROVENANCE
165
+ };
166
+ constraints.push(c);
167
+ }
168
+ if (field.max !== void 0) {
169
+ const c = {
170
+ kind: "constraint",
171
+ constraintKind: "maximum",
172
+ value: field.max,
173
+ provenance: CHAIN_DSL_PROVENANCE
174
+ };
175
+ constraints.push(c);
176
+ }
177
+ if (field.multipleOf !== void 0) {
178
+ const c = {
179
+ kind: "constraint",
180
+ constraintKind: "multipleOf",
181
+ value: field.multipleOf,
182
+ provenance: CHAIN_DSL_PROVENANCE
183
+ };
184
+ constraints.push(c);
185
+ }
186
+ return buildFieldNode(
187
+ field.name,
188
+ type,
189
+ field.required,
190
+ buildAnnotations(field.label),
191
+ constraints
192
+ );
193
+ }
194
+ function canonicalizeBooleanField(field) {
195
+ const type = { kind: "primitive", primitiveKind: "boolean" };
196
+ return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));
197
+ }
198
+ function canonicalizeStaticEnumField(field) {
199
+ const members = field.options.map((opt) => {
200
+ if (typeof opt === "string") {
201
+ return { value: opt };
202
+ }
203
+ return { value: opt.id, displayName: opt.label };
204
+ });
205
+ const type = { kind: "enum", members };
206
+ return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));
207
+ }
208
+ function canonicalizeDynamicEnumField(field) {
209
+ const type = {
210
+ kind: "dynamic",
211
+ dynamicKind: "enum",
212
+ sourceKey: field.source,
213
+ parameterFields: field.params ? [...field.params] : []
214
+ };
215
+ return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));
216
+ }
217
+ function canonicalizeDynamicSchemaField(field) {
218
+ const type = {
219
+ kind: "dynamic",
220
+ dynamicKind: "schema",
221
+ sourceKey: field.schemaSource,
222
+ parameterFields: []
223
+ };
224
+ return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));
225
+ }
226
+ function canonicalizeArrayField(field) {
227
+ const itemProperties = buildObjectProperties(field.items);
228
+ const itemsType = {
229
+ kind: "object",
230
+ properties: itemProperties,
231
+ additionalProperties: true
232
+ };
233
+ const type = { kind: "array", items: itemsType };
234
+ const constraints = [];
235
+ if (field.minItems !== void 0) {
236
+ const c = {
237
+ kind: "constraint",
238
+ constraintKind: "minItems",
239
+ value: field.minItems,
240
+ provenance: CHAIN_DSL_PROVENANCE
241
+ };
242
+ constraints.push(c);
243
+ }
244
+ if (field.maxItems !== void 0) {
245
+ const c = {
246
+ kind: "constraint",
247
+ constraintKind: "maxItems",
248
+ value: field.maxItems,
249
+ provenance: CHAIN_DSL_PROVENANCE
250
+ };
251
+ constraints.push(c);
252
+ }
253
+ return buildFieldNode(
254
+ field.name,
255
+ type,
256
+ field.required,
257
+ buildAnnotations(field.label),
258
+ constraints
259
+ );
260
+ }
261
+ function canonicalizeObjectField(field) {
262
+ const properties = buildObjectProperties(field.properties);
263
+ const type = {
264
+ kind: "object",
265
+ properties,
266
+ additionalProperties: true
267
+ };
268
+ return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));
269
+ }
270
+ function canonicalizeGroup(g) {
271
+ return {
272
+ kind: "group",
273
+ label: g.label,
274
+ elements: canonicalizeElements(g.elements),
275
+ provenance: CHAIN_DSL_PROVENANCE
276
+ };
277
+ }
278
+ function canonicalizeConditional(c) {
279
+ return {
280
+ kind: "conditional",
281
+ fieldName: c.field,
282
+ // Conditional values from the chain DSL are JSON-serializable primitives
283
+ // (strings, numbers, booleans) produced by the `is()` predicate helper.
284
+ value: assertJsonValue(c.value),
285
+ elements: canonicalizeElements(c.elements),
286
+ provenance: CHAIN_DSL_PROVENANCE
287
+ };
288
+ }
289
+ function assertJsonValue(v) {
290
+ if (v === null || typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
291
+ return v;
292
+ }
293
+ if (Array.isArray(v)) {
294
+ return v.map(assertJsonValue);
295
+ }
296
+ if (typeof v === "object") {
297
+ const result = {};
298
+ for (const [key, val] of Object.entries(v)) {
299
+ result[key] = assertJsonValue(val);
300
+ }
301
+ return result;
302
+ }
303
+ throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);
304
+ }
305
+ function buildFieldNode(name, type, required, annotations, constraints = []) {
306
+ return {
307
+ kind: "field",
308
+ name,
309
+ type,
310
+ required: required === true,
311
+ constraints,
312
+ annotations,
313
+ provenance: CHAIN_DSL_PROVENANCE
314
+ };
315
+ }
316
+ function buildAnnotations(label, placeholder) {
317
+ const annotations = [];
318
+ if (label !== void 0) {
319
+ const a = {
320
+ kind: "annotation",
321
+ annotationKind: "displayName",
322
+ value: label,
323
+ provenance: CHAIN_DSL_PROVENANCE
324
+ };
325
+ annotations.push(a);
326
+ }
327
+ if (placeholder !== void 0) {
328
+ const a = {
329
+ kind: "annotation",
330
+ annotationKind: "placeholder",
331
+ value: placeholder,
332
+ provenance: CHAIN_DSL_PROVENANCE
333
+ };
334
+ annotations.push(a);
335
+ }
336
+ return annotations;
337
+ }
338
+ function buildObjectProperties(elements, insideConditional = false) {
339
+ const properties = [];
340
+ for (const el of elements) {
341
+ if (isField(el)) {
342
+ const fieldNode = canonicalizeField(el);
343
+ properties.push({
344
+ name: fieldNode.name,
345
+ type: fieldNode.type,
346
+ // Fields inside a conditional branch are always optional in the
347
+ // data schema, regardless of their `required` flag — the condition
348
+ // may not be met, so the field may be absent.
349
+ optional: insideConditional || !fieldNode.required,
350
+ constraints: fieldNode.constraints,
351
+ annotations: fieldNode.annotations,
352
+ provenance: CHAIN_DSL_PROVENANCE
353
+ });
354
+ } else if (isGroup(el)) {
355
+ properties.push(...buildObjectProperties(el.elements, insideConditional));
356
+ } else if (isConditional(el)) {
357
+ properties.push(...buildObjectProperties(el.elements, true));
358
+ }
359
+ }
360
+ return properties;
361
+ }
362
+
363
+ // src/canonicalize/tsdoc-canonicalizer.ts
364
+ var import_core2 = require("@formspec/core");
365
+
366
+ // src/json-schema/ir-generator.ts
367
+ function makeContext(options) {
368
+ const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
369
+ if (!vendorPrefix.startsWith("x-")) {
370
+ throw new Error(
371
+ `Invalid vendorPrefix "${vendorPrefix}". Extension JSON Schema keywords must start with "x-".`
372
+ );
373
+ }
374
+ return {
375
+ defs: {},
376
+ extensionRegistry: options?.extensionRegistry,
377
+ vendorPrefix
378
+ };
379
+ }
380
+ function generateJsonSchemaFromIR(ir, options) {
381
+ const ctx = makeContext(options);
382
+ for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {
383
+ ctx.defs[name] = generateTypeNode(typeDef.type, ctx);
384
+ if (typeDef.constraints && typeDef.constraints.length > 0) {
385
+ applyConstraints(ctx.defs[name], typeDef.constraints, ctx);
386
+ }
387
+ if (typeDef.annotations && typeDef.annotations.length > 0) {
388
+ applyAnnotations(ctx.defs[name], typeDef.annotations, ctx);
389
+ }
390
+ }
391
+ const properties = {};
392
+ const required = [];
393
+ collectFields(ir.elements, properties, required, ctx);
394
+ const uniqueRequired = [...new Set(required)];
395
+ const result = {
396
+ $schema: "https://json-schema.org/draft/2020-12/schema",
397
+ type: "object",
398
+ properties,
399
+ ...uniqueRequired.length > 0 && { required: uniqueRequired }
400
+ };
401
+ if (ir.annotations && ir.annotations.length > 0) {
402
+ applyAnnotations(result, ir.annotations, ctx);
403
+ }
404
+ if (Object.keys(ctx.defs).length > 0) {
405
+ result.$defs = ctx.defs;
406
+ }
407
+ return result;
408
+ }
409
+ function collectFields(elements, properties, required, ctx) {
410
+ for (const element of elements) {
411
+ switch (element.kind) {
412
+ case "field":
413
+ properties[element.name] = generateFieldSchema(element, ctx);
414
+ if (element.required) {
415
+ required.push(element.name);
416
+ }
417
+ break;
418
+ case "group":
419
+ collectFields(element.elements, properties, required, ctx);
420
+ break;
421
+ case "conditional":
422
+ collectFields(element.elements, properties, required, ctx);
423
+ break;
424
+ default: {
425
+ const _exhaustive = element;
426
+ void _exhaustive;
427
+ }
428
+ }
429
+ }
430
+ }
431
+ function generateFieldSchema(field, ctx) {
432
+ const schema = generateTypeNode(field.type, ctx);
433
+ const itemStringSchema = schema.type === "array" && schema.items?.type === "string" ? schema.items : void 0;
434
+ const directConstraints = [];
435
+ const itemConstraints = [];
436
+ const pathConstraints = [];
437
+ for (const c of field.constraints) {
438
+ if (c.path) {
439
+ pathConstraints.push(c);
440
+ } else if (itemStringSchema !== void 0 && isStringItemConstraint(c)) {
441
+ itemConstraints.push(c);
442
+ } else {
443
+ directConstraints.push(c);
444
+ }
445
+ }
446
+ applyConstraints(schema, directConstraints, ctx);
447
+ if (itemStringSchema !== void 0) {
448
+ applyConstraints(itemStringSchema, itemConstraints, ctx);
449
+ }
450
+ const rootAnnotations = [];
451
+ const itemAnnotations = [];
452
+ for (const annotation of field.annotations) {
453
+ if (itemStringSchema !== void 0 && annotation.annotationKind === "format") {
454
+ itemAnnotations.push(annotation);
455
+ } else {
456
+ rootAnnotations.push(annotation);
457
+ }
458
+ }
459
+ applyAnnotations(schema, rootAnnotations, ctx);
460
+ if (itemStringSchema !== void 0) {
461
+ applyAnnotations(itemStringSchema, itemAnnotations, ctx);
462
+ }
463
+ if (pathConstraints.length === 0) {
464
+ return schema;
465
+ }
466
+ return applyPathTargetedConstraints(schema, pathConstraints, ctx);
467
+ }
468
+ function isStringItemConstraint(constraint) {
469
+ switch (constraint.constraintKind) {
470
+ case "minLength":
471
+ case "maxLength":
472
+ case "pattern":
473
+ return true;
474
+ default:
475
+ return false;
476
+ }
477
+ }
478
+ function applyPathTargetedConstraints(schema, pathConstraints, ctx) {
479
+ if (schema.type === "array" && schema.items) {
480
+ schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx);
481
+ return schema;
482
+ }
483
+ const byTarget = /* @__PURE__ */ new Map();
484
+ for (const c of pathConstraints) {
485
+ const target = c.path?.segments[0];
486
+ if (!target) continue;
487
+ const group = byTarget.get(target) ?? [];
488
+ group.push(c);
489
+ byTarget.set(target, group);
490
+ }
491
+ const propertyOverrides = {};
492
+ for (const [target, constraints] of byTarget) {
493
+ const subSchema = {};
494
+ applyConstraints(subSchema, constraints, ctx);
495
+ propertyOverrides[target] = subSchema;
496
+ }
497
+ if (schema.$ref) {
498
+ const { $ref, ...rest } = schema;
499
+ const refPart = { $ref };
500
+ const overridePart = {
501
+ properties: propertyOverrides,
502
+ ...rest
503
+ };
504
+ return { allOf: [refPart, overridePart] };
505
+ }
506
+ if (schema.type === "object" && schema.properties) {
507
+ const missingOverrides = {};
508
+ for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
509
+ if (schema.properties[target]) {
510
+ Object.assign(schema.properties[target], overrideSchema);
511
+ } else {
512
+ missingOverrides[target] = overrideSchema;
513
+ }
514
+ }
515
+ if (Object.keys(missingOverrides).length === 0) {
516
+ return schema;
517
+ }
518
+ return {
519
+ allOf: [schema, { properties: missingOverrides }]
520
+ };
521
+ }
522
+ if (schema.allOf) {
523
+ schema.allOf = [...schema.allOf, { properties: propertyOverrides }];
524
+ return schema;
525
+ }
526
+ return schema;
527
+ }
528
+ function generateTypeNode(type, ctx) {
529
+ switch (type.kind) {
530
+ case "primitive":
531
+ return generatePrimitiveType(type);
532
+ case "enum":
533
+ return generateEnumType(type);
534
+ case "array":
535
+ return generateArrayType(type, ctx);
536
+ case "object":
537
+ return generateObjectType(type, ctx);
538
+ case "record":
539
+ return generateRecordType(type, ctx);
540
+ case "union":
541
+ return generateUnionType(type, ctx);
542
+ case "reference":
543
+ return generateReferenceType(type);
544
+ case "dynamic":
545
+ return generateDynamicType(type);
546
+ case "custom":
547
+ return generateCustomType(type, ctx);
548
+ default: {
549
+ const _exhaustive = type;
550
+ return _exhaustive;
551
+ }
552
+ }
553
+ }
554
+ function generatePrimitiveType(type) {
555
+ return {
556
+ type: type.primitiveKind === "integer" || type.primitiveKind === "bigint" ? "integer" : type.primitiveKind
557
+ };
558
+ }
559
+ function generateEnumType(type) {
560
+ const hasDisplayNames = type.members.some((m) => m.displayName !== void 0);
561
+ if (hasDisplayNames) {
562
+ return {
563
+ oneOf: type.members.map((m) => {
564
+ const entry = { const: m.value };
565
+ if (m.displayName !== void 0) {
566
+ entry.title = m.displayName;
567
+ }
568
+ return entry;
569
+ })
570
+ };
571
+ }
572
+ return { enum: type.members.map((m) => m.value) };
573
+ }
574
+ function generateArrayType(type, ctx) {
575
+ return {
576
+ type: "array",
577
+ items: generateTypeNode(type.items, ctx)
578
+ };
579
+ }
580
+ function generateObjectType(type, ctx) {
581
+ const properties = {};
582
+ const required = [];
583
+ for (const prop of type.properties) {
584
+ properties[prop.name] = generatePropertySchema(prop, ctx);
585
+ if (!prop.optional) {
586
+ required.push(prop.name);
587
+ }
588
+ }
589
+ const schema = { type: "object", properties };
590
+ if (required.length > 0) {
591
+ schema.required = required;
592
+ }
593
+ if (!type.additionalProperties) {
594
+ schema.additionalProperties = false;
595
+ }
596
+ return schema;
597
+ }
598
+ function generateRecordType(type, ctx) {
599
+ return {
600
+ type: "object",
601
+ additionalProperties: generateTypeNode(type.valueType, ctx)
602
+ };
603
+ }
604
+ function generatePropertySchema(prop, ctx) {
605
+ const schema = generateTypeNode(prop.type, ctx);
606
+ applyConstraints(schema, prop.constraints, ctx);
607
+ applyAnnotations(schema, prop.annotations, ctx);
608
+ return schema;
609
+ }
610
+ function generateUnionType(type, ctx) {
611
+ if (isBooleanUnion(type)) {
612
+ return { type: "boolean" };
613
+ }
614
+ if (isNullableUnion(type)) {
615
+ return {
616
+ oneOf: type.members.map((m) => generateTypeNode(m, ctx))
617
+ };
618
+ }
619
+ return {
620
+ anyOf: type.members.map((m) => generateTypeNode(m, ctx))
621
+ };
622
+ }
623
+ function isBooleanUnion(type) {
624
+ if (type.members.length !== 2) return false;
625
+ const kinds = type.members.map((m) => m.kind);
626
+ return kinds.every((k) => k === "primitive") && type.members.every((m) => m.kind === "primitive" && m.primitiveKind === "boolean");
627
+ }
628
+ function isNullableUnion(type) {
629
+ if (type.members.length !== 2) return false;
630
+ const nullCount = type.members.filter(
631
+ (m) => m.kind === "primitive" && m.primitiveKind === "null"
632
+ ).length;
633
+ return nullCount === 1;
634
+ }
635
+ function generateReferenceType(type) {
636
+ return { $ref: `#/$defs/${type.name}` };
637
+ }
638
+ function generateDynamicType(type) {
639
+ if (type.dynamicKind === "enum") {
640
+ const schema = {
641
+ type: "string",
642
+ "x-formspec-source": type.sourceKey
643
+ };
644
+ if (type.parameterFields.length > 0) {
645
+ schema["x-formspec-params"] = [...type.parameterFields];
646
+ }
647
+ return schema;
648
+ }
649
+ return {
650
+ type: "object",
651
+ additionalProperties: true,
652
+ "x-formspec-schemaSource": type.sourceKey
653
+ };
654
+ }
655
+ function applyConstraints(schema, constraints, ctx) {
656
+ for (const constraint of constraints) {
657
+ switch (constraint.constraintKind) {
658
+ case "minimum":
659
+ schema.minimum = constraint.value;
660
+ break;
661
+ case "maximum":
662
+ schema.maximum = constraint.value;
663
+ break;
664
+ case "exclusiveMinimum":
665
+ schema.exclusiveMinimum = constraint.value;
666
+ break;
667
+ case "exclusiveMaximum":
668
+ schema.exclusiveMaximum = constraint.value;
669
+ break;
670
+ case "multipleOf": {
671
+ const { value } = constraint;
672
+ if (value === 1 && schema.type === "number") {
673
+ schema.type = "integer";
674
+ } else {
675
+ schema.multipleOf = value;
676
+ }
677
+ break;
678
+ }
679
+ case "minLength":
680
+ schema.minLength = constraint.value;
681
+ break;
682
+ case "maxLength":
683
+ schema.maxLength = constraint.value;
684
+ break;
685
+ case "minItems":
686
+ schema.minItems = constraint.value;
687
+ break;
688
+ case "maxItems":
689
+ schema.maxItems = constraint.value;
690
+ break;
691
+ case "pattern":
692
+ schema.pattern = constraint.pattern;
693
+ break;
694
+ case "uniqueItems":
695
+ schema.uniqueItems = constraint.value;
696
+ break;
697
+ case "const":
698
+ schema.const = constraint.value;
699
+ break;
700
+ case "allowedMembers":
701
+ break;
702
+ case "custom":
703
+ applyCustomConstraint(schema, constraint, ctx);
704
+ break;
705
+ default: {
706
+ const _exhaustive = constraint;
707
+ void _exhaustive;
708
+ }
709
+ }
710
+ }
711
+ }
712
+ function applyAnnotations(schema, annotations, ctx) {
713
+ for (const annotation of annotations) {
714
+ switch (annotation.annotationKind) {
715
+ case "displayName":
716
+ schema.title = annotation.value;
717
+ break;
718
+ case "description":
719
+ schema.description = annotation.value;
720
+ break;
721
+ case "defaultValue":
722
+ schema.default = annotation.value;
723
+ break;
724
+ case "format":
725
+ schema.format = annotation.value;
726
+ break;
727
+ case "deprecated":
728
+ schema.deprecated = true;
729
+ if (annotation.message !== void 0 && annotation.message !== "") {
730
+ schema[`${ctx.vendorPrefix}-deprecation-description`] = annotation.message;
731
+ }
732
+ break;
733
+ case "placeholder":
734
+ break;
735
+ case "formatHint":
736
+ break;
737
+ case "custom":
738
+ applyCustomAnnotation(schema, annotation, ctx);
739
+ break;
740
+ default: {
741
+ const _exhaustive = annotation;
742
+ void _exhaustive;
743
+ }
744
+ }
745
+ }
746
+ }
747
+ function generateCustomType(type, ctx) {
748
+ const registration = ctx.extensionRegistry?.findType(type.typeId);
749
+ if (registration === void 0) {
750
+ throw new Error(
751
+ `Cannot generate JSON Schema for custom type "${type.typeId}" without a matching extension registration`
752
+ );
753
+ }
754
+ return registration.toJsonSchema(type.payload, ctx.vendorPrefix);
755
+ }
756
+ function applyCustomConstraint(schema, constraint, ctx) {
757
+ const registration = ctx.extensionRegistry?.findConstraint(constraint.constraintId);
758
+ if (registration === void 0) {
759
+ throw new Error(
760
+ `Cannot generate JSON Schema for custom constraint "${constraint.constraintId}" without a matching extension registration`
761
+ );
762
+ }
763
+ assignVendorPrefixedExtensionKeywords(
764
+ schema,
765
+ registration.toJsonSchema(constraint.payload, ctx.vendorPrefix),
766
+ ctx.vendorPrefix,
767
+ `custom constraint "${constraint.constraintId}"`
768
+ );
769
+ }
770
+ function applyCustomAnnotation(schema, annotation, ctx) {
771
+ const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);
772
+ if (registration === void 0) {
773
+ throw new Error(
774
+ `Cannot generate JSON Schema for custom annotation "${annotation.annotationId}" without a matching extension registration`
775
+ );
776
+ }
777
+ if (registration.toJsonSchema === void 0) {
778
+ return;
779
+ }
780
+ assignVendorPrefixedExtensionKeywords(
781
+ schema,
782
+ registration.toJsonSchema(annotation.value, ctx.vendorPrefix),
783
+ ctx.vendorPrefix,
784
+ `custom annotation "${annotation.annotationId}"`
785
+ );
786
+ }
787
+ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPrefix, source) {
788
+ for (const [key, value] of Object.entries(extensionSchema)) {
789
+ if (!key.startsWith(`${vendorPrefix}-`)) {
790
+ throw new Error(
791
+ `Cannot apply ${source}: extension hooks may only emit "${vendorPrefix}-*" JSON Schema keywords`
792
+ );
793
+ }
794
+ schema[key] = value;
795
+ }
796
+ }
797
+
798
+ // src/json-schema/generator.ts
799
+ function generateJsonSchema(form, options) {
800
+ const ir = canonicalizeChainDSL(form);
801
+ return generateJsonSchemaFromIR(ir, options);
802
+ }
803
+
804
+ // src/ui-schema/schema.ts
805
+ var import_zod = require("zod");
806
+ var jsonPointerSchema = import_zod.z.string();
807
+ var ruleEffectSchema = import_zod.z.enum(["SHOW", "HIDE", "ENABLE", "DISABLE"]);
808
+ var uiSchemaElementTypeSchema = import_zod.z.enum([
809
+ "Control",
810
+ "VerticalLayout",
811
+ "HorizontalLayout",
812
+ "Group",
813
+ "Categorization",
814
+ "Category",
815
+ "Label"
816
+ ]);
817
+ var ruleConditionSchema = import_zod.z.lazy(
818
+ () => import_zod.z.object({
819
+ const: import_zod.z.unknown().optional(),
820
+ enum: import_zod.z.array(import_zod.z.unknown()).readonly().optional(),
821
+ type: import_zod.z.string().optional(),
822
+ not: ruleConditionSchema.optional(),
823
+ minimum: import_zod.z.number().optional(),
824
+ maximum: import_zod.z.number().optional(),
825
+ exclusiveMinimum: import_zod.z.number().optional(),
826
+ exclusiveMaximum: import_zod.z.number().optional(),
827
+ minLength: import_zod.z.number().optional(),
828
+ properties: import_zod.z.record(import_zod.z.string(), ruleConditionSchema).optional(),
829
+ required: import_zod.z.array(import_zod.z.string()).optional(),
830
+ allOf: import_zod.z.array(ruleConditionSchema).optional()
831
+ }).strict()
832
+ );
833
+ var schemaBasedConditionSchema = import_zod.z.object({
834
+ scope: jsonPointerSchema,
835
+ schema: ruleConditionSchema
836
+ }).strict();
837
+ var ruleSchema = import_zod.z.object({
838
+ effect: ruleEffectSchema,
839
+ condition: schemaBasedConditionSchema
840
+ }).strict();
841
+ var uiSchemaElementSchema = import_zod.z.lazy(
842
+ () => import_zod.z.union([
843
+ controlSchema,
844
+ verticalLayoutSchema,
845
+ horizontalLayoutSchema,
846
+ groupLayoutSchema,
847
+ categorizationSchema,
848
+ categorySchema,
849
+ labelElementSchema
850
+ ])
851
+ );
852
+ var controlSchema = import_zod.z.object({
853
+ type: import_zod.z.literal("Control"),
854
+ scope: jsonPointerSchema,
855
+ label: import_zod.z.union([import_zod.z.string(), import_zod.z.literal(false)]).optional(),
856
+ rule: ruleSchema.optional(),
857
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
858
+ }).passthrough();
859
+ var verticalLayoutSchema = import_zod.z.lazy(
860
+ () => import_zod.z.object({
861
+ type: import_zod.z.literal("VerticalLayout"),
862
+ elements: import_zod.z.array(uiSchemaElementSchema),
863
+ rule: ruleSchema.optional(),
864
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
865
+ }).passthrough()
866
+ );
867
+ var horizontalLayoutSchema = import_zod.z.lazy(
868
+ () => import_zod.z.object({
869
+ type: import_zod.z.literal("HorizontalLayout"),
870
+ elements: import_zod.z.array(uiSchemaElementSchema),
871
+ rule: ruleSchema.optional(),
872
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
873
+ }).passthrough()
874
+ );
875
+ var groupLayoutSchema = import_zod.z.lazy(
876
+ () => import_zod.z.object({
877
+ type: import_zod.z.literal("Group"),
878
+ label: import_zod.z.string(),
879
+ elements: import_zod.z.array(uiSchemaElementSchema),
880
+ rule: ruleSchema.optional(),
881
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
882
+ }).passthrough()
883
+ );
884
+ var categorySchema = import_zod.z.lazy(
885
+ () => import_zod.z.object({
886
+ type: import_zod.z.literal("Category"),
887
+ label: import_zod.z.string(),
888
+ elements: import_zod.z.array(uiSchemaElementSchema),
889
+ rule: ruleSchema.optional(),
890
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
891
+ }).passthrough()
892
+ );
893
+ var categorizationSchema = import_zod.z.lazy(
894
+ () => import_zod.z.object({
895
+ type: import_zod.z.literal("Categorization"),
896
+ elements: import_zod.z.array(categorySchema),
897
+ label: import_zod.z.string().optional(),
898
+ rule: ruleSchema.optional(),
899
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
900
+ }).passthrough()
901
+ );
902
+ var labelElementSchema = import_zod.z.object({
903
+ type: import_zod.z.literal("Label"),
904
+ text: import_zod.z.string(),
905
+ rule: ruleSchema.optional(),
906
+ options: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
907
+ }).passthrough();
908
+ var uiSchema = import_zod.z.lazy(
909
+ () => import_zod.z.union([verticalLayoutSchema, horizontalLayoutSchema, groupLayoutSchema, categorizationSchema])
910
+ );
911
+
912
+ // src/ui-schema/ir-generator.ts
913
+ var import_zod2 = require("zod");
914
+ function parseOrThrow(schema, value, label) {
915
+ try {
916
+ return schema.parse(value);
917
+ } catch (error) {
918
+ if (error instanceof import_zod2.z.ZodError) {
919
+ throw new Error(
920
+ `Generated ${label} failed validation:
921
+ ${error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n")}`
922
+ );
923
+ }
924
+ throw error;
925
+ }
926
+ }
927
+ function fieldToScope(fieldName) {
928
+ return `#/properties/${fieldName}`;
929
+ }
930
+ function createShowRule(fieldName, value) {
931
+ return {
932
+ effect: "SHOW",
933
+ condition: {
934
+ scope: fieldToScope(fieldName),
935
+ schema: { const: value }
936
+ }
937
+ };
938
+ }
939
+ function flattenConditionSchema(scope, schema) {
940
+ if (schema.allOf === void 0) {
941
+ if (scope === "#") {
942
+ return [schema];
943
+ }
944
+ const fieldName = scope.replace("#/properties/", "");
945
+ return [
946
+ {
947
+ properties: {
948
+ [fieldName]: schema
949
+ }
950
+ }
951
+ ];
952
+ }
953
+ return schema.allOf.flatMap((member) => flattenConditionSchema(scope, member));
954
+ }
955
+ function combineRules(parentRule, childRule) {
956
+ return {
957
+ effect: "SHOW",
958
+ condition: {
959
+ scope: "#",
960
+ schema: {
961
+ allOf: [
962
+ ...flattenConditionSchema(parentRule.condition.scope, parentRule.condition.schema),
963
+ ...flattenConditionSchema(childRule.condition.scope, childRule.condition.schema)
964
+ ]
965
+ }
966
+ }
967
+ };
968
+ }
969
+ function fieldNodeToControl(field, parentRule) {
970
+ const displayNameAnnotation = field.annotations.find((a) => a.annotationKind === "displayName");
971
+ const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === "placeholder");
972
+ const control = {
973
+ type: "Control",
974
+ scope: fieldToScope(field.name),
975
+ ...displayNameAnnotation !== void 0 && { label: displayNameAnnotation.value },
976
+ ...placeholderAnnotation !== void 0 && {
977
+ options: { placeholder: placeholderAnnotation.value }
978
+ },
979
+ ...parentRule !== void 0 && { rule: parentRule }
980
+ };
981
+ return control;
982
+ }
983
+ function groupNodeToLayout(group, parentRule) {
984
+ return {
985
+ type: "Group",
986
+ label: group.label,
987
+ elements: irElementsToUiSchema(group.elements, parentRule),
988
+ ...parentRule !== void 0 && { rule: parentRule }
989
+ };
990
+ }
991
+ function irElementsToUiSchema(elements, parentRule) {
992
+ const result = [];
993
+ for (const element of elements) {
994
+ switch (element.kind) {
995
+ case "field": {
996
+ result.push(fieldNodeToControl(element, parentRule));
997
+ break;
998
+ }
999
+ case "group": {
1000
+ result.push(groupNodeToLayout(element, parentRule));
1001
+ break;
1002
+ }
1003
+ case "conditional": {
1004
+ const newRule = createShowRule(element.fieldName, element.value);
1005
+ const combinedRule = parentRule !== void 0 ? combineRules(parentRule, newRule) : newRule;
1006
+ const childElements = irElementsToUiSchema(element.elements, combinedRule);
1007
+ result.push(...childElements);
1008
+ break;
1009
+ }
1010
+ default: {
1011
+ const _exhaustive = element;
1012
+ void _exhaustive;
1013
+ throw new Error("Unhandled IR element kind");
1014
+ }
1015
+ }
1016
+ }
1017
+ return result;
1018
+ }
1019
+ function generateUiSchemaFromIR(ir) {
1020
+ const result = {
1021
+ type: "VerticalLayout",
1022
+ elements: irElementsToUiSchema(ir.elements)
1023
+ };
1024
+ return parseOrThrow(uiSchema, result, "UI Schema");
1025
+ }
1026
+
1027
+ // src/ui-schema/generator.ts
1028
+ function generateUiSchema(form) {
1029
+ const ir = canonicalizeChainDSL(form);
1030
+ return generateUiSchemaFromIR(ir);
1031
+ }
1032
+
1033
+ // src/json-schema/types.ts
1034
+ function setSchemaExtension(schema, key, value) {
1035
+ schema[key] = value;
1036
+ }
1037
+ function getSchemaExtension(schema, key) {
1038
+ return schema[key];
1039
+ }
1040
+
1041
+ // src/extensions/registry.ts
1042
+ function createExtensionRegistry(extensions) {
1043
+ const typeMap = /* @__PURE__ */ new Map();
1044
+ const typeNameMap = /* @__PURE__ */ new Map();
1045
+ const constraintMap = /* @__PURE__ */ new Map();
1046
+ const constraintTagMap = /* @__PURE__ */ new Map();
1047
+ const builtinBroadeningMap = /* @__PURE__ */ new Map();
1048
+ const annotationMap = /* @__PURE__ */ new Map();
1049
+ for (const ext of extensions) {
1050
+ if (ext.types !== void 0) {
1051
+ for (const type of ext.types) {
1052
+ const qualifiedId = `${ext.extensionId}/${type.typeName}`;
1053
+ if (typeMap.has(qualifiedId)) {
1054
+ throw new Error(`Duplicate custom type ID: "${qualifiedId}"`);
1055
+ }
1056
+ typeMap.set(qualifiedId, type);
1057
+ for (const sourceTypeName of type.tsTypeNames ?? [type.typeName]) {
1058
+ if (typeNameMap.has(sourceTypeName)) {
1059
+ throw new Error(`Duplicate custom type source name: "${sourceTypeName}"`);
1060
+ }
1061
+ typeNameMap.set(sourceTypeName, {
1062
+ extensionId: ext.extensionId,
1063
+ registration: type
1064
+ });
1065
+ }
1066
+ if (type.builtinConstraintBroadenings !== void 0) {
1067
+ for (const broadening of type.builtinConstraintBroadenings) {
1068
+ const key = `${qualifiedId}:${broadening.tagName}`;
1069
+ if (builtinBroadeningMap.has(key)) {
1070
+ throw new Error(`Duplicate built-in constraint broadening: "${key}"`);
1071
+ }
1072
+ builtinBroadeningMap.set(key, {
1073
+ extensionId: ext.extensionId,
1074
+ registration: broadening
1075
+ });
1076
+ }
1077
+ }
1078
+ }
1079
+ }
1080
+ if (ext.constraints !== void 0) {
1081
+ for (const constraint of ext.constraints) {
1082
+ const qualifiedId = `${ext.extensionId}/${constraint.constraintName}`;
1083
+ if (constraintMap.has(qualifiedId)) {
1084
+ throw new Error(`Duplicate custom constraint ID: "${qualifiedId}"`);
1085
+ }
1086
+ constraintMap.set(qualifiedId, constraint);
1087
+ }
1088
+ }
1089
+ if (ext.constraintTags !== void 0) {
1090
+ for (const tag of ext.constraintTags) {
1091
+ if (constraintTagMap.has(tag.tagName)) {
1092
+ throw new Error(`Duplicate custom constraint tag: "@${tag.tagName}"`);
1093
+ }
1094
+ constraintTagMap.set(tag.tagName, {
1095
+ extensionId: ext.extensionId,
1096
+ registration: tag
1097
+ });
1098
+ }
1099
+ }
1100
+ if (ext.annotations !== void 0) {
1101
+ for (const annotation of ext.annotations) {
1102
+ const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;
1103
+ if (annotationMap.has(qualifiedId)) {
1104
+ throw new Error(`Duplicate custom annotation ID: "${qualifiedId}"`);
1105
+ }
1106
+ annotationMap.set(qualifiedId, annotation);
1107
+ }
1108
+ }
1109
+ }
1110
+ return {
1111
+ extensions,
1112
+ findType: (typeId) => typeMap.get(typeId),
1113
+ findTypeByName: (typeName) => typeNameMap.get(typeName),
1114
+ findConstraint: (constraintId) => constraintMap.get(constraintId),
1115
+ findConstraintTag: (tagName) => constraintTagMap.get(tagName),
1116
+ findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
1117
+ findAnnotation: (annotationId) => annotationMap.get(annotationId)
1118
+ };
1119
+ }
1120
+
1121
+ // src/json-schema/schema.ts
1122
+ var import_zod3 = require("zod");
1123
+ var jsonSchemaTypeSchema = import_zod3.z.enum([
1124
+ "string",
1125
+ "number",
1126
+ "integer",
1127
+ "boolean",
1128
+ "object",
1129
+ "array",
1130
+ "null"
1131
+ ]);
1132
+ var jsonSchema7Schema = import_zod3.z.lazy(
1133
+ () => import_zod3.z.object({
1134
+ $schema: import_zod3.z.string().optional(),
1135
+ $id: import_zod3.z.string().optional(),
1136
+ $ref: import_zod3.z.string().optional(),
1137
+ // Metadata
1138
+ title: import_zod3.z.string().optional(),
1139
+ description: import_zod3.z.string().optional(),
1140
+ deprecated: import_zod3.z.boolean().optional(),
1141
+ // Type
1142
+ type: import_zod3.z.union([jsonSchemaTypeSchema, import_zod3.z.array(jsonSchemaTypeSchema)]).optional(),
1143
+ // String validation
1144
+ minLength: import_zod3.z.number().optional(),
1145
+ maxLength: import_zod3.z.number().optional(),
1146
+ pattern: import_zod3.z.string().optional(),
1147
+ // Number validation
1148
+ minimum: import_zod3.z.number().optional(),
1149
+ maximum: import_zod3.z.number().optional(),
1150
+ exclusiveMinimum: import_zod3.z.number().optional(),
1151
+ exclusiveMaximum: import_zod3.z.number().optional(),
1152
+ // Enum
1153
+ enum: import_zod3.z.array(import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean(), import_zod3.z.null()])).readonly().optional(),
1154
+ const: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean(), import_zod3.z.null()]).optional(),
1155
+ // Object
1156
+ properties: import_zod3.z.record(import_zod3.z.string(), jsonSchema7Schema).optional(),
1157
+ required: import_zod3.z.array(import_zod3.z.string()).optional(),
1158
+ additionalProperties: import_zod3.z.union([import_zod3.z.boolean(), jsonSchema7Schema]).optional(),
1159
+ // Array
1160
+ items: import_zod3.z.union([jsonSchema7Schema, import_zod3.z.array(jsonSchema7Schema)]).optional(),
1161
+ minItems: import_zod3.z.number().optional(),
1162
+ maxItems: import_zod3.z.number().optional(),
1163
+ // Composition
1164
+ allOf: import_zod3.z.array(jsonSchema7Schema).optional(),
1165
+ anyOf: import_zod3.z.array(jsonSchema7Schema).optional(),
1166
+ oneOf: import_zod3.z.array(jsonSchema7Schema).optional(),
1167
+ not: jsonSchema7Schema.optional(),
1168
+ // Conditional
1169
+ if: jsonSchema7Schema.optional(),
1170
+ then: jsonSchema7Schema.optional(),
1171
+ else: jsonSchema7Schema.optional(),
1172
+ // Format
1173
+ format: import_zod3.z.string().optional(),
1174
+ // Default
1175
+ default: import_zod3.z.unknown().optional(),
1176
+ // FormSpec extensions
1177
+ "x-formspec-source": import_zod3.z.string().optional(),
1178
+ "x-formspec-params": import_zod3.z.array(import_zod3.z.string()).readonly().optional(),
1179
+ "x-formspec-schemaSource": import_zod3.z.string().optional()
1180
+ }).passthrough()
1181
+ );
1182
+
1183
+ // src/validate/constraint-validator.ts
1184
+ var import_analysis = require("@formspec/analysis");
1185
+ function validateFieldNode(ctx, field) {
1186
+ const analysis = (0, import_analysis.analyzeConstraintTargets)(
1187
+ field.name,
1188
+ field.type,
1189
+ field.constraints,
1190
+ ctx.typeRegistry,
1191
+ ctx.extensionRegistry === void 0 ? void 0 : {
1192
+ extensionRegistry: ctx.extensionRegistry
1193
+ }
1194
+ );
1195
+ ctx.diagnostics.push(...analysis.diagnostics);
1196
+ if (field.type.kind === "object") {
1197
+ for (const property of field.type.properties) {
1198
+ validateObjectProperty(ctx, field.name, property);
1199
+ }
1200
+ }
1201
+ }
1202
+ function validateObjectProperty(ctx, parentName, property) {
1203
+ const qualifiedName = `${parentName}.${property.name}`;
1204
+ const analysis = (0, import_analysis.analyzeConstraintTargets)(
1205
+ qualifiedName,
1206
+ property.type,
1207
+ property.constraints,
1208
+ ctx.typeRegistry,
1209
+ ctx.extensionRegistry === void 0 ? void 0 : {
1210
+ extensionRegistry: ctx.extensionRegistry
1211
+ }
1212
+ );
1213
+ ctx.diagnostics.push(...analysis.diagnostics);
1214
+ if (property.type.kind === "object") {
1215
+ for (const nestedProperty of property.type.properties) {
1216
+ validateObjectProperty(ctx, qualifiedName, nestedProperty);
1217
+ }
1218
+ }
1219
+ }
1220
+ function validateElement(ctx, element) {
1221
+ switch (element.kind) {
1222
+ case "field":
1223
+ validateFieldNode(ctx, element);
1224
+ break;
1225
+ case "group":
1226
+ for (const child of element.elements) {
1227
+ validateElement(ctx, child);
1228
+ }
1229
+ break;
1230
+ case "conditional":
1231
+ for (const child of element.elements) {
1232
+ validateElement(ctx, child);
1233
+ }
1234
+ break;
1235
+ default: {
1236
+ const exhaustive = element;
1237
+ throw new Error(`Unhandled element kind: ${String(exhaustive)}`);
1238
+ }
1239
+ }
1240
+ }
1241
+ function validateIR(ir, options) {
1242
+ const ctx = {
1243
+ diagnostics: [],
1244
+ extensionRegistry: options?.extensionRegistry,
1245
+ typeRegistry: ir.typeRegistry
1246
+ };
1247
+ for (const element of ir.elements) {
1248
+ validateElement(ctx, element);
1249
+ }
1250
+ return {
1251
+ diagnostics: ctx.diagnostics,
1252
+ valid: ctx.diagnostics.every((diagnostic) => diagnostic.severity !== "error")
1253
+ };
1254
+ }
1255
+
1256
+ // src/browser.ts
1257
+ function buildFormSchemas(form, options) {
1258
+ return {
1259
+ jsonSchema: generateJsonSchema(form, options),
1260
+ uiSchema: generateUiSchema(form)
1261
+ };
1262
+ }
1263
+ // Annotate the CommonJS export names for ESM import in node:
1264
+ 0 && (module.exports = {
1265
+ buildFormSchemas,
1266
+ canonicalizeChainDSL,
1267
+ categorizationSchema,
1268
+ categorySchema,
1269
+ controlSchema,
1270
+ createExtensionRegistry,
1271
+ generateJsonSchema,
1272
+ generateJsonSchemaFromIR,
1273
+ generateUiSchema,
1274
+ getSchemaExtension,
1275
+ groupLayoutSchema,
1276
+ horizontalLayoutSchema,
1277
+ jsonSchema7Schema,
1278
+ jsonSchemaTypeSchema,
1279
+ labelElementSchema,
1280
+ ruleConditionSchema,
1281
+ ruleEffectSchema,
1282
+ ruleSchema,
1283
+ schemaBasedConditionSchema,
1284
+ setSchemaExtension,
1285
+ uiSchemaElementSchema,
1286
+ uiSchemaElementTypeSchema,
1287
+ uiSchemaSchema,
1288
+ validateIR,
1289
+ verticalLayoutSchema
1290
+ });
1291
+ //# sourceMappingURL=browser.cjs.map