@formspec/build 0.1.0-alpha.55 → 0.1.0-alpha.58

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.
@@ -905,11 +905,12 @@ export declare interface FormSpecConfig {
905
905
  readonly vendorPrefix?: string;
906
906
  /**
907
907
  * JSON Schema representation for static enums.
908
- * - "enum": flat { "enum": ["a", "b"] }
909
- * - "oneOf": { "oneOf": [{ "const": "a" }, ...] }
908
+ * - "enum": compact `enum` output, plus a display-name extension when labels exist
909
+ * - "oneOf": per-member `const` output, with `title` only for distinct labels
910
+ * - "smart-size": uses `enum` unless a distinct display label would be lost
910
911
  * @defaultValue "enum"
911
912
  */
912
- readonly enumSerialization?: "enum" | "oneOf";
913
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
913
914
  /**
914
915
  * Per-package configuration overrides for monorepos.
915
916
  * Keys are glob patterns matched against file paths relative to
@@ -928,7 +929,7 @@ declare interface FormSpecPackageOverride {
928
929
  /** Override constraint surface for this package. */
929
930
  readonly constraints?: ConstraintConfig;
930
931
  /** Override enum serialization for this package. */
931
- readonly enumSerialization?: "enum" | "oneOf";
932
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
932
933
  /** Override metadata policy for this package. */
933
934
  readonly metadata?: MetadataPolicyInput_2;
934
935
  }
@@ -1011,7 +1012,7 @@ export declare interface GenerateJsonSchemaOptions {
1011
1012
  * JSON Schema representation to use for static enums.
1012
1013
  * @defaultValue "enum"
1013
1014
  */
1014
- readonly enumSerialization?: "enum" | "oneOf";
1015
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
1015
1016
  /** Metadata resolution policy for chain DSL generation. */
1016
1017
  readonly metadata?: MetadataPolicyInput | undefined;
1017
1018
  /**
@@ -2173,7 +2174,7 @@ export declare interface StaticSchemaGenerationOptions {
2173
2174
  * @defaultValue "enum"
2174
2175
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
2175
2176
  */
2176
- readonly enumSerialization?: "enum" | "oneOf";
2177
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
2177
2178
  /**
2178
2179
  * Metadata resolution policy for static schema generation.
2179
2180
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
@@ -905,11 +905,12 @@ export declare interface FormSpecConfig {
905
905
  readonly vendorPrefix?: string;
906
906
  /**
907
907
  * JSON Schema representation for static enums.
908
- * - "enum": flat { "enum": ["a", "b"] }
909
- * - "oneOf": { "oneOf": [{ "const": "a" }, ...] }
908
+ * - "enum": compact `enum` output, plus a display-name extension when labels exist
909
+ * - "oneOf": per-member `const` output, with `title` only for distinct labels
910
+ * - "smart-size": uses `enum` unless a distinct display label would be lost
910
911
  * @defaultValue "enum"
911
912
  */
912
- readonly enumSerialization?: "enum" | "oneOf";
913
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
913
914
  /**
914
915
  * Per-package configuration overrides for monorepos.
915
916
  * Keys are glob patterns matched against file paths relative to
@@ -928,7 +929,7 @@ declare interface FormSpecPackageOverride {
928
929
  /** Override constraint surface for this package. */
929
930
  readonly constraints?: ConstraintConfig;
930
931
  /** Override enum serialization for this package. */
931
- readonly enumSerialization?: "enum" | "oneOf";
932
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
932
933
  /** Override metadata policy for this package. */
933
934
  readonly metadata?: MetadataPolicyInput_2;
934
935
  }
