@formspec/build 0.1.0-alpha.40 → 0.1.0-alpha.42

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -51,11 +51,35 @@ function normalizeDeclarationPolicy(input) {
51
51
  displayName: normalizeScalarPolicy(input?.displayName)
52
52
  };
53
53
  }
54
+ function normalizeEnumMemberDisplayNamePolicy(input) {
55
+ if (input?.mode === "infer-if-missing") {
56
+ return {
57
+ mode: "infer-if-missing",
58
+ infer: input.infer
59
+ };
60
+ }
61
+ if (input?.mode === "require-explicit") {
62
+ return {
63
+ mode: "require-explicit",
64
+ infer: () => ""
65
+ };
66
+ }
67
+ return {
68
+ mode: "disabled",
69
+ infer: () => ""
70
+ };
71
+ }
72
+ function normalizeEnumMemberPolicy(input) {
73
+ return {
74
+ displayName: normalizeEnumMemberDisplayNamePolicy(input?.displayName)
75
+ };
76
+ }
54
77
  function normalizeMetadataPolicy(input) {
55
78
  return {
56
79
  type: normalizeDeclarationPolicy(input?.type),
57
80
  field: normalizeDeclarationPolicy(input?.field),
58
- method: normalizeDeclarationPolicy(input?.method)
81
+ method: normalizeDeclarationPolicy(input?.method),
82
+ enumMember: normalizeEnumMemberPolicy(input?.enumMember)
59
83
  };
60
84
  }
61
85
  function getDeclarationMetadataPolicy(policy, declarationKind) {
@@ -161,6 +185,40 @@ function pickResolvedMetadataValue(baseValue, overlayValue) {
161
185
  }
162
186
  return baseValue ?? overlayValue;
163
187
  }