@@ -1011,7 +1012,7 @@ export declare interface GenerateJsonSchemaOptions {
1011
1012
  * JSON Schema representation to use for static enums.
1012
1013
  * @defaultValue "enum"
1013
1014
  */
1014
- readonly enumSerialization?: "enum" | "oneOf";
1015
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
1015
1016
  /** Metadata resolution policy for chain DSL generation. */
1016
1017
  readonly metadata?: MetadataPolicyInput | undefined;
1017
1018
  /**
@@ -2173,7 +2174,7 @@ export declare interface StaticSchemaGenerationOptions {
2173
2174
  * @defaultValue "enum"
2174
2175
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
2175
2176
  */
2176
- readonly enumSerialization?: "enum" | "oneOf";
2177
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
2177
2178
  /**
2178
2179
  * Metadata resolution policy for static schema generation.
2179
2180
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
@@ -905,11 +905,12 @@ export declare interface FormSpecConfig {
905
905
  readonly vendorPrefix?: string;
906
906
  /**
907
907
  * JSON Schema representation for static enums.
908
- * - "enum": flat { "enum": ["a", "b"] }
909
- * - "oneOf": { "oneOf": [{ "const": "a" }, ...] }
908
+ * - "enum": compact `enum` output, plus a display-name extension when labels exist
909
+ * - "oneOf": per-member `const` output, with `title` only for distinct labels
910
+ * - "smart-size": uses `enum` unless a distinct display label would be lost
910
911
  * @defaultValue "enum"
911
912
  */
912
- readonly enumSerialization?: "enum" | "oneOf";
913
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
913
914
  /**
914
915
  * Per-package configuration overrides for monorepos.
915
916
  * Keys are glob patterns matched against file paths relative to
@@ -928,7 +929,7 @@ declare interface FormSpecPackageOverride {
928
929
  /** Override constraint surface for this package. */
929
930
  readonly constraints?: ConstraintConfig;
930
931
  /** Override enum serialization for this package. */
931
- readonly enumSerialization?: "enum" | "oneOf";
932
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
932
933
  /** Override metadata policy for this package. */
933
934
  readonly metadata?: MetadataPolicyInput_2;
934
935
  }
@@ -1011,7 +1012,7 @@ export declare interface GenerateJsonSchemaOptions {
1011
1012
  * JSON Schema representation to use for static enums.
1012
1013
  * @defaultValue "enum"
1013
1014
  */
1014
- readonly enumSerialization?: "enum" | "oneOf";
1015
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
1015
1016
  /** Metadata resolution policy for chain DSL generation. */
1016
1017
  readonly metadata?: MetadataPolicyInput | undefined;
1017
1018
  /**
@@ -2173,7 +2174,7 @@ export declare interface StaticSchemaGenerationOptions {
2173
2174
  * @defaultValue "enum"
2174
2175
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
2175
2176
  */
2176
- readonly enumSerialization?: "enum" | "oneOf";
2177
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
2177
2178
  /**
2178
2179
  * Metadata resolution policy for static schema generation.
2179
2180
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
package/dist/build.d.ts CHANGED
@@ -905,11 +905,12 @@ export declare interface FormSpecConfig {
905
905
  readonly vendorPrefix?: string;
906
906
  /**
907
907
  * JSON Schema representation for static enums.
908
- * - "enum": flat { "enum": ["a", "b"] }
909
- * - "oneOf": { "oneOf": [{ "const": "a" }, ...] }
908
+ * - "enum": compact `enum` output, plus a display-name extension when labels exist
909
+ * - "oneOf": per-member `const` output, with `title` only for distinct labels
910
+ * - "smart-size": uses `enum` unless a distinct display label would be lost
910
911
  * @defaultValue "enum"
911
912
  */
912
- readonly enumSerialization?: "enum" | "oneOf";
913
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
913
914
  /**
914
915
  * Per-package configuration overrides for monorepos.
915
916
  * Keys are glob patterns matched against file paths relative to
@@ -928,7 +929,7 @@ declare interface FormSpecPackageOverride {
928
929
  /** Override constraint surface for this package. */
929
930
  readonly constraints?: ConstraintConfig;
930
931
  /** Override enum serialization for this package. */
931
- readonly enumSerialization?: "enum" | "oneOf";
932
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
932
933
  /** Override metadata policy for this package. */
933
934
  readonly metadata?: MetadataPolicyInput_2;
934
935
  }
@@ -1011,7 +1012,7 @@ export declare interface GenerateJsonSchemaOptions {
1011
1012
  * JSON Schema representation to use for static enums.
1012
1013
  * @defaultValue "enum"
1013
1014
  */
1014
- readonly enumSerialization?: "enum" | "oneOf";
1015
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
1015
1016
  /** Metadata resolution policy for chain DSL generation. */
1016
1017
  readonly metadata?: MetadataPolicyInput | undefined;
1017
1018
  /**
@@ -2173,7 +2174,7 @@ export declare interface StaticSchemaGenerationOptions {
2173
2174
  * @defaultValue "enum"
2174
2175
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
2175
2176
  */
2176
- readonly enumSerialization?: "enum" | "oneOf";
2177
+ readonly enumSerialization?: "enum" | "oneOf" | "smart-size";
2177
2178
  /**
2178
2179
  * Metadata resolution policy for static schema generation.
2179
2180
  * @deprecated Provide a `FormSpecConfig` via the `config` option instead.
package/dist/cli.cjs CHANGED
@@ -1018,20 +1018,29 @@ var init_collision_guards = __esm({
1018
1018
  });
1019
1019
 
1020
1020
  // src/json-schema/ir-generator.ts
1021
+ function parseEnumSerialization(value) {
1022
+ switch (value) {
1023
+ case void 0:
1024
+ case "enum":
1025
+ return "enum";
1026
+ case "oneOf":
1027
+ return "oneOf";
1028
+ case "smart-size":
1029
+ return "smart-size";
1030
+ default:
1031
+ throw new Error(
1032
+ `Invalid enumSerialization "${String(value)}". Expected "enum", "oneOf", or "smart-size".`
1033
+ );
1034
+ }
1035
+ }
1021
1036
  function makeContext(options) {
1022
1037
  const vendorPrefix = options?.vendorPrefix ?? "x-formspec";
1023
- const rawEnumSerialization = options?.enumSerialization;
1038
+ const enumSerialization = parseEnumSerialization(options?.enumSerialization);
1024
1039
  if (!vendorPrefix.startsWith("x-")) {
1025
1040
  throw new Error(
1026
1041
  `Invalid vendorPrefix "${vendorPrefix}". Extension JSON Schema keywords must start with "x-".`
1027
1042
  );
1028
1043
  }
1029
- if (rawEnumSerialization !== void 0 && rawEnumSerialization !== "enum" && rawEnumSerialization !== "oneOf") {
1030
- throw new Error(
1031
- `Invalid enumSerialization "${rawEnumSerialization}". Expected "enum" or "oneOf".`
1032
- );
1033
- }
1034
- const enumSerialization = rawEnumSerialization ?? "enum";
1035
1044
  return {
1036
1045
  defs: {},
1037
1046
  typeNameMap: {},
@@ -1239,7 +1248,7 @@ function generatePrimitiveType(type) {
1239
1248
  };
1240
1249
  }
1241
1250
  function generateEnumType(type, ctx) {
1242
- if (ctx.enumSerialization === "oneOf") {
1251
+ if (ctx.enumSerialization === "oneOf" || ctx.enumSerialization === "smart-size" && shouldSerializeEnumAsOneOf(type)) {
1243
1252
  return {
1244
1253
  oneOf: type.members.map((m) => {
1245
1254
  const stringValue = String(m.value);
@@ -1249,12 +1258,21 @@ function generateEnumType(type, ctx) {
1249
1258
  };
1250
1259
  }
1251
1260
  const schema = { enum: type.members.map((m) => m.value) };
1261
+ if (ctx.enumSerialization === "smart-size") {
1262
+ return schema;
1263
+ }
1252
1264
  const displayNames = buildEnumDisplayNameExtension(type);
1253
1265
  if (displayNames !== void 0) {
1254
1266
  schema[`${ctx.vendorPrefix}-display-names`] = displayNames;
1255
1267
  }
1256
1268
  return schema;
1257
1269
  }
1270
+ function shouldSerializeEnumAsOneOf(type) {
1271
+ return type.members.some((member) => {
1272
+ const title = member.displayName ?? String(member.value);
1273
+ return title !== String(member.value);
1274
+ });
1275
+ }
1258
1276
  function buildEnumDisplayNameExtension(type) {
1259
1277
  if (!type.members.some((member) => member.displayName !== void 0)) {
1260
1278
  return void 0;
@@ -2612,6 +2630,7 @@ function processConstraintTag(tagName, text, parsedTag, provenance, node, source
2612
2630
  sourceFile,
2613
2631
  tagName,
2614
2632
  parsedTag,
2633
+ text,
2615
2634
  provenance,
2616
2635
  supportingDeclarations,
2617
2636
  options
@@ -2639,6 +2658,9 @@ function renderSyntheticArgumentExpression(valueKind, argumentText) {
2639
2658
  case "number":
2640
2659
  case "integer":
2641
2660
  case "signedInteger":
2661
+ if (trimmed === "Infinity" || trimmed === "-Infinity" || trimmed === "NaN") {
2662
+ return trimmed;
2663
+ }
2642
2664
  return Number.isFinite(Number(trimmed)) ? trimmed : JSON.stringify(trimmed);
2643
2665
  case "string":
2644
2666
  return JSON.stringify(argumentText);
@@ -2848,7 +2870,7 @@ function hasBuiltinConstraintBroadening(tagName, options) {
2848
2870
  const broadenedTypeId = getBroadenedCustomTypeId(options?.fieldType);
2849
2871
  return broadenedTypeId !== void 0 && options?.extensionRegistry?.findBuiltinConstraintBroadening(broadenedTypeId, tagName) !== void 0;
2850
2872
  }
2851
- function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, parsedTag, provenance, supportingDeclarations, options) {
2873
+ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, parsedTag, rawText, provenance, supportingDeclarations, options) {
2852
2874
  if (!(0, import_internals4.isBuiltinConstraintName)(tagName)) {
2853
2875
  return [];
2854
2876
  }
@@ -2869,8 +2891,10 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2869
2891
  const log2 = (0, import_internal4.getBuildLogger)();
2870
2892
  const broadeningLog = (0, import_internal4.getBroadeningLogger)();
2871
2893
  const syntheticLog = (0, import_internal4.getSyntheticLogger)();
2894
+ const typedParserLog = (0, import_internal4.getTypedParserLogger)();
2872
2895
  const logsEnabled = log2 !== import_core4.noopLogger || broadeningLog !== import_core4.noopLogger;
2873
2896
  const syntheticTraceEnabled = syntheticLog !== import_core4.noopLogger;
2897
+ const typedParserTraceEnabled = typedParserLog !== import_core4.noopLogger;
2874
2898
  const logStart = logsEnabled ? (0, import_internal4.nowMicros)() : 0;
2875
2899
  const subjectTypeKind = logsEnabled ? (0, import_internal4.describeTypeKind)(subjectType, checker) : "";
2876
2900
  function emit(outcome, result2) {
@@ -2978,16 +3002,57 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
2978
3002
  ]);
2979
3003
  }
2980
3004
  }
2981
- const argumentExpression = renderSyntheticArgumentExpression(
2982
- definition.valueKind,
2983
- parsedTag?.argumentText ?? ""
2984
- );
2985
- if (definition.requiresArgument && argumentExpression === null) {
2986
- return emit("A-pass", []);
2987
- }
3005
+ const effectiveArgumentText = parsedTag !== null ? (0, import_internal3.parseTagSyntax)(tagName, rawText).argumentText : rawText;
2988
3006
  if (hasBroadening) {
2989
3007
  return emit("bypass", []);
2990
3008
  }
3009
+ const typedParseResult = (0, import_internal4.parseTagArgument)(tagName, effectiveArgumentText, "build");
3010
+ if (!typedParseResult.ok) {
3011
+ if (typedParserTraceEnabled) {
3012
+ typedParserLog.trace("typed-parser C-reject", {
3013
+ consumer: "build",
3014
+ tag: tagName,
3015
+ placement: nonNullPlacement,
3016
+ subjectTypeKind: subjectTypeKind !== "" ? subjectTypeKind : "-",
3017
+ roleOutcome: "C-reject",
3018
+ diagnosticCode: typedParseResult.diagnostic.code
3019
+ });
3020
+ }
3021
+ let mappedCode;
3022
+ switch (typedParseResult.diagnostic.code) {
3023
+ case "MISSING_TAG_ARGUMENT":
3024
+ mappedCode = "MISSING_TAG_ARGUMENT";
3025
+ break;
3026
+ case "INVALID_TAG_ARGUMENT":
3027
+ mappedCode = "INVALID_TAG_ARGUMENT";
3028
+ break;
3029
+ case "UNKNOWN_TAG":
3030
+ throw new Error(
3031
+ `Unexpected UNKNOWN_TAG from parseTagArgument("${tagName}") \u2014 tag was resolved via getTagDefinition.`
3032
+ );
3033
+ default: {
3034
+ const _exhaustive = typedParseResult.diagnostic.code;
3035
+ throw new Error(`Unknown diagnostic code: ${String(_exhaustive)}`);
3036
+ }
3037
+ }
3038
+ return emit("C-reject", [
3039
+ makeDiagnostic(mappedCode, typedParseResult.diagnostic.message, provenance)
3040
+ ]);
3041
+ }
3042
+ if (typedParserTraceEnabled) {
3043
+ typedParserLog.trace("typed-parser C-pass", {
3044
+ consumer: "build",
3045
+ tag: tagName,
3046
+ placement: nonNullPlacement,
3047
+ subjectTypeKind: subjectTypeKind !== "" ? subjectTypeKind : "-",
3048
+ roleOutcome: "C-pass",
3049
+ valueKind: typedParseResult.value.kind
3050
+ });
3051
+ }
3052
+ const argumentExpression = renderSyntheticArgumentExpression(
3053
+ definition.valueKind,
3054
+ effectiveArgumentText
3055
+ );
2991
3056
  const subjectTypeText = checker.typeToString(subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
2992
3057
  const hostType = options?.hostType ?? subjectType;
2993
3058
  const hostTypeText = checker.typeToString(hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
@@ -7194,7 +7259,7 @@ Usage:
7194
7259
  Options:
7195
7260
  -o, --out-dir <dir> Output directory (default: ./generated)
7196
7261
  -n, --name <name> Base name for output files (default: derived from input)
7197
- --enum-serialization <enum|oneOf>
7262
+ --enum-serialization <enum|oneOf|smart-size>
7198
7263
  Enum JSON Schema representation (default: enum)
7199
7264
  -h, --help Show this help message
7200
7265
 
@@ -7246,8 +7311,10 @@ function parseArgs(args) {
7246
7311
  console.error("Error: --enum-serialization requires a value");
7247
7312
  return null;
7248
7313
  }
7249
- if (nextArg !== "enum" && nextArg !== "oneOf") {
7250
- console.error('Error: --enum-serialization must be "enum" or "oneOf"');
7314
+ if (nextArg !== "enum" && nextArg !== "oneOf" && nextArg !== "smart-size") {
7315
+ console.error(
7316
+ 'Error: --enum-serialization must be "enum", "oneOf", or "smart-size"'
7317
+ );
7251
7318
  return null;
7252
7319
  }
7253
7320
  enumSerialization = nextArg;