188
+ function resolveEnumMemberDisplayName(current, policy, context) {
189
+ if (current !== void 0) {
190
+ return current;
191
+ }
192
+ if (policy.mode === "require-explicit") {
193
+ throw new Error(
194
+ `Metadata policy requires explicit displayName for enum member "${context.logicalName}" on the ${context.surface} surface.`
195
+ );
196
+ }
197
+ if (policy.mode !== "infer-if-missing") {
198
+ return void 0;
199
+ }
200
+ const inferredValue = policy.infer(context).trim();
201
+ return inferredValue !== "" ? inferredValue : void 0;
202
+ }
203
+ function resolveEnumTypeMetadata(type, options) {
204
+ const members = type.members.map((member) => {
205
+ const displayName = resolveEnumMemberDisplayName(
206
+ member.displayName,
207
+ options.policy.enumMember.displayName,
208
+ {
209
+ surface: options.surface,
210
+ logicalName: String(member.value),
211
+ memberValue: member.value,
212
+ ...options.buildContext !== void 0 && { buildContext: options.buildContext }
213
+ }
214
+ );
215
+ if (displayName === member.displayName) {
216
+ return member;
217
+ }
218
+ return displayName === void 0 ? { value: member.value } : { value: member.value, displayName };
219
+ });
220
+ return members.some((member, index) => member !== type.members[index]) ? { ...type, members } : type;
221
+ }
164
222
  function resolveTypeNodeMetadata(type, options) {
165
223
  switch (type.kind) {
166
224
  case "array":
@@ -183,9 +241,10 @@ function resolveTypeNodeMetadata(type, options) {
183
241
  ...type,
184
242
  members: type.members.map((member) => resolveTypeNodeMetadata(member, options))
185
243
  };
244
+ case "enum":
245
+ return resolveEnumTypeMetadata(type, options);
186
246
  case "reference":
187
247
  case "primitive":
188
- case "enum":
189
248
  case "dynamic":
190
249
  case "custom":
191
250
  return type;
@@ -288,11 +347,10 @@ function getDisplayName(metadata) {
288
347
  return metadata?.displayName?.value;
289
348
  }
290
349
  function resolveFormIRMetadata(ir, options) {
291
- const rootLogicalName = options.rootLogicalName ?? ir.name ?? "FormSpec";
292
- const metadata = resolveResolvedMetadata(ir.metadata, options.policy.type, {
350
+ const metadata = options.resolveRootTypeMetadata === false ? ir.metadata : resolveResolvedMetadata(ir.metadata, options.policy.type, {
293
351
  surface: options.surface,
294
352
  declarationKind: "type",
295
- logicalName: rootLogicalName,
353
+ logicalName: options.rootLogicalName ?? ir.name ?? "FormSpec",
296
354
  ...options.buildContext !== void 0 && { buildContext: options.buildContext }
297
355
  });
298
356
  return {
@@ -328,7 +386,7 @@ function canonicalizeChainDSL(form, options) {
328
386
  const metadataPolicy = normalizeMetadataPolicy(
329
387
  options?.metadata ?? _getFormSpecMetadataPolicy(form)
330
388
  );
331
- return {
389
+ const ir = {
332
390
  kind: "form-ir",
333
391
  irVersion: IR_VERSION,
334
392
  elements: canonicalizeElements(form.elements, metadataPolicy),
@@ -336,6 +394,13 @@ function canonicalizeChainDSL(form, options) {
336
394
  typeRegistry: {},
337
395
  provenance: CHAIN_DSL_PROVENANCE
338
396
  };
397
+ return resolveFormIRMetadata(ir, {
398
+ policy: metadataPolicy,
399
+ surface: "chain-dsl",
400
+ // Chain DSL has no root/type-metadata authoring surface, so only resolve
401
+ // field/type-registry metadata and enum-member labels here.
402
+ resolveRootTypeMetadata: false
403
+ });
339
404
  }
340
405
  function canonicalizeElements(elements, metadataPolicy) {
341
406
  return elements.map((element) => canonicalizeElement(element, metadataPolicy));
@@ -873,17 +938,25 @@ function assertNoSerializedNameCollisions(ir) {
873
938
  // src/json-schema/ir-generator.ts
874
939
  function makeContext(options) {
875
940
  const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
941
+ const rawEnumSerialization = options?.enumSerialization;
876
942
  if (!vendorPrefix.startsWith("x-")) {
877
943
  throw new Error(
878
944
  `Invalid vendorPrefix "${vendorPrefix}". Extension JSON Schema keywords must start with "x-".`
879
945
  );
880
946
  }
947
+ if (rawEnumSerialization !== void 0 && rawEnumSerialization !== "enum" && rawEnumSerialization !== "oneOf") {
948
+ throw new Error(
949
+ `Invalid enumSerialization "${rawEnumSerialization}". Expected "enum" or "oneOf".`
950
+ );
951
+ }
952
+ const enumSerialization = rawEnumSerialization ?? "enum";
881
953
  return {
882
954
  defs: {},
883
955
  typeNameMap: {},
884
956
  typeRegistry: {},
885
957
  extensionRegistry: options?.extensionRegistry,
886
- vendorPrefix
958
+ vendorPrefix,
959
+ enumSerialization
887
960
  };
888
961
  }
889
962
  function generateJsonSchemaFromIR(ir, options) {
@@ -1057,7 +1130,7 @@ function generateTypeNode(type, ctx) {
1057
1130
  case "primitive":
1058
1131
  return generatePrimitiveType(type);
1059
1132
  case "enum":
1060
- return generateEnumType(type);
1133
+ return generateEnumType(type, ctx);
1061
1134
  case "array":
1062
1135
  return generateArrayType(type, ctx);
1063
1136
  case "object":
@@ -1083,20 +1156,37 @@ function generatePrimitiveType(type) {
1083
1156
  type: type.primitiveKind === "integer" || type.primitiveKind === "bigint" ? "integer" : type.primitiveKind
1084
1157
  };
1085
1158
  }
1086
- function generateEnumType(type) {
1087
- const hasDisplayNames = type.members.some((m) => m.displayName !== void 0);
1088
- if (hasDisplayNames) {
1159
+ function generateEnumType(type, ctx) {
1160
+ if (ctx.enumSerialization === "oneOf") {
1089
1161
  return {
1090
- oneOf: type.members.map((m) => {
1091
- const entry = { const: m.value };
1092
- if (m.displayName !== void 0) {
1093
- entry.title = m.displayName;
1094
- }
1095
- return entry;
1096
- })
1162
+ oneOf: type.members.map((m) => ({
1163
+ const: m.value,
1164
+ title: m.displayName ?? String(m.value)
1165
+ }))
1097
1166
  };
1098
1167
  }
1099
- return { enum: type.members.map((m) => m.value) };
1168
+ const schema = { enum: type.members.map((m) => m.value) };
1169
+ const displayNames = buildEnumDisplayNameExtension(type);
1170
+ if (displayNames !== void 0) {
1171
+ schema[`${ctx.vendorPrefix}-display-names`] = displayNames;
1172
+ }
1173
+ return schema;
1174
+ }
1175
+ function buildEnumDisplayNameExtension(type) {
1176
+ if (!type.members.some((member) => member.displayName !== void 0)) {
1177
+ return void 0;
1178
+ }
1179
+ const displayNames = /* @__PURE__ */ Object.create(null);
1180
+ for (const member of type.members) {
1181
+ const key = String(member.value);
1182
+ if (Object.hasOwn(displayNames, key)) {
1183
+ throw new Error(
1184
+ `Enum display-name key "${key}" is ambiguous after stringification. Use oneOf serialization for mixed string/number enum values that collide.`
1185
+ );
1186
+ }
1187
+ displayNames[key] = member.displayName ?? key;
1188
+ }
1189
+ return displayNames;
1100
1190
  }
1101
1191
  function generateArrayType(type, ctx) {
1102
1192
  return {
@@ -1445,6 +1535,66 @@ function generateCustomType(type, ctx) {
1445
1535
  }
1446
1536
  return registration.toJsonSchema(type.payload, ctx.vendorPrefix);
1447
1537
  }
1538
+ var JSON_SCHEMA_STRUCTURAL_KEYWORDS = /* @__PURE__ */ new Set([
1539
+ "$schema",
1540
+ "$ref",
1541
+ "$defs",
1542
+ "$id",
1543
+ "$anchor",
1544
+ "$dynamicRef",
1545
+ "$dynamicAnchor",
1546
+ "$vocabulary",
1547
+ "$comment",
1548
+ "type",
1549
+ "enum",
1550
+ "const",
1551
+ "properties",
1552
+ "patternProperties",
1553
+ "additionalProperties",
1554
+ "required",
1555
+ "items",
1556
+ "prefixItems",
1557
+ "additionalItems",
1558
+ "contains",
1559
+ "allOf",
1560
+ "oneOf",
1561
+ "anyOf",
1562
+ "not",
1563
+ "if",
1564
+ "then",
1565
+ "else",
1566
+ "minimum",
1567
+ "maximum",
1568
+ "exclusiveMinimum",
1569
+ "exclusiveMaximum",
1570
+ "multipleOf",
1571
+ "minLength",
1572
+ "maxLength",
1573
+ "pattern",
1574
+ "minItems",
1575
+ "maxItems",
1576
+ "uniqueItems",
1577
+ "minProperties",
1578
+ "maxProperties",
1579
+ "minContains",
1580
+ "maxContains",
1581
+ "format",
1582
+ "title",
1583
+ "description",
1584
+ "default",
1585
+ "deprecated",
1586
+ "readOnly",
1587
+ "writeOnly",
1588
+ "examples",
1589
+ "dependentRequired",
1590
+ "dependentSchemas",
1591
+ "propertyNames",
1592
+ "unevaluatedItems",
1593
+ "unevaluatedProperties",
1594
+ "contentEncoding",
1595
+ "contentMediaType",
1596
+ "contentSchema"
1597
+ ]);
1448
1598
  function applyCustomConstraint(schema, constraint, ctx) {
1449
1599
  const registration = ctx.extensionRegistry?.findConstraint(constraint.constraintId);
1450
1600
  if (registration === void 0) {
@@ -1452,12 +1602,25 @@ function applyCustomConstraint(schema, constraint, ctx) {
1452
1602
  `Cannot generate JSON Schema for custom constraint "${constraint.constraintId}" without a matching extension registration`
1453
1603
  );
1454
1604
  }
1455
- assignVendorPrefixedExtensionKeywords(
1456
- schema,
1457
- registration.toJsonSchema(constraint.payload, ctx.vendorPrefix),
1458
- ctx.vendorPrefix,
1459
- `custom constraint "${constraint.constraintId}"`
1460
- );
1605
+ const extensionSchema = registration.toJsonSchema(constraint.payload, ctx.vendorPrefix);
1606
+ if (registration.emitsVocabularyKeywords) {
1607
+ const target = schema;
1608
+ for (const [key, value] of Object.entries(extensionSchema)) {
1609
+ if (JSON_SCHEMA_STRUCTURAL_KEYWORDS.has(key)) {
1610
+ throw new Error(
1611
+ `Custom constraint "${constraint.constraintId}" with emitsVocabularyKeywords must not overwrite standard JSON Schema keyword "${key}"`
1612
+ );
1613
+ }
1614
+ target[key] = value;
1615
+ }
1616
+ } else {
1617
+ assignVendorPrefixedExtensionKeywords(
1618
+ schema,
1619
+ extensionSchema,
1620
+ ctx.vendorPrefix,
1621
+ `custom constraint "${constraint.constraintId}"`
1622
+ );
1623
+ }
1461
1624
  }
1462
1625
  function applyCustomAnnotation(schema, annotation, ctx) {
1463
1626
  const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);
@@ -1489,11 +1652,17 @@ function assignVendorPrefixedExtensionKeywords(schema, extensionSchema, vendorPr
1489
1652
 
1490
1653
  // src/json-schema/generator.ts
1491
1654
  function generateJsonSchema(form, options) {
1655
+ const metadata = options?.metadata;
1656
+ const vendorPrefix = options?.vendorPrefix;
1657
+ const enumSerialization = options?.enumSerialization;
1492
1658
  const ir = canonicalizeChainDSL(
1493
1659
  form,
1494
- options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
1660
+ metadata !== void 0 ? { metadata } : void 0
1495
1661
  );
1496
- const internalOptions = options?.vendorPrefix === void 0 ? void 0 : { vendorPrefix: options.vendorPrefix };
1662
+ const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
1663
+ ...vendorPrefix !== void 0 && { vendorPrefix },
1664
+ ...enumSerialization !== void 0 && { enumSerialization }
1665
+ };
1497
1666
  return generateJsonSchemaFromIR(ir, internalOptions);
1498
1667
  }
1499
1668
 
@@ -5465,6 +5634,7 @@ function generateSchemasFromClass(options) {
5465
5634
  {
5466
5635
  extensionRegistry: options.extensionRegistry,
5467
5636
  metadata: options.metadata,
5637
+ enumSerialization: options.enumSerialization,
5468
5638
  vendorPrefix: options.vendorPrefix
5469
5639
  }
5470
5640
  );
@@ -5594,6 +5764,7 @@ function generateSchemasFromDetailedProgramContext(ctx, filePath, typeName, opti
5594
5764
  {
5595
5765
  extensionRegistry: options.extensionRegistry,
5596
5766
  metadata: options.metadata,
5767
+ enumSerialization: options.enumSerialization,
5597
5768
  vendorPrefix: options.vendorPrefix
5598
5769
  }
5599
5770
  );
@@ -5793,7 +5964,7 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
5793
5964
  column: 0
5794
5965
  }
5795
5966
  };
5796
- const schema = generateJsonSchemaFromIR(
5967
+ const ir = resolveFormIRMetadata(
5797
5968
  {
5798
5969
  kind: "form-ir",
5799
5970
  name: root.name,
@@ -5804,8 +5975,17 @@ function toStandaloneJsonSchema(root, typeRegistry, options) {
5804
5975
  typeRegistry,
5805
5976
  provenance: syntheticField.provenance
5806
5977
  },
5978
+ {
5979
+ policy: normalizeMetadataPolicy(options?.metadata),
5980
+ surface: "tsdoc",
5981
+ rootLogicalName: root.name
5982
+ }
5983
+ );
5984
+ const schema = generateJsonSchemaFromIR(
5985
+ ir,
5807
5986
  {
5808
5987
  extensionRegistry: options?.extensionRegistry,
5988
+ enumSerialization: options?.enumSerialization,
5809
5989
  vendorPrefix: options?.vendorPrefix
5810
5990
  }
5811
5991
  );
@@ -5832,6 +6012,7 @@ function generateSchemasFromAnalysis(analysis, filePath, options) {
5832
6012
  { file: filePath },
5833
6013
  {
5834
6014
  extensionRegistry: options?.extensionRegistry,
6015
+ enumSerialization: options?.enumSerialization,
5835
6016
  metadata: options?.metadata,
5836
6017
  vendorPrefix: options?.vendorPrefix
5837
6018
  }
@@ -6229,8 +6410,19 @@ function buildFormSchemas(form, options) {
6229
6410
  };
6230
6411
  }
6231
6412
  function writeSchemas(form, options) {
6232
- const { outDir, name = "schema", indent = 2, vendorPrefix, metadata } = options;
6233
- const buildOptions = vendorPrefix === void 0 && metadata === void 0 ? void 0 : { vendorPrefix, metadata };
6413
+ const {
6414
+ outDir,
6415
+ name = "schema",
6416
+ indent = 2,
6417
+ vendorPrefix,
6418
+ enumSerialization,
6419
+ metadata
6420
+ } = options;
6421
+ const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? void 0 : {
6422
+ ...vendorPrefix !== void 0 && { vendorPrefix },
6423
+ ...enumSerialization !== void 0 && { enumSerialization },
6424
+ ...metadata !== void 0 && { metadata }
6425
+ };
6234
6426
  const { jsonSchema, uiSchema: uiSchema2 } = buildFormSchemas(form, buildOptions);
6235
6427
  if (!fs.existsSync(outDir)) {
6236
6428
  fs.mkdirSync(outDir, { recursive: true });