@formspec/build 0.1.0-alpha.16 → 0.1.0-alpha.17

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 (35) hide show
  1. package/dist/__tests__/fixtures/example-numeric-extension.d.ts +20 -0
  2. package/dist/__tests__/fixtures/example-numeric-extension.d.ts.map +1 -0
  3. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts +1 -0
  4. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts.map +1 -1
  5. package/dist/__tests__/numeric-extension.integration.test.d.ts +2 -0
  6. package/dist/__tests__/numeric-extension.integration.test.d.ts.map +1 -0
  7. package/dist/analyzer/class-analyzer.d.ts +5 -4
  8. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  9. package/dist/analyzer/jsdoc-constraints.d.ts +3 -2
  10. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
  11. package/dist/analyzer/tsdoc-parser.d.ts +18 -2
  12. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
  13. package/dist/browser.cjs +199 -4
  14. package/dist/browser.cjs.map +1 -1
  15. package/dist/browser.js +199 -4
  16. package/dist/browser.js.map +1 -1
  17. package/dist/build.d.ts +28 -2
  18. package/dist/cli.cjs +547 -84
  19. package/dist/cli.cjs.map +1 -1
  20. package/dist/cli.js +547 -84
  21. package/dist/cli.js.map +1 -1
  22. package/dist/extensions/registry.d.ts +25 -1
  23. package/dist/extensions/registry.d.ts.map +1 -1
  24. package/dist/generators/class-schema.d.ts +4 -4
  25. package/dist/generators/class-schema.d.ts.map +1 -1
  26. package/dist/index.cjs +546 -84
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +546 -84
  29. package/dist/index.js.map +1 -1
  30. package/dist/internals.cjs +645 -73
  31. package/dist/internals.cjs.map +1 -1
  32. package/dist/internals.js +643 -71
  33. package/dist/internals.js.map +1 -1
  34. package/dist/validate/constraint-validator.d.ts.map +1 -1
  35. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internals.ts","../src/canonicalize/chain-dsl-canonicalizer.ts","../src/canonicalize/tsdoc-canonicalizer.ts","../src/analyzer/program.ts","../src/analyzer/class-analyzer.ts","../src/analyzer/jsdoc-constraints.ts","../src/analyzer/tsdoc-parser.ts","../src/analyzer/json-utils.ts","../src/json-schema/ir-generator.ts","../src/ui-schema/schema.ts","../src/ui-schema/ir-generator.ts","../src/generators/class-schema.ts","../src/validate/constraint-validator.ts","../src/extensions/registry.ts","../src/generators/method-schema.ts"],"sourcesContent":["/**\n * Internal APIs for `@formspec/build`.\n *\n * This entry point exposes low-level analyzer and generator functions\n * used by `@formspec/cli`. These are NOT part of the public API and\n * may change without notice between versions.\n *\n * @remarks\n * Prefer the high-level functions from `@formspec/build` (e.g.,\n * `generateSchemasFromClass`, `buildFormSchemas`) for most use cases.\n *\n * @packageDocumentation\n */\n\n// Canonicalize: DSL → FormIR\nexport { canonicalizeChainDSL } from \"./canonicalize/index.js\";\n\n// Canonicalization: TSDoc → FormIR\nexport { canonicalizeTSDoc } from \"./canonicalize/index.js\";\nexport type { TSDocSource } from \"./canonicalize/index.js\";\n\n// Analyzer: program context and type lookup\nexport {\n createProgramContext,\n findClassByName,\n findInterfaceByName,\n findTypeAliasByName,\n} from \"./analyzer/program.js\";\n\n// Analyzer: IR analysis (class, interface, type alias)\nexport {\n analyzeClassToIR,\n analyzeInterfaceToIR,\n analyzeTypeAliasToIR,\n} from \"./analyzer/class-analyzer.js\";\nexport type {\n IRClassAnalysis,\n FieldLayoutMetadata,\n AnalyzeTypeAliasToIRResult,\n} from \"./analyzer/class-analyzer.js\";\n\n// Generators: class schema (now routes through IR)\nexport { generateClassSchemas } from \"./generators/class-schema.js\";\n\n// JSON Schema 2020-12: IR-based generator\nexport { generateJsonSchemaFromIR } from \"./json-schema/ir-generator.js\";\nexport type { JsonSchema2020 } from \"./json-schema/ir-generator.js\";\n\n// UI Schema: IR-based generator\nexport { generateUiSchemaFromIR } from \"./ui-schema/ir-generator.js\";\n\n// Validate: constraint validation and contradiction detection\nexport { validateIR } from \"./validate/index.js\";\nexport type {\n ValidationDiagnostic,\n ValidationResult,\n ValidateIROptions,\n} from \"./validate/index.js\";\n\n// Extensions: extension registry for custom types, constraints, annotations\nexport { createExtensionRegistry } from \"./extensions/index.js\";\nexport type { ExtensionRegistry } from \"./extensions/index.js\";\n\n// Generators: method schema\nexport { generateMethodSchemas, collectFormSpecReferences } from \"./generators/method-schema.js\";\nexport type { LoadedFormSpecSchemas, MethodSchemas } from \"./generators/method-schema.js\";\n","/**\n * Canonicalizer that translates chain DSL `FormSpec` objects into the\n * canonical FormIR intermediate representation.\n *\n * This module maps the runtime objects produced by `@formspec/dsl` builder\n * functions (`field.*`, `group`, `when`, `formspec`) into the IR that all\n * downstream phases (validation, JSON Schema generation, UI Schema generation)\n * consume.\n */\n\nimport type {\n // Source types (chain DSL)\n AnyField,\n ArrayField,\n BooleanField,\n Conditional,\n DynamicEnumField,\n DynamicSchemaField,\n EnumOptionValue,\n FormElement,\n FormSpec,\n Group,\n NumberField,\n ObjectField,\n StaticEnumField,\n TextField,\n // IR types\n JsonValue,\n AnnotationNode,\n ArrayTypeNode,\n ConstraintNode,\n ConditionalLayoutNode,\n DisplayNameAnnotationNode,\n DynamicTypeNode,\n EnumMember,\n EnumTypeNode,\n FieldNode,\n FormIR,\n FormIRElement,\n GroupLayoutNode,\n LengthConstraintNode,\n NumericConstraintNode,\n ObjectProperty,\n PatternConstraintNode,\n ObjectTypeNode,\n PlaceholderAnnotationNode,\n PrimitiveTypeNode,\n Provenance,\n TypeNode,\n} from \"@formspec/core\";\nimport { IR_VERSION } from \"@formspec/core\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Default provenance for chain DSL nodes (no source location available). */\nconst CHAIN_DSL_PROVENANCE: Provenance = {\n surface: \"chain-dsl\",\n file: \"\",\n line: 0,\n column: 0,\n} as const;\n\n// =============================================================================\n// TYPE GUARDS\n// =============================================================================\n\nfunction isGroup(el: FormElement): el is Group<readonly FormElement[]> {\n return el._type === \"group\";\n}\n\nfunction isConditional(\n el: FormElement\n): el is Conditional<string, unknown, readonly FormElement[]> {\n return el._type === \"conditional\";\n}\n\nfunction isField(el: FormElement): el is AnyField {\n return el._type === \"field\";\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Translates a chain DSL `FormSpec` into the canonical `FormIR`.\n *\n * @param form - A form specification created via `formspec(...)` from `@formspec/dsl`\n * @returns The canonical intermediate representation\n */\nexport function canonicalizeChainDSL(form: FormSpec<readonly FormElement[]>): FormIR {\n return {\n kind: \"form-ir\",\n irVersion: IR_VERSION,\n elements: canonicalizeElements(form.elements),\n typeRegistry: {},\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n// =============================================================================\n// ELEMENT CANONICALIZATION\n// =============================================================================\n\n/**\n * Canonicalizes an array of chain DSL form elements into IR elements.\n */\nfunction canonicalizeElements(elements: readonly FormElement[]): FormIRElement[] {\n return elements.map(canonicalizeElement);\n}\n\n/**\n * Dispatches a single form element to its specific canonicalization function.\n */\nfunction canonicalizeElement(element: FormElement): FormIRElement {\n if (isField(element)) {\n return canonicalizeField(element);\n }\n if (isGroup(element)) {\n return canonicalizeGroup(element);\n }\n if (isConditional(element)) {\n return canonicalizeConditional(element);\n }\n const _exhaustive: never = element;\n throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);\n}\n\n// =============================================================================\n// FIELD CANONICALIZATION\n// =============================================================================\n\n/**\n * Dispatches a field element to its type-specific canonicalization function.\n */\nfunction canonicalizeField(field: AnyField): FieldNode {\n switch (field._field) {\n case \"text\":\n return canonicalizeTextField(field);\n case \"number\":\n return canonicalizeNumberField(field);\n case \"boolean\":\n return canonicalizeBooleanField(field);\n case \"enum\":\n return canonicalizeStaticEnumField(field);\n case \"dynamic_enum\":\n return canonicalizeDynamicEnumField(field);\n case \"dynamic_schema\":\n return canonicalizeDynamicSchemaField(field);\n case \"array\":\n return canonicalizeArrayField(field);\n case \"object\":\n return canonicalizeObjectField(field);\n default: {\n const _exhaustive: never = field;\n throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\n// =============================================================================\n// SPECIFIC FIELD TYPE CANONICALIZERS\n// =============================================================================\n\nfunction canonicalizeTextField(field: TextField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"string\" };\n const constraints: ConstraintNode[] = [];\n\n if (field.minLength !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minLength\",\n value: field.minLength,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.maxLength !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maxLength\",\n value: field.maxLength,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.pattern !== undefined) {\n const c: PatternConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"pattern\",\n pattern: field.pattern,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label, field.placeholder),\n constraints\n );\n}\n\nfunction canonicalizeNumberField(field: NumberField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"number\" };\n const constraints: ConstraintNode[] = [];\n\n if (field.min !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minimum\",\n value: field.min,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.max !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maximum\",\n value: field.max,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.multipleOf !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"multipleOf\",\n value: field.multipleOf,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label),\n constraints\n );\n}\n\nfunction canonicalizeBooleanField(field: BooleanField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"boolean\" };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeStaticEnumField(\n field: StaticEnumField<string, readonly EnumOptionValue[]>\n): FieldNode {\n const members: EnumMember[] = field.options.map((opt) => {\n if (typeof opt === \"string\") {\n return { value: opt } satisfies EnumMember;\n }\n // Object option with id/label\n return { value: opt.id, displayName: opt.label } satisfies EnumMember;\n });\n\n const type: EnumTypeNode = { kind: \"enum\", members };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeDynamicEnumField(field: DynamicEnumField<string, string>): FieldNode {\n const type: DynamicTypeNode = {\n kind: \"dynamic\",\n dynamicKind: \"enum\",\n sourceKey: field.source,\n parameterFields: field.params ? [...field.params] : [],\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeDynamicSchemaField(field: DynamicSchemaField<string>): FieldNode {\n const type: DynamicTypeNode = {\n kind: \"dynamic\",\n dynamicKind: \"schema\",\n sourceKey: field.schemaSource,\n parameterFields: [],\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeArrayField(field: ArrayField<string, readonly FormElement[]>): FieldNode {\n // Array items form an object type from the sub-elements\n const itemProperties = buildObjectProperties(field.items);\n const itemsType: ObjectTypeNode = {\n kind: \"object\",\n properties: itemProperties,\n additionalProperties: true,\n };\n const type: ArrayTypeNode = { kind: \"array\", items: itemsType };\n\n const constraints: ConstraintNode[] = [];\n if (field.minItems !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minItems\",\n value: field.minItems,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n if (field.maxItems !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maxItems\",\n value: field.maxItems,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label),\n constraints\n );\n}\n\nfunction canonicalizeObjectField(field: ObjectField<string, readonly FormElement[]>): FieldNode {\n const properties = buildObjectProperties(field.properties);\n const type: ObjectTypeNode = {\n kind: \"object\",\n properties,\n additionalProperties: true,\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\n// =============================================================================\n// LAYOUT CANONICALIZATION\n// =============================================================================\n\nfunction canonicalizeGroup(g: Group<readonly FormElement[]>): GroupLayoutNode {\n return {\n kind: \"group\",\n label: g.label,\n elements: canonicalizeElements(g.elements),\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\nfunction canonicalizeConditional(\n c: Conditional<string, unknown, readonly FormElement[]>\n): ConditionalLayoutNode {\n return {\n kind: \"conditional\",\n fieldName: c.field,\n // Conditional values from the chain DSL are JSON-serializable primitives\n // (strings, numbers, booleans) produced by the `is()` predicate helper.\n value: assertJsonValue(c.value),\n elements: canonicalizeElements(c.elements),\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/**\n * Validates that a value is JSON-serializable (`JsonValue`).\n * The chain DSL's `is()` helper constrains conditional values to\n * JSON-compatible primitives, but the TypeScript type is `unknown`.\n * This runtime guard replaces an `as` cast with a validated assertion.\n */\nfunction assertJsonValue(v: unknown): JsonValue {\n if (v === null || typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\") {\n return v;\n }\n if (Array.isArray(v)) {\n return v.map(assertJsonValue);\n }\n if (typeof v === \"object\") {\n const result: Record<string, JsonValue> = {};\n for (const [key, val] of Object.entries(v)) {\n result[key] = assertJsonValue(val);\n }\n return result;\n }\n // Remaining types (function, symbol, bigint, undefined) are not JSON-serializable\n throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);\n}\n\n/**\n * Builds a FieldNode from common field properties.\n */\nfunction buildFieldNode(\n name: string,\n type: TypeNode,\n required: boolean | undefined,\n annotations: AnnotationNode[],\n constraints: ConstraintNode[] = []\n): FieldNode {\n return {\n kind: \"field\",\n name,\n type,\n required: required === true,\n constraints,\n annotations,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n/**\n * Builds annotation nodes from optional label and placeholder values.\n */\nfunction buildAnnotations(label?: string, placeholder?: string): AnnotationNode[] {\n const annotations: AnnotationNode[] = [];\n\n if (label !== undefined) {\n const a: DisplayNameAnnotationNode = {\n kind: \"annotation\",\n annotationKind: \"displayName\",\n value: label,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n annotations.push(a);\n }\n\n if (placeholder !== undefined) {\n const a: PlaceholderAnnotationNode = {\n kind: \"annotation\",\n annotationKind: \"placeholder\",\n value: placeholder,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n annotations.push(a);\n }\n\n return annotations;\n}\n\n/**\n * Converts an array of form elements into ObjectProperty nodes.\n * Used for ObjectField properties and ArrayField items.\n *\n * Only field elements produce properties; groups and conditionals within\n * an object/array context are recursively flattened to extract their fields.\n *\n * Fields inside conditional branches are always marked `optional: true`\n * because their presence in the data depends on the condition being met.\n * This matches the DSL's type inference behavior where conditional fields\n * produce optional properties in `InferFormSchema`.\n *\n * @param elements - The form elements to convert\n * @param insideConditional - Whether these elements are inside a conditional branch\n */\nfunction buildObjectProperties(\n elements: readonly FormElement[],\n insideConditional = false\n): ObjectProperty[] {\n const properties: ObjectProperty[] = [];\n\n for (const el of elements) {\n if (isField(el)) {\n const fieldNode = canonicalizeField(el);\n properties.push({\n name: fieldNode.name,\n type: fieldNode.type,\n // Fields inside a conditional branch are always optional in the\n // data schema, regardless of their `required` flag — the condition\n // may not be met, so the field may be absent.\n optional: insideConditional || !fieldNode.required,\n constraints: fieldNode.constraints,\n annotations: fieldNode.annotations,\n provenance: CHAIN_DSL_PROVENANCE,\n });\n } else if (isGroup(el)) {\n // Groups inside object/array items contribute their fields by flattening.\n // Groups do not affect optionality — pass through the current state.\n properties.push(...buildObjectProperties(el.elements, insideConditional));\n } else if (isConditional(el)) {\n // Conditionals inside object/array items contribute their fields by\n // flattening, but all fields inside are forced optional.\n properties.push(...buildObjectProperties(el.elements, true));\n }\n }\n\n return properties;\n}\n","/**\n * TSDoc canonicalizer — assembles an {@link IRClassAnalysis} into a canonical\n * {@link FormIR}, applying layout metadata from `@Group` and `@ShowWhen`\n * TSDoc tags.\n *\n * The analysis functions in `class-analyzer.ts` produce `FieldNode[]`,\n * `fieldLayouts`, and `typeRegistry` directly. This canonicalizer uses\n * the layout metadata to wrap fields in `GroupLayoutNode` and\n * `ConditionalLayoutNode` elements.\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n GroupLayoutNode,\n ConditionalLayoutNode,\n Provenance,\n} from \"@formspec/core\";\nimport { IR_VERSION } from \"@formspec/core\";\nimport type { IRClassAnalysis, FieldLayoutMetadata } from \"../analyzer/class-analyzer.js\";\n\n/**\n * Source-level metadata for provenance tracking.\n */\nexport interface TSDocSource {\n /** Absolute path to the source file. */\n readonly file: string;\n}\n\n/**\n * Wraps an {@link IRClassAnalysis} (from `analyzeClassToIR`,\n * `analyzeInterfaceToIR`, or `analyzeTypeAliasToIR`) into a canonical\n * {@link FormIR}.\n *\n * Fields with `@Group` TSDoc tags are grouped into `GroupLayoutNode` elements.\n * Fields with `@ShowWhen` TSDoc tags are wrapped in `ConditionalLayoutNode` elements.\n * When both are present, the conditional wraps the field inside the group.\n *\n * @param analysis - IR analysis result (fields are already FieldNode[])\n * @param source - Optional source file metadata for provenance\n * @returns The canonical FormIR\n */\nexport function canonicalizeTSDoc(analysis: IRClassAnalysis, source?: TSDocSource): FormIR {\n const file = source?.file ?? \"\";\n\n const provenance: Provenance = {\n surface: \"tsdoc\",\n file,\n line: 1,\n column: 0,\n };\n\n const elements = assembleElements(analysis.fields, analysis.fieldLayouts, provenance);\n\n return {\n kind: \"form-ir\",\n irVersion: IR_VERSION,\n elements,\n typeRegistry: analysis.typeRegistry,\n ...(analysis.annotations !== undefined &&\n analysis.annotations.length > 0 && { annotations: analysis.annotations }),\n provenance,\n };\n}\n\n/**\n * Assembles flat fields and their layout metadata into a tree of\n * `FormIRElement[]` with groups and conditionals.\n *\n * Fields are processed in order. Consecutive fields with the same\n * `@Group` label are collected into a single `GroupLayoutNode`.\n * Fields with `@ShowWhen` are wrapped in `ConditionalLayoutNode`.\n */\nfunction assembleElements(\n fields: readonly FieldNode[],\n layouts: readonly FieldLayoutMetadata[],\n provenance: Provenance\n): readonly FormIRElement[] {\n const elements: FormIRElement[] = [];\n\n // Group consecutive fields with the same group label together.\n // We use an ordered map to preserve insertion order of groups.\n const groupMap = new Map<string, FormIRElement[]>();\n const topLevelOrder: (\n | { type: \"group\"; label: string }\n | { type: \"element\"; element: FormIRElement }\n )[] = [];\n\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n const layout = layouts[i];\n if (!field || !layout) continue;\n\n // Wrap in conditional if @ShowWhen is present\n const element = wrapInConditional(field, layout, provenance);\n\n if (layout.groupLabel !== undefined) {\n const label = layout.groupLabel;\n let groupElements = groupMap.get(label);\n if (!groupElements) {\n groupElements = [];\n groupMap.set(label, groupElements);\n topLevelOrder.push({ type: \"group\", label });\n }\n groupElements.push(element);\n } else {\n topLevelOrder.push({ type: \"element\", element });\n }\n }\n\n // Assemble the final element array in order\n for (const entry of topLevelOrder) {\n if (entry.type === \"group\") {\n const groupElements = groupMap.get(entry.label);\n if (groupElements) {\n const groupNode: GroupLayoutNode = {\n kind: \"group\",\n label: entry.label,\n elements: groupElements,\n provenance,\n };\n elements.push(groupNode);\n // Clear so duplicate group labels in topLevelOrder don't re-emit\n groupMap.delete(entry.label);\n }\n } else {\n elements.push(entry.element);\n }\n }\n\n return elements;\n}\n\n/**\n * Wraps a field in a `ConditionalLayoutNode` if the layout has `showWhen` metadata.\n */\nfunction wrapInConditional(\n field: FieldNode,\n layout: FieldLayoutMetadata,\n provenance: Provenance\n): FormIRElement {\n if (layout.showWhen === undefined) {\n return field;\n }\n\n const conditional: ConditionalLayoutNode = {\n kind: \"conditional\",\n fieldName: layout.showWhen.field,\n value: layout.showWhen.value,\n elements: [field],\n provenance,\n };\n\n return conditional;\n}\n","/**\n * TypeScript program setup for static analysis.\n *\n * Creates a TypeScript program with type checker from a source file,\n * using the project's tsconfig.json for compiler options.\n */\n\nimport * as ts from \"typescript\";\nimport * as path from \"node:path\";\n\n/**\n * Result of creating a TypeScript program for analysis.\n */\nexport interface ProgramContext {\n /** The TypeScript program */\n program: ts.Program;\n /** Type checker for resolving types */\n checker: ts.TypeChecker;\n /** The source file being analyzed */\n sourceFile: ts.SourceFile;\n}\n\n/**\n * Creates a TypeScript program for analyzing a source file.\n *\n * Looks for tsconfig.json in the file's directory or parent directories.\n * Falls back to default compiler options if no config is found.\n *\n * @param filePath - Absolute path to the TypeScript source file\n * @returns Program context with checker and source file\n */\nexport function createProgramContext(filePath: string): ProgramContext {\n const absolutePath = path.resolve(filePath);\n const fileDir = path.dirname(absolutePath);\n\n // Find tsconfig.json - using ts.sys.fileExists which has `this: void` requirement\n const configPath = ts.findConfigFile(fileDir, ts.sys.fileExists.bind(ts.sys), \"tsconfig.json\");\n\n let compilerOptions: ts.CompilerOptions;\n let fileNames: string[];\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile.bind(ts.sys));\n if (configFile.error) {\n throw new Error(\n `Error reading tsconfig.json: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, \"\\n\")}`\n );\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path.dirname(configPath)\n );\n\n if (parsed.errors.length > 0) {\n const errorMessages = parsed.errors\n .map((e) => ts.flattenDiagnosticMessageText(e.messageText, \"\\n\"))\n .join(\"\\n\");\n throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);\n }\n\n compilerOptions = parsed.options;\n // Include the target file in the program\n fileNames = parsed.fileNames.includes(absolutePath)\n ? parsed.fileNames\n : [...parsed.fileNames, absolutePath];\n } else {\n // Fallback to default options\n compilerOptions = {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.NodeNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n strict: true,\n skipLibCheck: true,\n declaration: true,\n };\n fileNames = [absolutePath];\n }\n\n const program = ts.createProgram(fileNames, compilerOptions);\n const sourceFile = program.getSourceFile(absolutePath);\n\n if (!sourceFile) {\n throw new Error(`Could not find source file: ${absolutePath}`);\n }\n\n return {\n program,\n checker: program.getTypeChecker(),\n sourceFile,\n };\n}\n\n/**\n * Generic AST node finder by name. Walks the source file tree and returns\n * the first node matching the predicate with the given name.\n */\nfunction findNodeByName<T extends ts.Node>(\n sourceFile: ts.SourceFile,\n name: string,\n predicate: (node: ts.Node) => node is T,\n getName: (node: T) => string | undefined\n): T | null {\n let result: T | null = null;\n\n function visit(node: ts.Node): void {\n if (result) return;\n\n if (predicate(node) && getName(node) === name) {\n result = node;\n return;\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return result;\n}\n\n/**\n * Finds a class declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param className - Name of the class to find\n * @returns The class declaration node, or null if not found\n */\nexport function findClassByName(\n sourceFile: ts.SourceFile,\n className: string\n): ts.ClassDeclaration | null {\n return findNodeByName(sourceFile, className, ts.isClassDeclaration, (n) => n.name?.text);\n}\n\n/**\n * Finds an interface declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param interfaceName - Name of the interface to find\n * @returns The interface declaration node, or null if not found\n */\nexport function findInterfaceByName(\n sourceFile: ts.SourceFile,\n interfaceName: string\n): ts.InterfaceDeclaration | null {\n return findNodeByName(sourceFile, interfaceName, ts.isInterfaceDeclaration, (n) => n.name.text);\n}\n\n/**\n * Finds a type alias declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param aliasName - Name of the type alias to find\n * @returns The type alias declaration node, or null if not found\n */\nexport function findTypeAliasByName(\n sourceFile: ts.SourceFile,\n aliasName: string\n): ts.TypeAliasDeclaration | null {\n return findNodeByName(sourceFile, aliasName, ts.isTypeAliasDeclaration, (n) => n.name.text);\n}\n","/**\n * Class analyzer for extracting fields, types, and JSDoc constraints.\n *\n * Produces `IRClassAnalysis` containing `FieldNode[]` and `typeRegistry`\n * directly from class, interface, or type alias declarations.\n * All downstream generation routes through the canonical FormIR.\n */\n\nimport * as ts from \"typescript\";\nimport type {\n FieldNode,\n TypeNode,\n EnumTypeNode,\n EnumMember,\n ConstraintNode,\n AnnotationNode,\n Provenance,\n ObjectProperty,\n RecordTypeNode,\n TypeDefinition,\n JsonValue,\n} from \"@formspec/core\";\nimport {\n extractJSDocConstraintNodes,\n extractJSDocAnnotationNodes,\n extractDefaultValueAnnotation,\n} from \"./jsdoc-constraints.js\";\nimport { extractDisplayNameMetadata } from \"./tsdoc-parser.js\";\n\n// =============================================================================\n// TYPE GUARDS\n// =============================================================================\n\n/**\n * Type guard for ts.ObjectType — checks that the TypeFlags.Object bit is set.\n */\nfunction isObjectType(type: ts.Type): type is ts.ObjectType {\n return !!(type.flags & ts.TypeFlags.Object);\n}\n\n/**\n * Type guard for ts.TypeReference — checks ObjectFlags.Reference on top of ObjectType.\n * The internal `as` cast is isolated inside this guard and is required because\n * TypeScript's public API does not expose objectFlags on ts.Type directly.\n */\nfunction isTypeReference(type: ts.Type): type is ts.TypeReference {\n // as cast is isolated inside type guard\n return (\n !!(type.flags & ts.TypeFlags.Object) &&\n !!((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference)\n );\n}\n\n/**\n * Placeholder used while a named object type is still being expanded.\n *\n * The object identity matters: final empty-object schemas are distinct\n * instances, so we can tell an in-progress registry entry from a real one.\n */\nconst RESOLVING_TYPE_PLACEHOLDER: TypeNode = {\n kind: \"object\",\n properties: [],\n additionalProperties: true,\n};\n\n// =============================================================================\n// IR OUTPUT TYPES\n// =============================================================================\n\n/**\n * Layout metadata extracted from `@Group` and `@ShowWhen` TSDoc tags.\n * One entry per field, in the same order as `fields`.\n */\nexport interface FieldLayoutMetadata {\n /** Group label from `@Group(\"label\")`, or undefined if ungrouped. */\n readonly groupLabel?: string;\n /** ShowWhen condition from `@ShowWhen({ field, value })`, or undefined if always visible. */\n readonly showWhen?: { readonly field: string; readonly value: JsonValue };\n}\n\n/**\n * Result of analyzing a class/interface/type alias into canonical IR.\n */\nexport interface IRClassAnalysis {\n /** Type name */\n readonly name: string;\n /** Analyzed fields as canonical IR FieldNodes */\n readonly fields: readonly FieldNode[];\n /** Layout metadata per field (same order/length as `fields`). */\n readonly fieldLayouts: readonly FieldLayoutMetadata[];\n /** Named type definitions referenced by fields */\n readonly typeRegistry: Record<string, TypeDefinition>;\n /** Root-level metadata for the analyzed declaration. */\n readonly annotations?: readonly AnnotationNode[];\n /** Instance methods (retained for downstream method-schema generation) */\n readonly instanceMethods: readonly MethodInfo[];\n /** Static methods */\n readonly staticMethods: readonly MethodInfo[];\n}\n\n/**\n * Result of analyzing a type alias into IR — either success or error.\n */\nexport type AnalyzeTypeAliasToIRResult =\n | { readonly ok: true; readonly analysis: IRClassAnalysis }\n | { readonly ok: false; readonly error: string };\n\n// =============================================================================\n// IR ANALYSIS — PUBLIC API\n// =============================================================================\n\n/**\n * Analyzes a class declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeClassToIR(\n classDecl: ts.ClassDeclaration,\n checker: ts.TypeChecker,\n file = \"\"\n): IRClassAnalysis {\n const name = classDecl.name?.text ?? \"AnonymousClass\";\n const fields: FieldNode[] = [];\n const fieldLayouts: FieldLayoutMetadata[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(classDecl, file);\n const visiting = new Set<ts.Type>();\n const instanceMethods: MethodInfo[] = [];\n const staticMethods: MethodInfo[] = [];\n\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member)) {\n const fieldNode = analyzeFieldToIR(member, checker, file, typeRegistry, visiting);\n if (fieldNode) {\n fields.push(fieldNode);\n fieldLayouts.push({});\n }\n } else if (ts.isMethodDeclaration(member)) {\n const methodInfo = analyzeMethod(member, checker);\n if (methodInfo) {\n const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);\n if (isStatic) {\n staticMethods.push(methodInfo);\n } else {\n instanceMethods.push(methodInfo);\n }\n }\n }\n }\n\n return {\n name,\n fields,\n fieldLayouts,\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods,\n staticMethods,\n };\n}\n\n/**\n * Analyzes an interface declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeInterfaceToIR(\n interfaceDecl: ts.InterfaceDeclaration,\n checker: ts.TypeChecker,\n file = \"\"\n): IRClassAnalysis {\n const name = interfaceDecl.name.text;\n const fields: FieldNode[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(interfaceDecl, file);\n const visiting = new Set<ts.Type>();\n\n for (const member of interfaceDecl.members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(member, checker, file, typeRegistry, visiting);\n if (fieldNode) {\n fields.push(fieldNode);\n }\n }\n }\n\n const fieldLayouts: FieldLayoutMetadata[] = fields.map(() => ({}));\n return {\n name,\n fields,\n fieldLayouts,\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods: [],\n staticMethods: [],\n };\n}\n\n/**\n * Analyzes a type alias declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeTypeAliasToIR(\n typeAlias: ts.TypeAliasDeclaration,\n checker: ts.TypeChecker,\n file = \"\"\n): AnalyzeTypeAliasToIRResult {\n if (!ts.isTypeLiteralNode(typeAlias.type)) {\n const sourceFile = typeAlias.getSourceFile();\n const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- enum reverse mapping can be undefined for compiler-internal kinds\n const kindDesc = ts.SyntaxKind[typeAlias.type.kind] ?? \"unknown\";\n return {\n ok: false,\n error: `Type alias \"${typeAlias.name.text}\" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`,\n };\n }\n\n const name = typeAlias.name.text;\n const fields: FieldNode[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(typeAlias, file);\n const visiting = new Set<ts.Type>();\n\n for (const member of typeAlias.type.members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(member, checker, file, typeRegistry, visiting);\n if (fieldNode) {\n fields.push(fieldNode);\n }\n }\n }\n\n return {\n ok: true,\n analysis: {\n name,\n fields,\n fieldLayouts: fields.map(() => ({})),\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods: [],\n staticMethods: [],\n },\n };\n}\n\n// =============================================================================\n// IR FIELD ANALYSIS — PRIVATE\n// =============================================================================\n\n/**\n * Analyzes a class property declaration into a canonical IR FieldNode.\n */\nfunction analyzeFieldToIR(\n prop: ts.PropertyDeclaration,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): FieldNode | null {\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const tsType = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n const provenance = provenanceForNode(prop, file);\n\n // Resolve ts.Type → TypeNode\n let type = resolveTypeNode(tsType, checker, file, typeRegistry, visiting, prop);\n\n // Collect constraints\n const constraints: ConstraintNode[] = [];\n\n // Inherit constraints from type alias declarations (lower precedence)\n if (prop.type) {\n constraints.push(...extractTypeAliasConstraintNodes(prop.type, checker, file));\n }\n\n // Extract JSDoc constraints\n constraints.push(...extractJSDocConstraintNodes(prop, file));\n\n // Collect annotations\n let annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@displayName, @description, @deprecated)\n annotations.push(...extractJSDocAnnotationNodes(prop, file));\n\n // Default value annotation\n const defaultAnnotation = extractDefaultValueAnnotation(prop.initializer, file);\n if (defaultAnnotation && !annotations.some((a) => a.annotationKind === \"defaultValue\")) {\n annotations.push(defaultAnnotation);\n }\n\n ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));\n\n return {\n kind: \"field\",\n name,\n type,\n required: !optional,\n constraints,\n annotations,\n provenance,\n };\n}\n\n/**\n * Analyzes an interface/type-alias property signature into a canonical IR FieldNode.\n */\nfunction analyzeInterfacePropertyToIR(\n prop: ts.PropertySignature,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): FieldNode | null {\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const tsType = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n const provenance = provenanceForNode(prop, file);\n\n // Resolve ts.Type → TypeNode\n let type = resolveTypeNode(tsType, checker, file, typeRegistry, visiting, prop);\n\n // Collect constraints\n const constraints: ConstraintNode[] = [];\n\n // Inherit constraints from type alias declarations\n if (prop.type) {\n constraints.push(...extractTypeAliasConstraintNodes(prop.type, checker, file));\n }\n\n // JSDoc constraints\n constraints.push(...extractJSDocConstraintNodes(prop, file));\n\n // Collect annotations\n let annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@displayName, @description, @deprecated)\n annotations.push(...extractJSDocAnnotationNodes(prop, file));\n\n ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));\n\n return {\n kind: \"field\",\n name,\n type,\n required: !optional,\n constraints,\n annotations,\n provenance,\n };\n}\n\n/**\n * Rewrites enum-member display-name annotations into EnumMember.displayName\n * values and strips those annotations from the field-level annotation list.\n *\n * The TSDoc surface uses `@displayName :value Label` for enum member labels.\n * Plain `@displayName Label` annotations remain as field-level titles.\n */\nfunction applyEnumMemberDisplayNames(\n type: TypeNode,\n annotations: readonly AnnotationNode[]\n): { type: TypeNode; annotations: AnnotationNode[] } {\n if (\n !annotations.some(\n (annotation) =>\n annotation.annotationKind === \"displayName\" && annotation.value.trim().startsWith(\":\")\n )\n ) {\n return { type, annotations: [...annotations] };\n }\n\n const consumed = new Set<AnnotationNode>();\n const nextType = rewriteEnumDisplayNames(type, annotations, consumed);\n\n if (consumed.size === 0) {\n return { type, annotations: [...annotations] };\n }\n\n return {\n type: nextType,\n annotations: annotations.filter((annotation) => !consumed.has(annotation)),\n };\n}\n\nfunction rewriteEnumDisplayNames(\n type: TypeNode,\n annotations: readonly AnnotationNode[],\n consumed: Set<AnnotationNode>\n): TypeNode {\n switch (type.kind) {\n case \"enum\":\n return applyEnumMemberDisplayNamesToEnum(type, annotations, consumed);\n\n case \"union\": {\n return {\n ...type,\n members: type.members.map((member) =>\n rewriteEnumDisplayNames(member, annotations, consumed)\n ),\n };\n }\n\n default:\n return type;\n }\n}\n\nfunction applyEnumMemberDisplayNamesToEnum(\n type: EnumTypeNode,\n annotations: readonly AnnotationNode[],\n consumed: Set<AnnotationNode>\n): EnumTypeNode {\n const displayNames = new Map<string, string>();\n\n for (const annotation of annotations) {\n if (annotation.annotationKind !== \"displayName\") continue;\n\n const parsed = parseEnumMemberDisplayName(annotation.value);\n if (!parsed) continue;\n\n // Once parsed as a member-target display name, never let it fall back to a\n // field-level title, even if the target value does not exist.\n consumed.add(annotation);\n\n const member = type.members.find((m) => String(m.value) === parsed.value);\n if (!member) continue;\n\n displayNames.set(String(member.value), parsed.label);\n }\n\n if (displayNames.size === 0) {\n return type;\n }\n\n return {\n ...type,\n members: type.members.map((member) => {\n const displayName = displayNames.get(String(member.value));\n return displayName !== undefined ? { ...member, displayName } : member;\n }),\n };\n}\n\nfunction parseEnumMemberDisplayName(value: string): { value: string; label: string } | null {\n const trimmed = value.trim();\n const match = /^:([^\\s]+)\\s+([\\s\\S]+)$/.exec(trimmed);\n if (!match?.[1] || !match[2]) return null;\n\n const label = match[2].trim();\n if (label === \"\") return null;\n\n return { value: match[1], label };\n}\n\n// =============================================================================\n// TYPE RESOLUTION — ts.Type → TypeNode\n// =============================================================================\n\n/**\n * Resolves a TypeScript type to a canonical IR TypeNode.\n */\nexport function resolveTypeNode(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n sourceNode?: ts.Node\n): TypeNode {\n // --- Primitives ---\n if (type.flags & ts.TypeFlags.String) {\n return { kind: \"primitive\", primitiveKind: \"string\" };\n }\n if (type.flags & ts.TypeFlags.Number) {\n return { kind: \"primitive\", primitiveKind: \"number\" };\n }\n if (type.flags & ts.TypeFlags.Boolean) {\n return { kind: \"primitive\", primitiveKind: \"boolean\" };\n }\n if (type.flags & ts.TypeFlags.Null) {\n return { kind: \"primitive\", primitiveKind: \"null\" };\n }\n if (type.flags & ts.TypeFlags.Undefined) {\n // Undefined maps to null for nullable semantics in JSON Schema\n return { kind: \"primitive\", primitiveKind: \"null\" };\n }\n\n // --- String literal ---\n if (type.isStringLiteral()) {\n return {\n kind: \"enum\",\n members: [{ value: type.value }],\n };\n }\n\n // --- Number literal ---\n if (type.isNumberLiteral()) {\n return {\n kind: \"enum\",\n members: [{ value: type.value }],\n };\n }\n\n // --- Union types ---\n if (type.isUnion()) {\n return resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode);\n }\n\n // --- Array types ---\n if (checker.isArrayType(type)) {\n return resolveArrayType(type, checker, file, typeRegistry, visiting);\n }\n\n // --- Object types ---\n if (isObjectType(type)) {\n return resolveObjectType(type, checker, file, typeRegistry, visiting);\n }\n\n // --- Fallback: treat unknown/any/void as string ---\n return { kind: \"primitive\", primitiveKind: \"string\" };\n}\n\nfunction resolveUnionType(\n type: ts.UnionType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n sourceNode?: ts.Node\n): TypeNode {\n const typeName = getNamedTypeName(type);\n const namedDecl = getNamedTypeDeclaration(type);\n\n if (typeName && typeName in typeRegistry) {\n return { kind: \"reference\", name: typeName, typeArguments: [] };\n }\n\n const allTypes = type.types;\n const nonNullTypes = allTypes.filter(\n (t) => !(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))\n );\n const hasNull = allTypes.some((t) => t.flags & ts.TypeFlags.Null);\n const memberDisplayNames = new Map<string, string>();\n if (namedDecl) {\n for (const [value, label] of extractDisplayNameMetadata(namedDecl).memberDisplayNames) {\n memberDisplayNames.set(value, label);\n }\n }\n if (sourceNode) {\n for (const [value, label] of extractDisplayNameMetadata(sourceNode).memberDisplayNames) {\n memberDisplayNames.set(value, label);\n }\n }\n\n const registerNamed = (result: TypeNode): TypeNode => {\n if (!typeName) {\n return result;\n }\n const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file) : undefined;\n typeRegistry[typeName] = {\n name: typeName,\n type: result,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl ?? sourceNode, file),\n };\n return { kind: \"reference\", name: typeName, typeArguments: [] };\n };\n\n const applyMemberLabels = (members: readonly (string | number)[]): EnumMember[] =>\n members.map((value) => {\n const displayName = memberDisplayNames.get(String(value));\n return displayName !== undefined ? { value, displayName } : { value };\n });\n\n const isBooleanUnion =\n nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts.TypeFlags.BooleanLiteral);\n\n if (isBooleanUnion) {\n const boolNode: TypeNode = { kind: \"primitive\", primitiveKind: \"boolean\" };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [boolNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : boolNode;\n return registerNamed(result);\n }\n\n const allStringLiterals = nonNullTypes.every((t) => t.isStringLiteral());\n if (allStringLiterals && nonNullTypes.length > 0) {\n const stringTypes = nonNullTypes.filter((t): t is ts.StringLiteralType => t.isStringLiteral());\n const enumNode: TypeNode = {\n kind: \"enum\",\n members: applyMemberLabels(stringTypes.map((t) => t.value)),\n };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : enumNode;\n return registerNamed(result);\n }\n\n const allNumberLiterals = nonNullTypes.every((t) => t.isNumberLiteral());\n if (allNumberLiterals && nonNullTypes.length > 0) {\n const numberTypes = nonNullTypes.filter((t): t is ts.NumberLiteralType => t.isNumberLiteral());\n const enumNode: TypeNode = {\n kind: \"enum\",\n members: applyMemberLabels(numberTypes.map((t) => t.value)),\n };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : enumNode;\n return registerNamed(result);\n }\n\n if (nonNullTypes.length === 1 && nonNullTypes[0]) {\n const inner = resolveTypeNode(\n nonNullTypes[0],\n checker,\n file,\n typeRegistry,\n visiting,\n sourceNode\n );\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [inner, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : inner;\n return registerNamed(result);\n }\n\n const members = nonNullTypes.map((t) =>\n resolveTypeNode(t, checker, file, typeRegistry, visiting, sourceNode)\n );\n if (hasNull) {\n members.push({ kind: \"primitive\", primitiveKind: \"null\" });\n }\n return registerNamed({ kind: \"union\", members });\n}\n\nfunction resolveArrayType(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): TypeNode {\n const typeArgs = isTypeReference(type) ? type.typeArguments : undefined;\n const elementType = typeArgs?.[0];\n\n const items = elementType\n ? resolveTypeNode(elementType, checker, file, typeRegistry, visiting)\n : ({ kind: \"primitive\", primitiveKind: \"string\" } satisfies TypeNode);\n\n return { kind: \"array\", items };\n}\n\n/**\n * Returns a `RecordTypeNode` if `type` is a pure dictionary type (string index\n * signature with no named properties), or `null` otherwise.\n *\n * This handles both `Record<string, T>` (a mapped/aliased type) and inline\n * `{ [k: string]: T }` index signature types per spec 003 §2.5.\n */\nfunction tryResolveRecordType(\n type: ts.ObjectType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): RecordTypeNode | null {\n // Only types with no named properties qualify as pure dictionaries.\n if (type.getProperties().length > 0) {\n return null;\n }\n const indexInfo = checker.getIndexInfoOfType(type, ts.IndexKind.String);\n if (!indexInfo) {\n return null;\n }\n\n const valueType = resolveTypeNode(indexInfo.type, checker, file, typeRegistry, visiting);\n return { kind: \"record\", valueType };\n}\n\nfunction typeNodeContainsReference(type: TypeNode, targetName: string): boolean {\n switch (type.kind) {\n case \"reference\":\n return type.name === targetName;\n case \"array\":\n return typeNodeContainsReference(type.items, targetName);\n case \"record\":\n return typeNodeContainsReference(type.valueType, targetName);\n case \"union\":\n return type.members.some((member) => typeNodeContainsReference(member, targetName));\n case \"object\":\n return type.properties.some((property) =>\n typeNodeContainsReference(property.type, targetName)\n );\n case \"primitive\":\n case \"enum\":\n case \"dynamic\":\n case \"custom\":\n return false;\n default: {\n const _exhaustive: never = type;\n return _exhaustive;\n }\n }\n}\n\nfunction resolveObjectType(\n type: ts.ObjectType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): TypeNode {\n const typeName = getNamedTypeName(type);\n const namedTypeName = typeName ?? undefined;\n const namedDecl = getNamedTypeDeclaration(type);\n const shouldRegisterNamedType =\n namedTypeName !== undefined &&\n !(namedTypeName === \"Record\" && namedDecl?.getSourceFile().fileName !== file);\n const clearNamedTypeRegistration = (): void => {\n if (namedTypeName === undefined || !shouldRegisterNamedType) {\n return;\n }\n Reflect.deleteProperty(typeRegistry, namedTypeName);\n };\n\n if (visiting.has(type)) {\n // Recursive object expansion is deferred through the named-type registry.\n // Anonymous cycles still collapse to a closed empty object sentinel.\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n return { kind: \"object\", properties: [], additionalProperties: false };\n }\n\n // Seed the registry with a placeholder before traversing children so any\n // recursive property reference can resolve to a stable `$ref`.\n if (namedTypeName !== undefined && shouldRegisterNamedType && !typeRegistry[namedTypeName]) {\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: RESOLVING_TYPE_PLACEHOLDER,\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n }\n\n visiting.add(type);\n\n // Detect previously resolved named types before walking the object body.\n if (\n namedTypeName !== undefined &&\n shouldRegisterNamedType &&\n typeRegistry[namedTypeName]?.type !== undefined\n ) {\n if (typeRegistry[namedTypeName].type !== RESOLVING_TYPE_PLACEHOLDER) {\n visiting.delete(type);\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n }\n\n // Detect pure dictionary types (Record<string, T> or { [k: string]: T })\n // after the recursion guard/placeholder setup so recursive records can point\n // back at the named type instead of collapsing to an empty object.\n const recordNode = tryResolveRecordType(type, checker, file, typeRegistry, visiting);\n if (recordNode) {\n visiting.delete(type);\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType, namedTypeName);\n if (!isRecursiveRecord) {\n clearNamedTypeRegistration();\n return recordNode;\n }\n const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file) : undefined;\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: recordNode,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n return recordNode;\n }\n\n const properties: ObjectProperty[] = [];\n\n // Get FieldInfo-level analysis from named type declarations for constraint propagation\n const fieldInfoMap = getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visiting);\n\n for (const prop of type.getProperties()) {\n const declaration = prop.valueDeclaration ?? prop.declarations?.[0];\n if (!declaration) continue;\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);\n const optional = !!(prop.flags & ts.SymbolFlags.Optional);\n const propTypeNode = resolveTypeNode(\n propType,\n checker,\n file,\n typeRegistry,\n visiting,\n declaration\n );\n\n // Get constraints and annotations from the declaration if available\n const fieldNodeInfo = fieldInfoMap?.get(prop.name);\n\n properties.push({\n name: prop.name,\n type: propTypeNode,\n optional,\n constraints: fieldNodeInfo?.constraints ?? [],\n annotations: fieldNodeInfo?.annotations ?? [],\n provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file),\n });\n }\n\n visiting.delete(type);\n\n const objectNode: TypeNode = {\n kind: \"object\",\n properties,\n additionalProperties: true,\n };\n\n // Register named types\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file) : undefined;\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: objectNode,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n\n return objectNode;\n}\n\n// =============================================================================\n// NAMED TYPE FIELD INFO MAP — for nested constraint propagation\n// =============================================================================\n\ninterface FieldNodeInfo {\n readonly constraints: readonly ConstraintNode[];\n readonly annotations: readonly AnnotationNode[];\n readonly provenance: Provenance;\n}\n\n/**\n * Builds a map from property name to constraint/annotation info for named types.\n * This enables propagating TSDoc constraints from nested type declarations.\n */\nfunction getNamedTypeFieldNodeInfoMap(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): Map<string, FieldNodeInfo> | null {\n const symbols = [type.getSymbol(), type.aliasSymbol].filter(\n (s): s is ts.Symbol => s?.declarations != null && s.declarations.length > 0\n );\n\n for (const symbol of symbols) {\n const declarations = symbol.declarations;\n if (!declarations) continue;\n\n // Try class declaration\n const classDecl = declarations.find(ts.isClassDeclaration);\n if (classDecl) {\n const map = new Map<string, FieldNodeInfo>();\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name)) {\n const fieldNode = analyzeFieldToIR(member, checker, file, typeRegistry, visiting);\n if (fieldNode) {\n map.set(fieldNode.name, {\n constraints: [...fieldNode.constraints],\n annotations: [...fieldNode.annotations],\n provenance: fieldNode.provenance,\n });\n }\n }\n }\n return map;\n }\n\n // Try interface declaration\n const interfaceDecl = declarations.find(ts.isInterfaceDeclaration);\n if (interfaceDecl) {\n return buildFieldNodeInfoMap(interfaceDecl.members, checker, file, typeRegistry, visiting);\n }\n\n // Try type alias with type literal body\n const typeAliasDecl = declarations.find(ts.isTypeAliasDeclaration);\n if (typeAliasDecl && ts.isTypeLiteralNode(typeAliasDecl.type)) {\n return buildFieldNodeInfoMap(\n typeAliasDecl.type.members,\n checker,\n file,\n typeRegistry,\n visiting\n );\n }\n }\n\n return null;\n}\n\nfunction buildFieldNodeInfoMap(\n members: ts.NodeArray<ts.TypeElement>,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>\n): Map<string, FieldNodeInfo> {\n const map = new Map<string, FieldNodeInfo>();\n for (const member of members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(member, checker, file, typeRegistry, visiting);\n if (fieldNode) {\n map.set(fieldNode.name, {\n constraints: [...fieldNode.constraints],\n annotations: [...fieldNode.annotations],\n provenance: fieldNode.provenance,\n });\n }\n }\n }\n return map;\n}\n\n// =============================================================================\n// TYPE ALIAS CONSTRAINT PROPAGATION\n// =============================================================================\n\n/** Maximum depth for transitive type alias constraint propagation. */\nconst MAX_ALIAS_CHAIN_DEPTH = 8;\n\n/**\n * Given a type node referencing a type alias, extracts IR ConstraintNodes\n * from the alias declaration's JSDoc tags.\n *\n * Follows alias chains transitively: if `type Percentage = Integer` and\n * `type Integer = number`, constraints from both `Percentage` and `Integer`\n * are collected. Constraints from closer aliases appear first in the result\n * (higher precedence). Recursion is capped at {@link MAX_ALIAS_CHAIN_DEPTH}\n * levels; exceeding the limit throws to surface pathological alias chains.\n */\nfunction extractTypeAliasConstraintNodes(\n typeNode: ts.TypeNode,\n checker: ts.TypeChecker,\n file: string,\n depth = 0\n): ConstraintNode[] {\n if (!ts.isTypeReferenceNode(typeNode)) return [];\n\n if (depth >= MAX_ALIAS_CHAIN_DEPTH) {\n const aliasName = typeNode.typeName.getText();\n throw new Error(\n `Type alias chain exceeds maximum depth of ${String(MAX_ALIAS_CHAIN_DEPTH)} ` +\n `at alias \"${aliasName}\" in ${file}. ` +\n `Simplify the alias chain or check for circular references.`\n );\n }\n\n const symbol = checker.getSymbolAtLocation(typeNode.typeName);\n if (!symbol?.declarations) return [];\n\n const aliasDecl = symbol.declarations.find(ts.isTypeAliasDeclaration);\n if (!aliasDecl) return [];\n\n // Don't extract from object type aliases\n if (ts.isTypeLiteralNode(aliasDecl.type)) return [];\n\n const constraints = extractJSDocConstraintNodes(aliasDecl, file);\n\n // Transitively follow alias chains (e.g., Percentage → Integer → number)\n // Constraints from parent aliases are appended after the immediate alias's\n // constraints, giving the immediate alias higher precedence.\n constraints.push(...extractTypeAliasConstraintNodes(aliasDecl.type, checker, file, depth + 1));\n\n return constraints;\n}\n\n// =============================================================================\n// PROVENANCE HELPERS\n// =============================================================================\n\nfunction provenanceForNode(node: ts.Node, file: string): Provenance {\n const sourceFile = node.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n };\n}\n\nfunction provenanceForFile(file: string): Provenance {\n return { surface: \"tsdoc\", file, line: 0, column: 0 };\n}\n\nfunction provenanceForDeclaration(node: ts.Node | undefined, file: string): Provenance {\n if (!node) {\n return provenanceForFile(file);\n }\n return provenanceForNode(node, file);\n}\n\n// =============================================================================\n// NAMED TYPE HELPERS\n// =============================================================================\n\n/**\n * Extracts a stable type name from a ts.Type when it originates from\n * a named declaration (class, interface, or type alias).\n */\nfunction getNamedTypeName(type: ts.Type): string | null {\n const symbol = type.getSymbol();\n if (symbol?.declarations) {\n const decl = symbol.declarations[0];\n if (\n decl &&\n (ts.isClassDeclaration(decl) ||\n ts.isInterfaceDeclaration(decl) ||\n ts.isTypeAliasDeclaration(decl))\n ) {\n const name = ts.isClassDeclaration(decl) ? decl.name?.text : decl.name.text;\n if (name) return name;\n }\n }\n\n const aliasSymbol = type.aliasSymbol;\n if (aliasSymbol?.declarations) {\n const aliasDecl = aliasSymbol.declarations.find(ts.isTypeAliasDeclaration);\n if (aliasDecl) {\n return aliasDecl.name.text;\n }\n }\n\n return null;\n}\n\n/**\n * Returns the declaration that defines a named type, if available.\n */\nfunction getNamedTypeDeclaration(type: ts.Type): ts.Declaration | undefined {\n const symbol = type.getSymbol();\n if (symbol?.declarations) {\n const decl = symbol.declarations[0];\n if (\n decl &&\n (ts.isClassDeclaration(decl) ||\n ts.isInterfaceDeclaration(decl) ||\n ts.isTypeAliasDeclaration(decl))\n ) {\n return decl;\n }\n }\n\n const aliasSymbol = type.aliasSymbol;\n if (aliasSymbol?.declarations) {\n return aliasSymbol.declarations.find(ts.isTypeAliasDeclaration);\n }\n\n return undefined;\n}\n\n// =============================================================================\n// SHARED OUTPUT TYPES\n// =============================================================================\n\n/**\n * Analyzed method information.\n */\nexport interface MethodInfo {\n /** Method name */\n name: string;\n /** Method parameters */\n parameters: ParameterInfo[];\n /** Return type node */\n returnTypeNode: ts.TypeNode | undefined;\n /** Resolved return type */\n returnType: ts.Type;\n}\n\n/**\n * Analyzed parameter information.\n */\nexport interface ParameterInfo {\n /** Parameter name */\n name: string;\n /** TypeScript type node */\n typeNode: ts.TypeNode | undefined;\n /** Resolved type */\n type: ts.Type;\n /** If this is InferSchema<typeof X>, the export name X */\n formSpecExportName: string | null;\n /** Whether the parameter is optional (has ? or default value) */\n optional: boolean;\n}\n\n// =============================================================================\n// SHARED HELPERS\n// =============================================================================\n\n/**\n * Analyzes a method declaration to extract method info.\n * Shared between IR and legacy paths.\n */\nfunction analyzeMethod(method: ts.MethodDeclaration, checker: ts.TypeChecker): MethodInfo | null {\n if (!ts.isIdentifier(method.name)) {\n return null;\n }\n\n const name = method.name.text;\n const parameters: ParameterInfo[] = [];\n\n for (const param of method.parameters) {\n if (ts.isIdentifier(param.name)) {\n const paramInfo = analyzeParameter(param, checker);\n parameters.push(paramInfo);\n }\n }\n\n const returnTypeNode = method.type;\n const signature = checker.getSignatureFromDeclaration(method);\n const returnType = signature\n ? checker.getReturnTypeOfSignature(signature)\n : checker.getTypeAtLocation(method);\n\n return { name, parameters, returnTypeNode, returnType };\n}\n\nfunction analyzeParameter(param: ts.ParameterDeclaration, checker: ts.TypeChecker): ParameterInfo {\n const name = ts.isIdentifier(param.name) ? param.name.text : \"param\";\n const typeNode = param.type;\n const type = checker.getTypeAtLocation(param);\n const formSpecExportName = detectFormSpecReference(typeNode);\n const optional = param.questionToken !== undefined || param.initializer !== undefined;\n\n return { name, typeNode, type, formSpecExportName, optional };\n}\n\nfunction detectFormSpecReference(typeNode: ts.TypeNode | undefined): string | null {\n if (!typeNode) return null;\n\n if (!ts.isTypeReferenceNode(typeNode)) return null;\n\n const typeName = ts.isIdentifier(typeNode.typeName)\n ? typeNode.typeName.text\n : ts.isQualifiedName(typeNode.typeName)\n ? typeNode.typeName.right.text\n : null;\n\n if (typeName !== \"InferSchema\" && typeName !== \"InferFormSchema\") return null;\n\n const typeArg = typeNode.typeArguments?.[0];\n if (!typeArg || !ts.isTypeQueryNode(typeArg)) return null;\n\n if (ts.isIdentifier(typeArg.exprName)) {\n return typeArg.exprName.text;\n }\n\n if (ts.isQualifiedName(typeArg.exprName)) {\n return typeArg.exprName.right.text;\n }\n\n return null;\n}\n","/**\n * JSDoc constraint and annotation extractor.\n *\n * Extracts constraints and annotation tags from JSDoc comments on\n * class/interface fields and returns canonical IR nodes directly:\n * - {@link ConstraintNode} for set-influencing tags (@minimum, @pattern, etc.)\n * - {@link AnnotationNode} for value-influencing tags (@displayName, etc.)\n *\n * The IR extraction path uses the official `@microsoft/tsdoc` parser for\n * all canonical tags.\n *\n * Supported constraints correspond to the built-in FormSpec constraint tags\n * (e.g., `@minimum`, `@maximum`, `@pattern`).\n */\n\nimport * as ts from \"typescript\";\nimport type { ConstraintNode, AnnotationNode, JsonValue } from \"@formspec/core\";\nimport { parseTSDocTags, hasDeprecatedTagTSDoc } from \"./tsdoc-parser.js\";\n\n// =============================================================================\n// IR API — uses @microsoft/tsdoc for structured parsing\n// =============================================================================\n\n/**\n * Extracts constraints from JSDoc comments on a TypeScript AST node and returns\n * canonical {@link ConstraintNode} objects.\n *\n * Uses the official `@microsoft/tsdoc` parser for structured tag extraction.\n * Constraints are registered as custom block tags in the TSDoc configuration.\n *\n * @param node - The AST node to inspect for JSDoc tags\n * @param file - Absolute path to the source file for provenance\n * @returns Canonical constraint nodes for each valid constraint tag\n */\nexport function extractJSDocConstraintNodes(node: ts.Node, file = \"\"): ConstraintNode[] {\n const result = parseTSDocTags(node, file);\n return [...result.constraints];\n}\n\n/**\n * Extracts canonical annotation tags from a node and returns\n * {@link AnnotationNode} objects.\n *\n * @param node - The AST node to inspect for annotation tags\n * @param file - Absolute path to the source file for provenance\n * @returns Canonical annotation nodes\n */\nexport function extractJSDocAnnotationNodes(node: ts.Node, file = \"\"): AnnotationNode[] {\n const result = parseTSDocTags(node, file);\n return [...result.annotations];\n}\n\n/**\n * Checks if a node has a TSDoc `@deprecated` tag.\n *\n * Uses the TSDoc parser for structured detection.\n */\nexport function hasDeprecatedTag(node: ts.Node): boolean {\n return hasDeprecatedTagTSDoc(node);\n}\n\n/**\n * Extracts a default value from a property initializer and returns a\n * {@link DefaultValueAnnotationNode} if present.\n *\n * Only extracts literal values (strings, numbers, booleans, null).\n */\nexport function extractDefaultValueAnnotation(\n initializer: ts.Expression | undefined,\n file = \"\"\n): AnnotationNode | null {\n if (!initializer) return null;\n\n let value: JsonValue | undefined;\n\n if (ts.isStringLiteral(initializer)) {\n value = initializer.text;\n } else if (ts.isNumericLiteral(initializer)) {\n value = Number(initializer.text);\n } else if (initializer.kind === ts.SyntaxKind.TrueKeyword) {\n value = true;\n } else if (initializer.kind === ts.SyntaxKind.FalseKeyword) {\n value = false;\n } else if (initializer.kind === ts.SyntaxKind.NullKeyword) {\n value = null;\n } else if (ts.isPrefixUnaryExpression(initializer)) {\n if (\n initializer.operator === ts.SyntaxKind.MinusToken &&\n ts.isNumericLiteral(initializer.operand)\n ) {\n value = -Number(initializer.operand.text);\n }\n }\n\n if (value === undefined) return null;\n\n const sourceFile = initializer.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(initializer.getStart());\n\n return {\n kind: \"annotation\",\n annotationKind: \"defaultValue\",\n value,\n provenance: {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n },\n };\n}\n","/**\n * TSDoc-based structured tag parser.\n *\n * Bridges the TypeScript compiler AST with the official `@microsoft/tsdoc`\n * parser to extract constraint and annotation tags from JSDoc comments\n * on class/interface/type-alias properties.\n *\n * The parser recognises two categories of tags:\n *\n * 1. **Constraint tags** (all alphanumeric, TSDoc-compliant):\n * `@minimum`, `@maximum`, `@exclusiveMinimum`, `@exclusiveMaximum`,\n * `@multipleOf`, `@minLength`, `@maxLength`, `@minItems`, `@maxItems`,\n * `@uniqueItems`, `@pattern`, `@enumOptions`, `@const`\n * — Parsed via TSDocParser as custom block tags.\n * Both camelCase and PascalCase forms are accepted (e.g., `@Minimum`).\n *\n * 2. **Annotation tags** (`@displayName`, `@description`, `@format`, `@placeholder`):\n * These are parsed as structured custom block tags and mapped directly\n * onto annotation IR nodes.\n *\n * The `@deprecated` tag is a standard TSDoc block tag, parsed structurally.\n *\n * **Fallback strategy**: TSDoc treats `{` / `}` as inline tag delimiters and\n * `@` as a tag prefix, so content containing these characters (e.g. JSON\n * objects in `@EnumOptions`, regex patterns with `@` in `@Pattern`) gets\n * mangled by the TSDoc parser. For these tags, the raw text is extracted\n * via the TS compiler's `ts.getJSDocTags()` API which preserves content\n * verbatim.\n */\n\nimport * as ts from \"typescript\";\nimport {\n TSDocParser,\n TSDocConfiguration,\n TSDocTagDefinition,\n TSDocTagSyntaxKind,\n DocPlainText,\n DocSoftBreak,\n TextRange,\n type DocNode,\n type DocBlock,\n} from \"@microsoft/tsdoc\";\nimport {\n BUILTIN_CONSTRAINT_DEFINITIONS,\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n type ConstraintNode,\n type AnnotationNode,\n type Provenance,\n type NumericConstraintNode,\n type LengthConstraintNode,\n type PathTarget,\n type JsonValue,\n} from \"@formspec/core\";\nimport { tryParseJson } from \"./json-utils.js\";\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/**\n * Constraint tag name → constraint kind mapping for numeric constraints.\n * Keys are camelCase matching BUILTIN_CONSTRAINT_DEFINITIONS.\n */\nconst NUMERIC_CONSTRAINT_MAP: Record<string, NumericConstraintNode[\"constraintKind\"]> = {\n minimum: \"minimum\",\n maximum: \"maximum\",\n exclusiveMinimum: \"exclusiveMinimum\",\n exclusiveMaximum: \"exclusiveMaximum\",\n multipleOf: \"multipleOf\",\n};\n\n/**\n * Constraint tag name → constraint kind mapping for length constraints.\n * Keys are camelCase matching BUILTIN_CONSTRAINT_DEFINITIONS.\n */\nconst LENGTH_CONSTRAINT_MAP: Record<string, LengthConstraintNode[\"constraintKind\"]> = {\n minLength: \"minLength\",\n maxLength: \"maxLength\",\n minItems: \"minItems\",\n maxItems: \"maxItems\",\n};\n\n/**\n * Tags whose content may contain TSDoc-significant characters (`{}`, `@`)\n * and must be extracted via the TS compiler JSDoc API rather than the\n * TSDoc DocNode tree to avoid content mangling.\n *\n * - `@pattern`: regex patterns commonly contain `@` (e.g. email validation)\n * - `@enumOptions`: JSON arrays may contain object literals with `{}`\n * - `@defaultValue`: JSON defaults may contain objects, arrays, or quoted strings\n */\nconst TAGS_REQUIRING_RAW_TEXT = new Set([\"pattern\", \"enumOptions\", \"defaultValue\"]);\n\n/**\n * Creates a TSDocConfiguration with FormSpec custom block tag definitions\n * registered for all constraint tags.\n */\nfunction createFormSpecTSDocConfig(): TSDocConfiguration {\n const config = new TSDocConfiguration();\n\n // Register each constraint tag as a custom block tag (allowMultiple so\n // repeated tags don't produce warnings).\n for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS)) {\n config.addTagDefinition(\n new TSDocTagDefinition({\n tagName: \"@\" + tagName,\n syntaxKind: TSDocTagSyntaxKind.BlockTag,\n allowMultiple: true,\n })\n );\n }\n\n // Register annotation tags that participate in the canonical IR.\n for (const tagName of [\"displayName\", \"description\", \"format\", \"placeholder\"]) {\n config.addTagDefinition(\n new TSDocTagDefinition({\n tagName: \"@\" + tagName,\n syntaxKind: TSDocTagSyntaxKind.BlockTag,\n allowMultiple: true,\n })\n );\n }\n\n return config;\n}\n\n/**\n * Shared parser instance — thread-safe because TSDocParser is stateless;\n * all parse state lives in the returned ParserContext.\n */\nlet sharedParser: TSDocParser | undefined;\n\nfunction getParser(): TSDocParser {\n sharedParser ??= new TSDocParser(createFormSpecTSDocConfig());\n return sharedParser;\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Result of parsing a single JSDoc comment attached to a TS AST node.\n */\nexport interface TSDocParseResult {\n /** Constraint IR nodes extracted from custom block tags. */\n readonly constraints: readonly ConstraintNode[];\n /** Annotation IR nodes extracted from canonical TSDoc block tags. */\n readonly annotations: readonly AnnotationNode[];\n}\n\n/**\n * Display-name metadata extracted from a node's JSDoc tags.\n *\n * The root display name is returned separately from member-target labels so\n * callers can apply the former to the enclosing type/form and the latter to\n * enum members.\n */\nexport interface DisplayNameMetadata {\n readonly displayName?: string;\n readonly memberDisplayNames: ReadonlyMap<string, string>;\n}\n\n/**\n * Parses the JSDoc comment attached to a TypeScript AST node using the\n * official TSDoc parser and returns canonical IR constraint and annotation\n * nodes.\n *\n * For constraint tags (`@minimum`, `@pattern`, `@enumOptions`, etc.),\n * the structured TSDoc parser is used. Canonical annotation tags\n * (`@displayName`, `@description`) are also parsed structurally.\n *\n * @param node - The TS AST node to inspect (PropertyDeclaration, PropertySignature, etc.)\n * @param file - Absolute source file path for provenance\n * @returns Parsed constraint and annotation nodes\n */\nexport function parseTSDocTags(node: ts.Node, file = \"\"): TSDocParseResult {\n const constraints: ConstraintNode[] = [];\n const annotations: AnnotationNode[] = [];\n let displayName: string | undefined;\n let description: string | undefined;\n let placeholder: string | undefined;\n let displayNameProvenance: Provenance | undefined;\n let descriptionProvenance: Provenance | undefined;\n let placeholderProvenance: Provenance | undefined;\n\n // ----- Phase 1: TSDoc structural parse for constraint tags -----\n const sourceFile = node.getSourceFile();\n const sourceText = sourceFile.getFullText();\n const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());\n\n if (commentRanges) {\n for (const range of commentRanges) {\n // Only parse /** ... */ comments (kind 3 = MultiLineCommentTrivia)\n if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {\n continue;\n }\n const commentText = sourceText.substring(range.pos, range.end);\n if (!commentText.startsWith(\"/**\")) {\n continue;\n }\n\n const parser = getParser();\n const parserContext = parser.parseRange(\n TextRange.fromStringRange(sourceText, range.pos, range.end)\n );\n const docComment = parserContext.docComment;\n\n // Extract constraint nodes from custom blocks.\n // Tags in TAGS_REQUIRING_RAW_TEXT are skipped here and handled via the\n // TS compiler API in Phase 1b below.\n for (const block of docComment.customBlocks) {\n const tagName = normalizeConstraintTagName(block.blockTag.tagName.substring(1)); // Remove leading @ and normalize to camelCase\n if (\n tagName === \"displayName\" ||\n tagName === \"description\" ||\n tagName === \"format\" ||\n tagName === \"placeholder\"\n ) {\n const text = extractBlockText(block).trim();\n if (text === \"\") continue;\n\n const provenance = provenanceForComment(range, sourceFile, file, tagName);\n if (tagName === \"displayName\") {\n if (!isMemberTargetDisplayName(text) && displayName === undefined) {\n displayName = text;\n displayNameProvenance = provenance;\n }\n } else if (tagName === \"format\") {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"format\",\n value: text,\n provenance,\n });\n } else {\n if (tagName === \"description\" && description === undefined) {\n description = text;\n descriptionProvenance = provenance;\n } else if (tagName === \"placeholder\" && placeholder === undefined) {\n placeholder = text;\n placeholderProvenance = provenance;\n }\n }\n continue;\n }\n\n if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;\n\n const text = extractBlockText(block).trim();\n const expectedType = isBuiltinConstraintName(tagName)\n ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName]\n : undefined;\n if (text === \"\" && expectedType !== \"boolean\") continue;\n\n const provenance = provenanceForComment(range, sourceFile, file, tagName);\n const constraintNode = parseConstraintValue(tagName, text, provenance);\n if (constraintNode) {\n constraints.push(constraintNode);\n }\n }\n\n // Extract @deprecated from the standard deprecated block\n if (docComment.deprecatedBlock !== undefined) {\n const message = extractBlockText(docComment.deprecatedBlock).trim();\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"deprecated\",\n ...(message !== \"\" && { message }),\n provenance: provenanceForComment(range, sourceFile, file, \"deprecated\"),\n });\n }\n\n if (description === undefined && docComment.remarksBlock !== undefined) {\n const remarks = extractBlockText(docComment.remarksBlock).trim();\n if (remarks !== \"\") {\n description = remarks;\n descriptionProvenance = provenanceForComment(range, sourceFile, file, \"remarks\");\n }\n }\n }\n }\n\n if (displayName !== undefined && displayNameProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"displayName\",\n value: displayName,\n provenance: displayNameProvenance,\n });\n }\n\n if (description !== undefined && descriptionProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"description\",\n value: description,\n provenance: descriptionProvenance,\n });\n }\n\n if (placeholder !== undefined && placeholderProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"placeholder\",\n value: placeholder,\n provenance: placeholderProvenance,\n });\n }\n\n // ----- Phase 1b: TS compiler API for tags with TSDoc-incompatible content -----\n // @pattern, @enumOptions, and @defaultValue content can contain `@`, `{}`,\n // or quoted JSON payloads that the TSDoc parser treats as structural markers.\n // We extract these via the TS compiler API which preserves content verbatim.\n const jsDocTagsAll = ts.getJSDocTags(node);\n for (const tag of jsDocTagsAll) {\n const tagName = normalizeConstraintTagName(tag.tagName.text);\n if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;\n\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText.trim() === \"\") continue;\n\n const text = commentText.trim();\n const provenance = provenanceForJSDocTag(tag, file);\n if (tagName === \"defaultValue\") {\n const defaultValueNode = parseDefaultValueValue(text, provenance);\n annotations.push(defaultValueNode);\n continue;\n }\n\n const constraintNode = parseConstraintValue(tagName, text, provenance);\n if (constraintNode) {\n constraints.push(constraintNode);\n }\n }\n\n return { constraints, annotations };\n}\n\n/**\n * Checks if a TS AST node has a `@deprecated` tag using the TSDoc parser.\n *\n * Falls back to the TS compiler API for nodes without doc comments.\n */\nexport function hasDeprecatedTagTSDoc(node: ts.Node): boolean {\n const sourceFile = node.getSourceFile();\n const sourceText = sourceFile.getFullText();\n const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());\n\n if (commentRanges) {\n for (const range of commentRanges) {\n if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) continue;\n const commentText = sourceText.substring(range.pos, range.end);\n if (!commentText.startsWith(\"/**\")) continue;\n\n const parser = getParser();\n const parserContext = parser.parseRange(\n TextRange.fromStringRange(sourceText, range.pos, range.end)\n );\n if (parserContext.docComment.deprecatedBlock !== undefined) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Extracts root and member-target display-name metadata from a node's JSDoc tags.\n *\n * Member-target display-name tags use the syntax `@displayName :member Label`.\n * The first non-target `@displayName` is returned as the root display name.\n */\nexport function extractDisplayNameMetadata(node: ts.Node): DisplayNameMetadata {\n let displayName: string | undefined;\n const memberDisplayNames = new Map<string, string>();\n\n for (const tag of ts.getJSDocTags(node)) {\n const tagName = normalizeConstraintTagName(tag.tagName.text);\n if (tagName !== \"displayName\") continue;\n\n const commentText = getTagCommentText(tag);\n if (commentText === undefined) continue;\n\n const text = commentText.trim();\n if (text === \"\") continue;\n\n const memberTarget = parseMemberTargetDisplayName(text);\n if (memberTarget) {\n memberDisplayNames.set(memberTarget.target, memberTarget.label);\n continue;\n }\n\n displayName ??= text;\n }\n\n return {\n ...(displayName !== undefined && { displayName }),\n memberDisplayNames,\n };\n}\n\n// =============================================================================\n// PUBLIC HELPERS — path target extraction\n// =============================================================================\n\n/**\n * Extracts a path-target prefix (`:fieldName`) from constraint tag text.\n * Returns the parsed PathTarget and remaining text, or null if no path target.\n *\n * @example\n * extractPathTarget(\":value 0\") // → { path: { segments: [\"value\"] }, remainingText: \"0\" }\n * extractPathTarget(\"42\") // → null\n */\nexport function extractPathTarget(\n text: string\n): { path: PathTarget; remainingText: string } | null {\n const trimmed = text.trimStart();\n const match = /^:([a-zA-Z_]\\w*)\\s+([\\s\\S]*)$/.exec(trimmed);\n if (!match?.[1] || !match[2]) return null;\n return {\n path: { segments: [match[1]] },\n remainingText: match[2],\n };\n}\n\n// =============================================================================\n// PRIVATE HELPERS — TSDoc text extraction\n// =============================================================================\n\n/**\n * Recursively extracts plain text content from a TSDoc DocNode tree.\n *\n * Walks child nodes and concatenates DocPlainText and DocSoftBreak content.\n */\nfunction extractBlockText(block: DocBlock): string {\n return extractPlainText(block.content);\n}\n\nfunction extractPlainText(node: DocNode): string {\n let result = \"\";\n if (node instanceof DocPlainText) {\n return node.text;\n }\n if (node instanceof DocSoftBreak) {\n return \" \";\n }\n if (typeof node.getChildNodes === \"function\") {\n for (const child of node.getChildNodes()) {\n result += extractPlainText(child);\n }\n }\n return result;\n}\n\n// =============================================================================\n// PRIVATE HELPERS — constraint value parsing\n// =============================================================================\n\n/**\n * Parses a raw text value extracted from a TSDoc block tag into an IR\n * ConstraintNode based on the tag name and BUILTIN_CONSTRAINT_DEFINITIONS.\n *\n * @param tagName - camelCase-normalized constraint tag name (callers normalize before calling)\n */\nfunction parseConstraintValue(\n tagName: string,\n text: string,\n provenance: Provenance\n): ConstraintNode | null {\n if (!isBuiltinConstraintName(tagName)) {\n return null;\n }\n\n // Extract optional path target (e.g., \":value 0\" → path=[\"value\"], text=\"0\")\n const pathResult = extractPathTarget(text);\n const effectiveText = pathResult ? pathResult.remainingText : text;\n const path = pathResult?.path;\n\n const expectedType = BUILTIN_CONSTRAINT_DEFINITIONS[tagName];\n\n if (expectedType === \"number\") {\n const value = Number(effectiveText);\n if (Number.isNaN(value)) {\n return null;\n }\n\n const numericKind = NUMERIC_CONSTRAINT_MAP[tagName];\n if (numericKind) {\n return {\n kind: \"constraint\",\n constraintKind: numericKind,\n value,\n ...(path && { path }),\n provenance,\n };\n }\n\n const lengthKind = LENGTH_CONSTRAINT_MAP[tagName];\n if (lengthKind) {\n return {\n kind: \"constraint\",\n constraintKind: lengthKind,\n value,\n ...(path && { path }),\n provenance,\n };\n }\n\n return null;\n }\n\n if (expectedType === \"boolean\") {\n const trimmed = effectiveText.trim();\n if (trimmed !== \"\" && trimmed !== \"true\") {\n return null;\n }\n\n if (tagName === \"uniqueItems\") {\n return {\n kind: \"constraint\",\n constraintKind: \"uniqueItems\",\n value: true,\n ...(path && { path }),\n provenance,\n };\n }\n\n return null;\n }\n\n if (expectedType === \"json\") {\n if (tagName === \"const\") {\n const trimmedText = effectiveText.trim();\n if (trimmedText === \"\") return null;\n\n try {\n const parsed = JSON.parse(trimmedText) as JsonValue;\n return {\n kind: \"constraint\",\n constraintKind: \"const\",\n value: parsed,\n ...(path && { path }),\n provenance,\n };\n } catch {\n // Bare strings like `@const USD` are accepted as a shorthand for\n // string-valued const constraints. Non-string malformed JSON still\n // gets rejected later during IR validation if the field type is\n // incompatible with this fallback string value.\n return {\n kind: \"constraint\",\n constraintKind: \"const\",\n value: trimmedText,\n ...(path && { path }),\n provenance,\n };\n }\n }\n\n const parsed = tryParseJson(effectiveText);\n if (!Array.isArray(parsed)) {\n return null;\n }\n const members: (string | number)[] = [];\n for (const item of parsed) {\n if (typeof item === \"string\" || typeof item === \"number\") {\n members.push(item);\n } else if (typeof item === \"object\" && item !== null && \"id\" in item) {\n const id = (item as Record<string, unknown>)[\"id\"];\n if (typeof id === \"string\" || typeof id === \"number\") {\n members.push(id);\n }\n }\n }\n return {\n kind: \"constraint\",\n constraintKind: \"allowedMembers\",\n members,\n ...(path && { path }),\n provenance,\n };\n }\n\n // expectedType === \"string\" — only remaining case after number and json\n return {\n kind: \"constraint\",\n constraintKind: \"pattern\",\n pattern: effectiveText,\n ...(path && { path }),\n provenance,\n };\n}\n\n/**\n * Parses a raw `@defaultValue` tag payload into a JSON value annotation.\n */\nfunction parseDefaultValueValue(text: string, provenance: Provenance): AnnotationNode {\n const trimmed = text.trim();\n let value: JsonValue;\n\n if (trimmed === \"null\") {\n value = null;\n } else if (trimmed === \"true\") {\n value = true;\n } else if (trimmed === \"false\") {\n value = false;\n } else {\n const parsed = tryParseJson(trimmed);\n value = parsed !== null ? (parsed as JsonValue) : trimmed;\n }\n\n return {\n kind: \"annotation\",\n annotationKind: \"defaultValue\",\n value,\n provenance,\n };\n}\n\nfunction isMemberTargetDisplayName(text: string): boolean {\n return parseMemberTargetDisplayName(text) !== null;\n}\n\nfunction parseMemberTargetDisplayName(\n text: string\n): { readonly target: string; readonly label: string } | null {\n const match = /^:([^\\s]+)\\s+([\\s\\S]+)$/.exec(text);\n if (!match?.[1] || !match[2]) return null;\n return { target: match[1], label: match[2].trim() };\n}\n\n// =============================================================================\n// PRIVATE HELPERS — provenance\n// =============================================================================\n\nfunction provenanceForComment(\n range: ts.CommentRange,\n sourceFile: ts.SourceFile,\n file: string,\n tagName: string\n): Provenance {\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(range.pos);\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n tagName: \"@\" + tagName,\n };\n}\n\nfunction provenanceForJSDocTag(tag: ts.JSDocTag, file: string): Provenance {\n const sourceFile = tag.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(tag.getStart());\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n tagName: \"@\" + tag.tagName.text,\n };\n}\n\n/**\n * Extracts the text content from a TypeScript JSDoc tag's comment.\n */\nfunction getTagCommentText(tag: ts.JSDocTag): string | undefined {\n if (tag.comment === undefined) {\n return undefined;\n }\n if (typeof tag.comment === \"string\") {\n return tag.comment;\n }\n return ts.getTextOfJSDocComment(tag.comment);\n}\n","/**\n * Shared JSON parsing utilities for the analyzer pipeline.\n */\n\n/**\n * Attempts to parse `text` as JSON.\n *\n * Returns the parsed value on success, or `null` if the input is not valid\n * JSON. This is the canonical \"try-parse\" wrapper used by the constraint tag\n * parsers so that every `JSON.parse` call in this package is consistent and\n * centrally tested.\n *\n * Note: when the input is the literal string `\"null\"`, the return value is\n * also `null` (valid JSON). This helper therefore cannot distinguish parse\n * failure from a successfully-parsed JSON `null`. Callers that need to\n * distinguish these cases should use a different API (for example, a wrapper\n * that returns a discriminated result such as `{ ok: boolean, value?: unknown }`).\n *\n * @param text - Raw string to parse\n * @returns The parsed value, or `null` on parse failure\n */\nexport function tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return null;\n }\n}\n","/**\n * JSON Schema 2020-12 generator that consumes the canonical FormIR.\n *\n * This generator is a pure function of the IR. It never consults the TypeScript\n * AST or surface syntax directly — only the IR (per the JSON Schema vocabulary spec §1.2).\n *\n * @see https://json-schema.org/draft/2020-12/schema\n * @see https://json-schema.org/draft/2020-12/schema\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n TypeNode,\n PrimitiveTypeNode,\n EnumTypeNode,\n ArrayTypeNode,\n ObjectTypeNode,\n RecordTypeNode,\n UnionTypeNode,\n ReferenceTypeNode,\n DynamicTypeNode,\n CustomTypeNode,\n ConstraintNode,\n AnnotationNode,\n ObjectProperty,\n JsonValue,\n} from \"@formspec/core\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\n\n// =============================================================================\n// OUTPUT TYPE\n// =============================================================================\n\n/**\n * A JSON Schema 2020-12 document, sub-schema, or keyword collection.\n *\n * This interface covers the subset of JSON Schema 2020-12 that this generator\n * emits, plus an index signature for custom `x-formspec-*` extension keywords.\n */\nexport interface JsonSchema2020 {\n $schema?: string;\n $ref?: string;\n $defs?: Record<string, JsonSchema2020>;\n type?: string;\n properties?: Record<string, JsonSchema2020>;\n required?: string[];\n items?: JsonSchema2020;\n additionalProperties?: boolean | JsonSchema2020;\n enum?: readonly (string | number)[];\n const?: JsonValue;\n allOf?: readonly JsonSchema2020[];\n oneOf?: readonly JsonSchema2020[];\n anyOf?: readonly JsonSchema2020[];\n // Constraints\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n multipleOf?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n maxItems?: number;\n pattern?: string;\n uniqueItems?: boolean;\n format?: string;\n // Annotations\n title?: string;\n description?: string;\n default?: unknown;\n deprecated?: boolean;\n // Extensions (open for vendor-prefixed keywords, e.g., x-formspec-*, x-stripe-*)\n // The vendor prefix is configurable (white-labelable).\n [key: `x-${string}`]: unknown;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/**\n * Mutable accumulator passed through the generation traversal.\n *\n * Using a context object rather than return-value threading keeps the\n * recursive generators simple and avoids repeated object spreading.\n */\ninterface GeneratorContext {\n /** Named type schemas collected during traversal, keyed by reference name. */\n readonly defs: Record<string, JsonSchema2020>;\n /** Optional extension registry for resolving custom IR nodes. */\n readonly extensionRegistry: ExtensionRegistry | undefined;\n /** Vendor prefix passed through to extension toJsonSchema handlers. */\n readonly vendorPrefix: string;\n}\n\n/**\n * Options for generating JSON Schema from a canonical FormIR.\n */\nexport interface GenerateJsonSchemaFromIROptions {\n /**\n * Registry used to resolve custom types, constraints, and annotations.\n *\n * JSON Schema generation throws when custom IR nodes are present without a\n * matching registration in this registry.\n */\n readonly extensionRegistry?: ExtensionRegistry | undefined;\n /**\n * Vendor prefix passed to extension `toJsonSchema` hooks.\n * @defaultValue \"x-formspec\"\n */\n readonly vendorPrefix?: string | undefined;\n}\n\nfunction makeContext(options?: GenerateJsonSchemaFromIROptions): GeneratorContext {\n const vendorPrefix = options?.vendorPrefix ?? \"x-formspec\";\n if (!vendorPrefix.startsWith(\"x-\")) {\n throw new Error(\n `Invalid vendorPrefix \"${vendorPrefix}\". Extension JSON Schema keywords must start with \"x-\".`\n );\n }\n\n return {\n defs: {},\n extensionRegistry: options?.extensionRegistry,\n vendorPrefix,\n };\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Generates a JSON Schema 2020-12 object from a canonical FormIR.\n *\n * Groups and conditionals are flattened — they influence UI layout but do not\n * affect the data schema. All fields appear at the level they would occupy in\n * the output data.\n *\n * Named types in the `typeRegistry` are emitted as `$defs` entries and\n * referenced via `$ref` (per PP7 — high-fidelity output).\n *\n * @example\n * ```typescript\n * import { canonicalizeDSL } from \"./canonicalize/index.js\";\n * import { generateJsonSchemaFromIR } from \"./json-schema/ir-generator.js\";\n * import { formspec, field } from \"@formspec/dsl\";\n *\n * const form = formspec(\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n * const ir = canonicalizeDSL(form);\n * const schema = generateJsonSchemaFromIR(ir);\n * // {\n * // $schema: \"https://json-schema.org/draft/2020-12/schema\",\n * // type: \"object\",\n * // properties: {\n * // name: { type: \"string\", title: \"Name\" },\n * // age: { type: \"number\", minimum: 0 }\n * // },\n * // required: [\"name\"]\n * // }\n * ```\n *\n * Advanced API — most consumers should use `generateJsonSchema()` or\n * `buildFormSchemas()`, which canonicalize form definitions automatically.\n * Callers of this function are responsible for providing pre-canonicalized IR.\n *\n * @param ir - The canonical FormIR produced by a canonicalizer\n * @returns A plain JSON-serializable JSON Schema 2020-12 object\n */\nexport function generateJsonSchemaFromIR(\n ir: FormIR,\n options?: GenerateJsonSchemaFromIROptions\n): JsonSchema2020 {\n const ctx = makeContext(options);\n\n // Seed $defs from the type registry so referenced types are available even if\n // the field tree traversal never visits them (e.g., unreferenced types added\n // by a TSDoc canonicalizer pass).\n for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {\n ctx.defs[name] = generateTypeNode(typeDef.type, ctx);\n if (typeDef.annotations && typeDef.annotations.length > 0) {\n applyAnnotations(ctx.defs[name], typeDef.annotations, ctx);\n }\n }\n\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n collectFields(ir.elements, properties, required, ctx);\n\n // Deduplicate required (same field can appear across conditional branches).\n const uniqueRequired = [...new Set(required)];\n\n const result: JsonSchema2020 = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties,\n ...(uniqueRequired.length > 0 && { required: uniqueRequired }),\n };\n\n if (ir.annotations && ir.annotations.length > 0) {\n applyAnnotations(result, ir.annotations, ctx);\n }\n\n if (Object.keys(ctx.defs).length > 0) {\n result.$defs = ctx.defs;\n }\n\n return result;\n}\n\n// =============================================================================\n// ELEMENT TRAVERSAL\n// =============================================================================\n\n/**\n * Recursively visits all IR elements, collecting field schemas and required names.\n *\n * Groups and conditionals are transparent to the schema — their children are\n * lifted to the enclosing level (per the JSON Schema vocabulary spec §1.2).\n */\nfunction collectFields(\n elements: readonly FormIRElement[],\n properties: Record<string, JsonSchema2020>,\n required: string[],\n ctx: GeneratorContext\n): void {\n for (const element of elements) {\n switch (element.kind) {\n case \"field\":\n properties[element.name] = generateFieldSchema(element, ctx);\n if (element.required) {\n required.push(element.name);\n }\n break;\n\n case \"group\":\n // Groups are UI-only; flatten children into the enclosing schema.\n collectFields(element.elements, properties, required, ctx);\n break;\n\n case \"conditional\":\n // Conditional visibility is UI-only; all fields remain in the schema.\n collectFields(element.elements, properties, required, ctx);\n break;\n\n default: {\n const _exhaustive: never = element;\n void _exhaustive;\n }\n }\n }\n}\n\n// =============================================================================\n// FIELD SCHEMA GENERATION\n// =============================================================================\n\n/**\n * Generates the JSON Schema sub-schema for a single FieldNode.\n */\nfunction generateFieldSchema(field: FieldNode, ctx: GeneratorContext): JsonSchema2020 {\n const schema = generateTypeNode(field.type, ctx);\n const itemStringSchema =\n schema.type === \"array\" && schema.items?.type === \"string\" ? schema.items : undefined;\n\n // Partition constraints into direct (no path) and path-targeted.\n const directConstraints: ConstraintNode[] = [];\n const itemConstraints: ConstraintNode[] = [];\n const pathConstraints: ConstraintNode[] = [];\n for (const c of field.constraints) {\n if (c.path) {\n pathConstraints.push(c);\n } else if (itemStringSchema !== undefined && isStringItemConstraint(c)) {\n itemConstraints.push(c);\n } else {\n directConstraints.push(c);\n }\n }\n\n // Apply direct constraints. multipleOf:1 on a number type is a special case:\n // it promotes the type to \"integer\" and removes the multipleOf keyword.\n applyConstraints(schema, directConstraints, ctx);\n\n if (itemStringSchema !== undefined) {\n applyConstraints(itemStringSchema, itemConstraints, ctx);\n }\n\n // Apply annotations (title, description, default, deprecated, etc.).\n const rootAnnotations: AnnotationNode[] = [];\n const itemAnnotations: AnnotationNode[] = [];\n for (const annotation of field.annotations) {\n if (itemStringSchema !== undefined && annotation.annotationKind === \"format\") {\n itemAnnotations.push(annotation);\n } else {\n rootAnnotations.push(annotation);\n }\n }\n\n applyAnnotations(schema, rootAnnotations, ctx);\n if (itemStringSchema !== undefined) {\n applyAnnotations(itemStringSchema, itemAnnotations, ctx);\n }\n\n // If no path-targeted constraints, return as-is.\n if (pathConstraints.length === 0) {\n return schema;\n }\n\n return applyPathTargetedConstraints(schema, pathConstraints, ctx);\n}\n\n/**\n * Returns true if a constraint should be applied to the `items` schema of a\n * primitive `string[]` rather than the array itself.\n *\n * `@const` is intentionally excluded: arrays cannot carry primitive const\n * constraints in FormSpec, so `@const` on `string[]` remains a validation\n * error instead of targeting the item schema.\n */\nfunction isStringItemConstraint(constraint: ConstraintNode): boolean {\n switch (constraint.constraintKind) {\n case \"minLength\":\n case \"maxLength\":\n case \"pattern\":\n return true;\n default:\n return false;\n }\n}\n\n/**\n * Applies path-targeted constraints to a schema via allOf composition.\n *\n * For $ref schemas: wraps in allOf with property overrides.\n * For inline object schemas: applies directly to nested properties.\n * For array schemas: applies path constraints to the items sub-schema.\n */\nfunction applyPathTargetedConstraints(\n schema: JsonSchema2020,\n pathConstraints: readonly ConstraintNode[],\n ctx: GeneratorContext\n): JsonSchema2020 {\n // Array transparency: path-targeted constraints target the item type.\n if (schema.type === \"array\" && schema.items) {\n schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx);\n return schema;\n }\n\n // Group path constraints by target field name (first path segment).\n // Callers guarantee all entries have a defined `path` (filtered upstream).\n const byTarget = new Map<string, ConstraintNode[]>();\n for (const c of pathConstraints) {\n const target = c.path?.segments[0];\n if (!target) continue;\n const group = byTarget.get(target) ?? [];\n group.push(c);\n byTarget.set(target, group);\n }\n\n // Build the property overrides object.\n const propertyOverrides: Record<string, JsonSchema2020> = {};\n for (const [target, constraints] of byTarget) {\n const subSchema: JsonSchema2020 = {};\n applyConstraints(subSchema, constraints, ctx);\n propertyOverrides[target] = subSchema;\n }\n\n // $ref schema: wrap in allOf to preserve $ref semantics while adding overrides.\n if (schema.$ref) {\n const { $ref, ...rest } = schema;\n const refPart: JsonSchema2020 = { $ref };\n const overridePart: JsonSchema2020 = {\n properties: propertyOverrides,\n ...rest,\n };\n return { allOf: [refPart, overridePart] };\n }\n\n // Inline object schema: merge property overrides directly where possible.\n if (schema.type === \"object\" && schema.properties) {\n const missingOverrides: Record<string, JsonSchema2020> = {};\n\n for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {\n if (schema.properties[target]) {\n Object.assign(schema.properties[target], overrideSchema);\n } else {\n // Do not introduce new properties directly; compose via allOf instead\n // to preserve additionalProperties semantics on the base object.\n missingOverrides[target] = overrideSchema;\n }\n }\n\n if (Object.keys(missingOverrides).length === 0) {\n return schema;\n }\n\n return {\n allOf: [schema, { properties: missingOverrides }],\n };\n }\n\n // allOf schema (already composed): add property overrides as another member.\n if (schema.allOf) {\n schema.allOf = [...schema.allOf, { properties: propertyOverrides }];\n return schema;\n }\n\n // Fallback: for non-object/non-$ref schemas, path-targeted constraints do not\n // apply in a meaningful way. Return the original schema unchanged and rely\n // on validation diagnostics to surface misuse of path-based constraints.\n return schema;\n}\n\n// =============================================================================\n// TYPE NODE GENERATION\n// =============================================================================\n\n/**\n * Converts a TypeNode to a JSON Schema sub-schema.\n *\n * This function is intentionally exhaustive — all TypeNode variants are handled.\n * TypeScript's exhaustiveness check via the default branch ensures new variants\n * added to the IR are caught at compile time.\n */\nfunction generateTypeNode(type: TypeNode, ctx: GeneratorContext): JsonSchema2020 {\n switch (type.kind) {\n case \"primitive\":\n return generatePrimitiveType(type);\n\n case \"enum\":\n return generateEnumType(type);\n\n case \"array\":\n return generateArrayType(type, ctx);\n\n case \"object\":\n return generateObjectType(type, ctx);\n\n case \"record\":\n return generateRecordType(type, ctx);\n\n case \"union\":\n return generateUnionType(type, ctx);\n\n case \"reference\":\n return generateReferenceType(type);\n\n case \"dynamic\":\n return generateDynamicType(type);\n\n case \"custom\":\n return generateCustomType(type, ctx);\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = type;\n return _exhaustive;\n }\n }\n}\n\n/**\n * Maps primitive IR types to JSON Schema type keywords.\n *\n * Note: `integer` is NOT a primitive kind in the IR. Integer semantics are\n * expressed via a `multipleOf: 1` constraint on a number type; `applyConstraints`\n * handles the promotion (per the JSON Schema vocabulary spec §2.1).\n */\nfunction generatePrimitiveType(type: PrimitiveTypeNode): JsonSchema2020 {\n return { type: type.primitiveKind };\n}\n\n/**\n * Generates JSON Schema for a static enum type.\n *\n * When any member has a displayName, the output uses the `oneOf` form with\n * per-member `const`/`title` entries (per the JSON Schema vocabulary spec §2.3). Otherwise the\n * flat `enum` keyword is used (simpler, equally valid).\n */\nfunction generateEnumType(type: EnumTypeNode): JsonSchema2020 {\n const hasDisplayNames = type.members.some((m) => m.displayName !== undefined);\n\n if (hasDisplayNames) {\n return {\n oneOf: type.members.map((m) => {\n const entry: JsonSchema2020 = { const: m.value };\n if (m.displayName !== undefined) {\n entry.title = m.displayName;\n }\n return entry;\n }),\n };\n }\n\n return { enum: type.members.map((m) => m.value) };\n}\n\n/**\n * Generates JSON Schema for an array type.\n * Per 2020-12, `items` is a single schema (not an array); tuple types use\n * `prefixItems` + `items: false`.\n */\nfunction generateArrayType(type: ArrayTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n return {\n type: \"array\",\n items: generateTypeNode(type.items, ctx),\n };\n}\n\n/**\n * Generates JSON Schema for an object type.\n *\n * `additionalProperties` is emitted only when the IR explicitly closes the\n * object. Ordinary static object types now canonicalize to\n * `additionalProperties: true`, which omits the keyword per spec 003 §2.5.\n */\nfunction generateObjectType(type: ObjectTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n for (const prop of type.properties) {\n properties[prop.name] = generatePropertySchema(prop, ctx);\n if (!prop.optional) {\n required.push(prop.name);\n }\n }\n\n const schema: JsonSchema2020 = { type: \"object\", properties };\n\n if (required.length > 0) {\n schema.required = required;\n }\n\n if (!type.additionalProperties) {\n schema.additionalProperties = false;\n }\n\n return schema;\n}\n\n/**\n * Generates JSON Schema for a record (dictionary) type per spec 003 §2.5.\n *\n * `Record<string, T>` and `{ [k: string]: T }` both emit:\n * `{ \"type\": \"object\", \"additionalProperties\": <T schema> }`\n *\n * No `properties` key is emitted — the record has no named properties.\n */\nfunction generateRecordType(type: RecordTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n return {\n type: \"object\",\n additionalProperties: generateTypeNode(type.valueType, ctx),\n };\n}\n\n/**\n * Generates a schema for an ObjectProperty, applying its use-site constraints\n * and annotations (per the JSON Schema vocabulary spec §5.4 — inline allOf at use site).\n */\nfunction generatePropertySchema(prop: ObjectProperty, ctx: GeneratorContext): JsonSchema2020 {\n const schema = generateTypeNode(prop.type, ctx);\n applyConstraints(schema, prop.constraints, ctx);\n applyAnnotations(schema, prop.annotations, ctx);\n return schema;\n}\n\n/**\n * Generates JSON Schema for a union type.\n *\n * Union handling strategy (per spec 003):\n * - Boolean shorthand: `true | false` → `{ type: \"boolean\" }` (not oneOf/anyOf)\n * - Nullable unions: `T | null` → `{ \"oneOf\": [<T schema>, { \"type\": \"null\" }] }` (§2.3)\n * - All other unions → `anyOf` (members may overlap; discriminated union\n * detection is deferred to a future phase per design doc 003 §7.4)\n */\nfunction generateUnionType(type: UnionTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n // Boolean shorthand: union of true-literal and false-literal → type: \"boolean\"\n if (isBooleanUnion(type)) {\n return { type: \"boolean\" };\n }\n\n // Nullable union: `T | null` → oneOf per spec 003 §2.3.\n // A nullable union is any union where exactly one member is the null primitive.\n if (isNullableUnion(type)) {\n return {\n oneOf: type.members.map((m) => generateTypeNode(m, ctx)),\n };\n }\n\n // Default: anyOf for non-discriminated object unions (spec 003 §7.4).\n // Discriminated union detection (shared required property with distinct consts)\n // is deferred to a future phase.\n return {\n anyOf: type.members.map((m) => generateTypeNode(m, ctx)),\n };\n}\n\n/**\n * Returns true if the union is `true | false` (boolean shorthand).\n */\nfunction isBooleanUnion(type: UnionTypeNode): boolean {\n if (type.members.length !== 2) return false;\n const kinds = type.members.map((m) => m.kind);\n // Both must be primitives; check if both are \"boolean\" primitives.\n // The IR currently does not have a boolean literal node, so boolean union\n // is represented as two primitive boolean members.\n return (\n kinds.every((k) => k === \"primitive\") &&\n type.members.every((m) => m.kind === \"primitive\" && m.primitiveKind === \"boolean\")\n );\n}\n\n/**\n * Returns true if the union is a nullable wrapper union (`T | null` for any T).\n *\n * A nullable union is a two-member union where exactly one member is the `null`\n * primitive type and the other member is any non-null type.\n * Per spec 003 §2.3, nullable unions map to `oneOf` (not `anyOf`).\n */\nfunction isNullableUnion(type: UnionTypeNode): boolean {\n if (type.members.length !== 2) return false;\n const nullCount = type.members.filter(\n (m) => m.kind === \"primitive\" && m.primitiveKind === \"null\"\n ).length;\n return nullCount === 1;\n}\n\n/**\n * Generates JSON Schema for a reference type.\n *\n * The referenced type's schema is stored in `$defs` (seeded from the type\n * registry before traversal begins). The reference simply emits a `$ref`.\n */\nfunction generateReferenceType(type: ReferenceTypeNode): JsonSchema2020 {\n return { $ref: `#/$defs/${type.name}` };\n}\n\n/**\n * Generates JSON Schema for a dynamic type (runtime-resolved enum or schema).\n *\n * Dynamic enums emit `x-formspec-source` and optionally `x-formspec-params`.\n * Dynamic schemas emit `x-formspec-schemaSource` with `additionalProperties: true`\n * since the actual schema is determined at runtime (per the JSON Schema vocabulary spec §3.2).\n */\nfunction generateDynamicType(type: DynamicTypeNode): JsonSchema2020 {\n if (type.dynamicKind === \"enum\") {\n const schema: JsonSchema2020 = {\n type: \"string\",\n \"x-formspec-source\": type.sourceKey,\n };\n if (type.parameterFields.length > 0) {\n schema[\"x-formspec-params\"] = [...type.parameterFields];\n }\n return schema;\n }\n\n // dynamicKind === \"schema\"\n return {\n type: \"object\",\n additionalProperties: true,\n \"x-formspec-schemaSource\": type.sourceKey,\n };\n}\n\n// =============================================================================\n// CONSTRAINT APPLICATION\n// =============================================================================\n\n/**\n * Applies constraint nodes onto an existing JSON Schema object (mutates in place).\n *\n * All callers pass freshly-created objects so there is no aliasing risk.\n *\n * Special rule (per the JSON Schema vocabulary spec §2.1): `multipleOf: 1` on a `\"number\"` type\n * promotes to `\"integer\"` and suppresses the `multipleOf` keyword (integer is a\n * subtype of number; expressing it via multipleOf:1 is redundant).\n *\n * Path-targeted constraints are handled separately by `applyPathTargetedConstraints`.\n */\nfunction applyConstraints(\n schema: JsonSchema2020,\n constraints: readonly ConstraintNode[],\n ctx: GeneratorContext\n): void {\n for (const constraint of constraints) {\n switch (constraint.constraintKind) {\n case \"minimum\":\n schema.minimum = constraint.value;\n break;\n\n case \"maximum\":\n schema.maximum = constraint.value;\n break;\n\n case \"exclusiveMinimum\":\n schema.exclusiveMinimum = constraint.value;\n break;\n\n case \"exclusiveMaximum\":\n schema.exclusiveMaximum = constraint.value;\n break;\n\n case \"multipleOf\": {\n const { value } = constraint;\n if (value === 1 && schema.type === \"number\") {\n // Promote number → integer; omit the multipleOf keyword (redundant).\n schema.type = \"integer\";\n } else {\n schema.multipleOf = value;\n }\n break;\n }\n\n case \"minLength\":\n schema.minLength = constraint.value;\n break;\n\n case \"maxLength\":\n schema.maxLength = constraint.value;\n break;\n\n case \"minItems\":\n schema.minItems = constraint.value;\n break;\n\n case \"maxItems\":\n schema.maxItems = constraint.value;\n break;\n\n case \"pattern\":\n schema.pattern = constraint.pattern;\n break;\n\n case \"uniqueItems\":\n schema.uniqueItems = constraint.value;\n break;\n\n case \"const\":\n schema.const = constraint.value;\n break;\n\n case \"allowedMembers\":\n // EnumMemberConstraintNode — not yet emitted to JSON Schema (Phase 6 validation).\n break;\n\n case \"custom\":\n applyCustomConstraint(schema, constraint, ctx);\n break;\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = constraint;\n void _exhaustive;\n }\n }\n }\n}\n\n// =============================================================================\n// ANNOTATION APPLICATION\n// =============================================================================\n\n/**\n * Applies annotation nodes onto an existing JSON Schema object (mutates in place).\n *\n * Mapping per the JSON Schema vocabulary spec §2.8:\n * - `displayName` → `title`\n * - `description` → `description`\n * - `defaultValue` → `default`\n * - `deprecated` → `deprecated: true` (2020-12 standard annotation)\n * - `format` → `format`\n *\n * UI-only annotations (`placeholder`, `formatHint`) are silently ignored here —\n * they belong in the UI Schema, not the data schema.\n */\nfunction applyAnnotations(\n schema: JsonSchema2020,\n annotations: readonly AnnotationNode[],\n ctx: GeneratorContext\n): void {\n for (const annotation of annotations) {\n switch (annotation.annotationKind) {\n case \"displayName\":\n schema.title = annotation.value;\n break;\n\n case \"description\":\n schema.description = annotation.value;\n break;\n\n case \"defaultValue\":\n schema.default = annotation.value;\n break;\n\n case \"format\":\n schema.format = annotation.value;\n break;\n\n case \"deprecated\":\n schema.deprecated = true;\n if (annotation.message !== undefined && annotation.message !== \"\") {\n schema[\"x-formspec-deprecation-description\"] = annotation.message;\n }\n break;\n\n case \"placeholder\":\n // UI-only — belongs in UI Schema, not emitted here.\n break;\n\n case \"formatHint\":\n // UI-only — belongs in UI Schema, not emitted here.\n break;\n\n case \"custom\":\n applyCustomAnnotation(schema, annotation, ctx);\n break;\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = annotation;\n void _exhaustive;\n }\n }\n }\n}\n\nfunction generateCustomType(type: CustomTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n const registration = ctx.extensionRegistry?.findType(type.typeId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom type \"${type.typeId}\" without a matching extension registration`\n );\n }\n\n // Trust boundary: extensions are responsible for returning valid JSON Schema.\n // Core only depends on Record<string, unknown> here, so we cast at the edge.\n return registration.toJsonSchema(type.payload, ctx.vendorPrefix) as JsonSchema2020;\n}\n\nfunction applyCustomConstraint(\n schema: JsonSchema2020,\n constraint: Extract<ConstraintNode, { constraintKind: \"custom\" }>,\n ctx: GeneratorContext\n): void {\n const registration = ctx.extensionRegistry?.findConstraint(constraint.constraintId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom constraint \"${constraint.constraintId}\" without a matching extension registration`\n );\n }\n\n // Trust boundary: extension hooks are expected to return valid JSON Schema\n // keywords, typically vendor-prefixed extension annotations.\n Object.assign(schema, registration.toJsonSchema(constraint.payload, ctx.vendorPrefix));\n}\n\nfunction applyCustomAnnotation(\n schema: JsonSchema2020,\n annotation: Extract<AnnotationNode, { annotationKind: \"custom\" }>,\n ctx: GeneratorContext\n): void {\n const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom annotation \"${annotation.annotationId}\" without a matching extension registration`\n );\n }\n\n if (registration.toJsonSchema === undefined) {\n return;\n }\n\n // Trust boundary: extension hooks are expected to return valid JSON Schema\n // keywords, typically vendor-prefixed extension annotations.\n Object.assign(schema, registration.toJsonSchema(annotation.value, ctx.vendorPrefix));\n}\n","/**\n * Zod schemas for JSON Forms UI Schema.\n *\n * These schemas are the source of truth for UI Schema validation.\n * TypeScript types are derived from these schemas via `z.infer<>`.\n *\n * @see https://jsonforms.io/docs/uischema/\n */\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Primitive helpers\n// =============================================================================\n\n/** JSON Pointer string (e.g., \"#/properties/fieldName\") */\nconst jsonPointerSchema = z.string();\n\n// =============================================================================\n// Rule Effect and Element Type enums\n// =============================================================================\n\n/**\n * Zod schema for rule effect values.\n */\nexport const ruleEffectSchema = z.enum([\"SHOW\", \"HIDE\", \"ENABLE\", \"DISABLE\"]);\n\n/**\n * Rule effect types for conditional visibility.\n */\nexport type RuleEffect = z.infer<typeof ruleEffectSchema>;\n\n/**\n * Zod schema for UI Schema element type strings.\n */\nexport const uiSchemaElementTypeSchema = z.enum([\n \"Control\",\n \"VerticalLayout\",\n \"HorizontalLayout\",\n \"Group\",\n \"Categorization\",\n \"Category\",\n \"Label\",\n]);\n\n/**\n * UI Schema element types.\n */\nexport type UISchemaElementType = z.infer<typeof uiSchemaElementTypeSchema>;\n\n// =============================================================================\n// Rule Condition Schema (recursive)\n// =============================================================================\n\n// Forward-declare the recursive TypeScript type.\n// We use an interface here (rather than z.infer<>) because the recursive\n// z.lazy() type annotation requires us to pre-declare the shape.\n/**\n * JSON Schema subset used in rule conditions.\n */\nexport interface RuleConditionSchema {\n const?: unknown;\n enum?: readonly unknown[];\n type?: string;\n not?: RuleConditionSchema;\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n minLength?: number;\n properties?: Record<string, RuleConditionSchema>;\n required?: string[];\n allOf?: RuleConditionSchema[];\n}\n\n// Build the Zod schema referencing the pre-declared interface.\n// We use z.ZodType<RuleConditionSchema> so the recursive reference works.\n// The interface uses `?` (exact optional), and z.ZodType checks output only,\n// so the optional fields (which Zod infers as `T | undefined`) are compatible\n// because `T | undefined` is assignable to the optional field slot.\n//\n// @ts-expect-error -- exactOptionalPropertyTypes: the Zod output type for optional\n// fields is `T | undefined`, but our interface uses `?` (exact optional, key may\n// be absent). This is a known mismatch when using z.ZodType<T> with\n// exactOptionalPropertyTypes:true; the runtime behavior is correct.\nexport const ruleConditionSchema: z.ZodType<RuleConditionSchema> = z.lazy(() =>\n z\n .object({\n const: z.unknown().optional(),\n enum: z.array(z.unknown()).readonly().optional(),\n type: z.string().optional(),\n not: ruleConditionSchema.optional(),\n minimum: z.number().optional(),\n maximum: z.number().optional(),\n exclusiveMinimum: z.number().optional(),\n exclusiveMaximum: z.number().optional(),\n minLength: z.number().optional(),\n properties: z.record(z.string(), ruleConditionSchema).optional(),\n required: z.array(z.string()).optional(),\n allOf: z.array(ruleConditionSchema).optional(),\n })\n .strict()\n);\n\n// =============================================================================\n// Schema-Based Condition and Rule\n// =============================================================================\n\n/**\n * Zod schema for a schema-based rule condition.\n */\nexport const schemaBasedConditionSchema = z\n .object({\n scope: jsonPointerSchema,\n schema: ruleConditionSchema,\n })\n .strict();\n\n/**\n * Condition for a rule.\n */\nexport type SchemaBasedCondition = z.infer<typeof schemaBasedConditionSchema>;\n\n/**\n * Zod schema for a UI Schema rule.\n */\nexport const ruleSchema = z\n .object({\n effect: ruleEffectSchema,\n condition: schemaBasedConditionSchema,\n })\n .strict();\n\n/**\n * Rule for conditional element visibility/enablement.\n */\nexport type Rule = z.infer<typeof ruleSchema>;\n\n// =============================================================================\n// UI Schema Element Schemas (recursive via z.lazy)\n// =============================================================================\n\n// Forward-declare UISchemaElement so layout schemas can reference it.\n// We declare the type up-front and wire the Zod schema below.\n/**\n * Union of all UI Schema element types.\n */\nexport type UISchemaElement =\n | ControlElement\n | VerticalLayout\n | HorizontalLayout\n | GroupLayout\n | Categorization\n | Category\n | LabelElement;\n\n// The Zod schema for UISchemaElement is defined as a const using z.lazy(),\n// which defers evaluation until first use. This allows all element schemas\n// below to be referenced even though they are declared after this line.\nexport const uiSchemaElementSchema: z.ZodType<UISchemaElement> = z.lazy(() =>\n z.union([\n controlSchema,\n verticalLayoutSchema,\n horizontalLayoutSchema,\n groupLayoutSchema,\n categorizationSchema,\n categorySchema,\n labelElementSchema,\n ])\n) as z.ZodType<UISchemaElement>;\n\n// -----------------------------------------------------------------------------\n// Control\n// -----------------------------------------------------------------------------\n\n/**\n * Zod schema for a Control element.\n */\nexport const controlSchema = z\n .object({\n type: z.literal(\"Control\"),\n scope: jsonPointerSchema,\n label: z.union([z.string(), z.literal(false)]).optional(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\n/**\n * A Control element that binds to a JSON Schema property.\n */\nexport type ControlElement = z.infer<typeof controlSchema>;\n\n// -----------------------------------------------------------------------------\n// VerticalLayout\n// -----------------------------------------------------------------------------\n\n// Pre-declare the interface so the Zod schema can reference UISchemaElement.\n/**\n * A vertical layout element.\n */\nexport interface VerticalLayout {\n type: \"VerticalLayout\";\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const verticalLayoutSchema: z.ZodType<VerticalLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"VerticalLayout\"),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// HorizontalLayout\n// -----------------------------------------------------------------------------\n\n/**\n * A horizontal layout element.\n */\nexport interface HorizontalLayout {\n type: \"HorizontalLayout\";\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const horizontalLayoutSchema: z.ZodType<HorizontalLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"HorizontalLayout\"),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// GroupLayout\n// -----------------------------------------------------------------------------\n\n/**\n * A group element with a label.\n */\nexport interface GroupLayout {\n type: \"Group\";\n label: string;\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const groupLayoutSchema: z.ZodType<GroupLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Group\"),\n label: z.string(),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// Category\n// -----------------------------------------------------------------------------\n\n/**\n * A Category element, used inside a Categorization layout.\n */\nexport interface Category {\n type: \"Category\";\n label: string;\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const categorySchema: z.ZodType<Category> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Category\"),\n label: z.string(),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// Categorization\n// -----------------------------------------------------------------------------\n\n/**\n * A Categorization element (tab-based layout).\n */\nexport interface Categorization {\n type: \"Categorization\";\n elements: Category[];\n label?: string | undefined;\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const categorizationSchema: z.ZodType<Categorization> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Categorization\"),\n elements: z.array(categorySchema),\n label: z.string().optional(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// LabelElement\n// -----------------------------------------------------------------------------\n\n/**\n * Zod schema for a Label element.\n */\nexport const labelElementSchema = z\n .object({\n type: z.literal(\"Label\"),\n text: z.string(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\n/**\n * A Label element for displaying static text.\n */\nexport type LabelElement = z.infer<typeof labelElementSchema>;\n\n// =============================================================================\n// Root UISchema\n// =============================================================================\n\n/**\n * Root UI Schema (always a layout — not a Control, Category, or Label).\n */\nexport type UISchema = VerticalLayout | HorizontalLayout | GroupLayout | Categorization;\n\n/**\n * Zod schema for the root UI Schema (layout types only).\n */\nexport const uiSchema: z.ZodType<UISchema> = z.lazy(() =>\n z.union([verticalLayoutSchema, horizontalLayoutSchema, groupLayoutSchema, categorizationSchema])\n) as z.ZodType<UISchema>;\n","/**\n * JSON Forms UI Schema generator that operates on the canonical FormIR.\n *\n * This generator consumes the IR produced by the Canonicalize phase and\n * produces a JSON Forms UI Schema. All downstream UI Schema generation\n * should use this module for UI Schema generation.\n */\n\nimport type { FormIR, FormIRElement, FieldNode, GroupLayoutNode } from \"@formspec/core\";\nimport type {\n UISchema,\n UISchemaElement,\n ControlElement,\n GroupLayout,\n Rule,\n RuleConditionSchema,\n} from \"./types.js\";\nimport { uiSchema as uiSchemaValidator } from \"./schema.js\";\nimport { z } from \"zod\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/**\n * Parses a value through a Zod schema, converting validation errors to a\n * descriptive Error.\n */\nfunction parseOrThrow<T>(schema: z.ZodType<T>, value: unknown, label: string): T {\n try {\n return schema.parse(value);\n } catch (error) {\n if (error instanceof z.ZodError) {\n throw new Error(\n `Generated ${label} failed validation:\\n${error.issues.map((i) => ` ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\")}`\n );\n }\n throw error;\n }\n}\n\n/**\n * Converts a field name to a JSON Pointer scope string.\n */\nfunction fieldToScope(fieldName: string): string {\n return `#/properties/${fieldName}`;\n}\n\n/**\n * Creates a SHOW rule for a single conditional field/value pair.\n */\nfunction createShowRule(fieldName: string, value: unknown): Rule {\n return {\n effect: \"SHOW\",\n condition: {\n scope: fieldToScope(fieldName),\n schema: { const: value },\n },\n };\n}\n\n/**\n * Combines two SHOW rules into a single rule using an allOf condition.\n *\n * When elements are nested inside multiple conditionals, all parent conditions\n * must be met for the element to be visible. This function flattens both\n * conditions into a single rule using a top-level allOf so JSON Forms evaluates\n * every predicate simultaneously without nesting rule fragments.\n */\nfunction flattenConditionSchema(scope: string, schema: RuleConditionSchema): RuleConditionSchema[] {\n if (schema.allOf === undefined) {\n if (scope === \"#\") {\n return [schema];\n }\n\n const fieldName = scope.replace(\"#/properties/\", \"\");\n return [\n {\n properties: {\n [fieldName]: schema,\n },\n },\n ];\n }\n\n return schema.allOf.flatMap((member) => flattenConditionSchema(scope, member));\n}\n\nfunction combineRules(parentRule: Rule, childRule: Rule): Rule {\n return {\n effect: \"SHOW\",\n condition: {\n scope: \"#\",\n schema: {\n allOf: [\n ...flattenConditionSchema(parentRule.condition.scope, parentRule.condition.schema),\n ...flattenConditionSchema(childRule.condition.scope, childRule.condition.schema),\n ],\n },\n },\n };\n}\n\n// =============================================================================\n// ELEMENT CONVERSION\n// =============================================================================\n\n/**\n * Converts a FieldNode from the IR to a ControlElement.\n *\n * The label is sourced from the first `displayName` annotation on the field,\n * matching how the chain DSL propagates the `label` option through the\n * canonicalization phase.\n */\nfunction fieldNodeToControl(field: FieldNode, parentRule?: Rule): ControlElement {\n const displayNameAnnotation = field.annotations.find((a) => a.annotationKind === \"displayName\");\n const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === \"placeholder\");\n\n const control: ControlElement = {\n type: \"Control\",\n scope: fieldToScope(field.name),\n ...(displayNameAnnotation !== undefined && { label: displayNameAnnotation.value }),\n ...(placeholderAnnotation !== undefined && {\n options: { placeholder: placeholderAnnotation.value },\n }),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n\n return control;\n}\n\n/**\n * Converts a GroupLayoutNode from the IR to a GroupLayout element.\n *\n * The group's children are recursively converted; the optional parent rule is\n * forwarded to nested elements so that a group inside a conditional inherits\n * the visibility rule.\n */\nfunction groupNodeToLayout(group: GroupLayoutNode, parentRule?: Rule): GroupLayout {\n return {\n type: \"Group\",\n label: group.label,\n elements: irElementsToUiSchema(group.elements, parentRule),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n}\n\n/**\n * Converts an array of IR elements to UI Schema elements.\n *\n * @param elements - The IR elements to convert\n * @param parentRule - Optional rule inherited from a parent ConditionalLayoutNode\n * @returns Array of UI Schema elements\n */\nfunction irElementsToUiSchema(\n elements: readonly FormIRElement[],\n parentRule?: Rule\n): UISchemaElement[] {\n const result: UISchemaElement[] = [];\n\n for (const element of elements) {\n switch (element.kind) {\n case \"field\": {\n result.push(fieldNodeToControl(element, parentRule));\n break;\n }\n\n case \"group\": {\n result.push(groupNodeToLayout(element, parentRule));\n break;\n }\n\n case \"conditional\": {\n // Build the rule for this conditional level.\n const newRule = createShowRule(element.fieldName, element.value);\n // Combine with the inherited parent rule for nested conditionals.\n const combinedRule = parentRule !== undefined ? combineRules(parentRule, newRule) : newRule;\n // Children are flattened into the parent container with the combined\n // rule attached.\n const childElements = irElementsToUiSchema(element.elements, combinedRule);\n result.push(...childElements);\n break;\n }\n\n default: {\n const _exhaustive: never = element;\n void _exhaustive;\n throw new Error(\"Unhandled IR element kind\");\n }\n }\n }\n\n return result;\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Generates a JSON Forms UI Schema from a canonical `FormIR`.\n *\n * Mapping rules:\n * - `FieldNode` → `ControlElement` with `scope: \"#/properties/<name>\"`\n * - `displayName` annotation → `label` on the `ControlElement`\n * - `GroupLayoutNode` → `GroupLayout` with recursively converted `elements`\n * - `ConditionalLayoutNode` → children flattened with a `SHOW` rule\n * - Nested conditionals → combined `allOf` rule\n * - Root wrapper is always `{ type: \"VerticalLayout\", elements: [...] }`\n *\n * @example\n * ```typescript\n * const ir = canonicalizeDSL(\n * formspec(\n * group(\"Customer\", field.text(\"name\", { label: \"Name\" })),\n * when(is(\"status\", \"draft\"), field.text(\"notes\", { label: \"Notes\" })),\n * )\n * );\n *\n * const uiSchema = generateUiSchemaFromIR(ir);\n * // {\n * // type: \"VerticalLayout\",\n * // elements: [\n * // {\n * // type: \"Group\",\n * // label: \"Customer\",\n * // elements: [{ type: \"Control\", scope: \"#/properties/name\", label: \"Name\" }]\n * // },\n * // {\n * // type: \"Control\",\n * // scope: \"#/properties/notes\",\n * // label: \"Notes\",\n * // rule: { effect: \"SHOW\", condition: { scope: \"#/properties/status\", schema: { const: \"draft\" } } }\n * // }\n * // ]\n * // }\n * ```\n *\n * @param ir - The canonical FormIR produced by the Canonicalize phase\n * @returns A validated JSON Forms UI Schema\n */\nexport function generateUiSchemaFromIR(ir: FormIR): UISchema {\n const result: UISchema = {\n type: \"VerticalLayout\",\n elements: irElementsToUiSchema(ir.elements),\n };\n\n return parseOrThrow(uiSchemaValidator, result, \"UI Schema\");\n}\n","/**\n * Class schema generator.\n *\n * Generates JSON Schema 2020-12 and JSON Forms UI Schema from statically\n * analyzed class/interface/type alias declarations, routing through the\n * canonical FormIR pipeline.\n */\n\nimport type { UISchema } from \"../ui-schema/types.js\";\nimport {\n createProgramContext,\n findClassByName,\n findInterfaceByName,\n findTypeAliasByName,\n} from \"../analyzer/program.js\";\nimport {\n analyzeClassToIR,\n analyzeInterfaceToIR,\n analyzeTypeAliasToIR,\n type IRClassAnalysis,\n} from \"../analyzer/class-analyzer.js\";\nimport { canonicalizeTSDoc, type TSDocSource } from \"../canonicalize/index.js\";\nimport { generateJsonSchemaFromIR, type JsonSchema2020 } from \"../json-schema/ir-generator.js\";\nimport { generateUiSchemaFromIR } from \"../ui-schema/ir-generator.js\";\n\n/**\n * Generated schemas for a class.\n */\nexport interface ClassSchemas {\n /** JSON Schema 2020-12 for validation */\n jsonSchema: JsonSchema2020;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema 2020-12 and UI Schema from an IR class analysis.\n *\n * Routes through the canonical IR pipeline:\n * IRClassAnalysis → canonicalizeTSDoc → FormIR → JSON Schema / UI Schema\n *\n * @param analysis - The IR analysis result (from analyzeClassToIR, analyzeInterfaceToIR, or analyzeTypeAliasToIR)\n * @param source - Optional source file metadata for provenance\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateClassSchemas(\n analysis: IRClassAnalysis,\n source?: TSDocSource\n): ClassSchemas {\n const ir = canonicalizeTSDoc(analysis, source);\n return {\n jsonSchema: generateJsonSchemaFromIR(ir),\n uiSchema: generateUiSchemaFromIR(ir),\n };\n}\n\n/**\n * Options for generating schemas from a decorated class.\n */\nexport interface GenerateFromClassOptions {\n /** Path to the TypeScript source file */\n filePath: string;\n /** Class name to analyze */\n className: string;\n}\n\n/**\n * Result of generating schemas from a decorated class.\n */\nexport interface GenerateFromClassResult {\n /** JSON Schema 2020-12 for validation */\n jsonSchema: JsonSchema2020;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema and UI Schema from a decorated TypeScript class.\n *\n * This is a high-level entry point that handles the entire pipeline:\n * creating a TypeScript program, finding the class, analyzing it to IR,\n * and generating schemas — all in one call.\n *\n * @example\n * ```typescript\n * const result = generateSchemasFromClass({\n * filePath: \"./src/forms.ts\",\n * className: \"UserForm\",\n * });\n * console.log(result.jsonSchema);\n * ```\n *\n * @param options - File path, class name, and optional compiler options\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateSchemasFromClass(\n options: GenerateFromClassOptions\n): GenerateFromClassResult {\n const ctx = createProgramContext(options.filePath);\n const classDecl = findClassByName(ctx.sourceFile, options.className);\n\n if (!classDecl) {\n throw new Error(`Class \"${options.className}\" not found in ${options.filePath}`);\n }\n\n const analysis = analyzeClassToIR(classDecl, ctx.checker, options.filePath);\n return generateClassSchemas(analysis, { file: options.filePath });\n}\n\n/**\n * Options for generating schemas from a named type (class, interface, or type alias).\n */\nexport interface GenerateSchemasOptions {\n /** Path to the TypeScript source file */\n filePath: string;\n /** Name of the exported class, interface, or type alias to analyze */\n typeName: string;\n}\n\n/**\n * Generates JSON Schema and UI Schema from a named TypeScript\n * type — a decorated class, an interface with TSDoc tags, or a type alias.\n *\n * This is the recommended entry point. It automatically detects whether\n * the name resolves to a class, interface, or type alias and uses the\n * appropriate IR analysis pipeline.\n *\n * @example\n * ```typescript\n * const result = generateSchemas({\n * filePath: \"./src/config.ts\",\n * typeName: \"DiscountConfig\",\n * });\n * ```\n *\n * @param options - File path and type name\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateSchemas(options: GenerateSchemasOptions): GenerateFromClassResult {\n const ctx = createProgramContext(options.filePath);\n const source: TSDocSource = { file: options.filePath };\n\n // Try class first\n const classDecl = findClassByName(ctx.sourceFile, options.typeName);\n if (classDecl) {\n const analysis = analyzeClassToIR(classDecl, ctx.checker, options.filePath);\n return generateClassSchemas(analysis, source);\n }\n\n // Try interface\n const interfaceDecl = findInterfaceByName(ctx.sourceFile, options.typeName);\n if (interfaceDecl) {\n const analysis = analyzeInterfaceToIR(interfaceDecl, ctx.checker, options.filePath);\n return generateClassSchemas(analysis, source);\n }\n\n // Try type alias\n const typeAlias = findTypeAliasByName(ctx.sourceFile, options.typeName);\n if (typeAlias) {\n const result = analyzeTypeAliasToIR(typeAlias, ctx.checker, options.filePath);\n if (result.ok) {\n return generateClassSchemas(result.analysis, source);\n }\n throw new Error(result.error);\n }\n\n throw new Error(\n `Type \"${options.typeName}\" not found as a class, interface, or type alias in ${options.filePath}`\n );\n}\n","/**\n * Constraint validator for the FormSpec IR.\n *\n * Performs the Validate pipeline phase:\n * - Contradiction detection between paired constraints\n * - Type applicability checks (e.g. numeric constraints on string fields)\n * - Custom constraint type applicability (when extension registry is provided)\n * - Unknown extension warnings (when a registry is provided)\n *\n * @packageDocumentation\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n TypeNode,\n ConstraintNode,\n NumericConstraintNode,\n LengthConstraintNode,\n EnumMemberConstraintNode,\n Provenance,\n ObjectProperty,\n JsonValue,\n} from \"@formspec/core\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\n\n// =============================================================================\n// PUBLIC API TYPES\n// =============================================================================\n\n/**\n * A structured diagnostic produced by constraint validation.\n *\n * The `code` is a stable, machine-readable semantic identifier.\n * Examples: `CONTRADICTING_CONSTRAINTS`, `TYPE_MISMATCH`, `UNKNOWN_EXTENSION`.\n */\nexport interface ValidationDiagnostic {\n readonly code: string;\n readonly message: string;\n readonly severity: \"error\" | \"warning\";\n /** Location of the primary constraint involved in the violation. */\n readonly primaryLocation: Provenance;\n /** Related locations (e.g., the other side of a contradiction pair). */\n readonly relatedLocations: readonly Provenance[];\n}\n\n/** Result of validating a {@link FormIR}. */\nexport interface ValidationResult {\n readonly diagnostics: readonly ValidationDiagnostic[];\n /** `true` if there are no error-severity diagnostics (warnings are OK). */\n readonly valid: boolean;\n}\n\n/** Options for constraint validation. */\nexport interface ValidateIROptions {\n /** @deprecated Ignored. Diagnostic codes are semantic identifiers only. */\n readonly vendorPrefix?: string;\n /**\n * Extension registry for resolving custom constraint type applicability.\n * When provided, custom constraints with `applicableTypes` will be\n * validated against the field's type node kind. Custom constraints\n * whose IDs are absent from this registry emit a WARNING (UNKNOWN_EXTENSION).\n * When omitted, custom constraints are silently skipped.\n */\n readonly extensionRegistry?: ExtensionRegistry;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/** Mutable accumulator threaded through the validation walk. */\ninterface ValidationContext {\n readonly diagnostics: ValidationDiagnostic[];\n readonly extensionRegistry: ExtensionRegistry | undefined;\n readonly typeRegistry: FormIR[\"typeRegistry\"];\n}\n\n// =============================================================================\n// DIAGNOSTIC FACTORIES\n// =============================================================================\n\nfunction addContradiction(\n ctx: ValidationContext,\n message: string,\n primary: Provenance,\n related: Provenance\n): void {\n ctx.diagnostics.push({\n code: \"CONTRADICTING_CONSTRAINTS\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [related],\n });\n}\n\nfunction addTypeMismatch(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"TYPE_MISMATCH\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addUnknownExtension(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"UNKNOWN_EXTENSION\",\n message,\n severity: \"warning\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addUnknownPathTarget(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"UNKNOWN_PATH_TARGET\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addConstraintBroadening(\n ctx: ValidationContext,\n message: string,\n primary: Provenance,\n related: Provenance\n): void {\n ctx.diagnostics.push({\n code: \"CONSTRAINT_BROADENING\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [related],\n });\n}\n\n// =============================================================================\n// CONSTRAINT NARROWING HELPERS\n// =============================================================================\n\n/** Extract the first numeric constraint with the given kind, if present. */\nfunction findNumeric(\n constraints: readonly ConstraintNode[],\n constraintKind: NumericConstraintNode[\"constraintKind\"]\n): NumericConstraintNode | undefined {\n return constraints.find((c): c is NumericConstraintNode => c.constraintKind === constraintKind);\n}\n\n/** Extract the first length constraint with the given kind, if present. */\nfunction findLength(\n constraints: readonly ConstraintNode[],\n constraintKind: LengthConstraintNode[\"constraintKind\"]\n): LengthConstraintNode | undefined {\n return constraints.find((c): c is LengthConstraintNode => c.constraintKind === constraintKind);\n}\n\n/** Extract all allowedMembers constraints. */\nfunction findAllowedMembers(\n constraints: readonly ConstraintNode[]\n): readonly EnumMemberConstraintNode[] {\n return constraints.filter(\n (c): c is EnumMemberConstraintNode => c.constraintKind === \"allowedMembers\"\n );\n}\n\nfunction findConstConstraints(\n constraints: readonly ConstraintNode[]\n): readonly Extract<ConstraintNode, { readonly constraintKind: \"const\" }>[] {\n return constraints.filter(\n (c): c is Extract<ConstraintNode, { readonly constraintKind: \"const\" }> =>\n c.constraintKind === \"const\"\n );\n}\n\nfunction jsonValueEquals(left: JsonValue, right: JsonValue): boolean {\n if (left === right) {\n return true;\n }\n\n if (Array.isArray(left) || Array.isArray(right)) {\n if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {\n return false;\n }\n\n return left.every((item, index) => jsonValueEquals(item, right[index] as JsonValue));\n }\n\n if (isJsonObject(left) || isJsonObject(right)) {\n if (!isJsonObject(left) || !isJsonObject(right)) {\n return false;\n }\n\n const leftKeys = Object.keys(left).sort();\n const rightKeys = Object.keys(right).sort();\n if (leftKeys.length !== rightKeys.length) {\n return false;\n }\n\n return leftKeys.every((key, index) => {\n const rightKey = rightKeys[index];\n if (rightKey !== key) {\n return false;\n }\n const leftValue = left[key];\n const rightValue = right[rightKey];\n return leftValue !== undefined && rightValue !== undefined && jsonValueEquals(leftValue, rightValue);\n });\n }\n\n return false;\n}\n\nfunction isJsonObject(value: JsonValue): value is Record<string, JsonValue> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\ntype OrderedBoundKind =\n | \"minimum\"\n | \"exclusiveMinimum\"\n | \"minLength\"\n | \"minItems\"\n | \"maximum\"\n | \"exclusiveMaximum\"\n | \"maxLength\"\n | \"maxItems\";\n\ntype OrderedBoundConstraint = Extract<\n ConstraintNode,\n { readonly constraintKind: OrderedBoundKind }\n>;\n\ntype OrderedBoundFamily =\n | \"numeric-lower\"\n | \"numeric-upper\"\n | \"minLength\"\n | \"minItems\"\n | \"maxLength\"\n | \"maxItems\";\n\nfunction isOrderedBoundConstraint(\n constraint: ConstraintNode\n): constraint is OrderedBoundConstraint {\n return (\n constraint.constraintKind === \"minimum\" ||\n constraint.constraintKind === \"exclusiveMinimum\" ||\n constraint.constraintKind === \"minLength\" ||\n constraint.constraintKind === \"minItems\" ||\n constraint.constraintKind === \"maximum\" ||\n constraint.constraintKind === \"exclusiveMaximum\" ||\n constraint.constraintKind === \"maxLength\" ||\n constraint.constraintKind === \"maxItems\"\n );\n}\n\nfunction pathKey(constraint: ConstraintNode): string {\n return constraint.path?.segments.join(\".\") ?? \"\";\n}\n\nfunction orderedBoundFamily(kind: OrderedBoundKind): OrderedBoundFamily {\n switch (kind) {\n case \"minimum\":\n case \"exclusiveMinimum\":\n return \"numeric-lower\";\n case \"maximum\":\n case \"exclusiveMaximum\":\n return \"numeric-upper\";\n case \"minLength\":\n return \"minLength\";\n case \"minItems\":\n return \"minItems\";\n case \"maxLength\":\n return \"maxLength\";\n case \"maxItems\":\n return \"maxItems\";\n default: {\n const _exhaustive: never = kind;\n return _exhaustive;\n }\n }\n}\n\nfunction isNumericLowerKind(kind: OrderedBoundKind): kind is \"minimum\" | \"exclusiveMinimum\" {\n return kind === \"minimum\" || kind === \"exclusiveMinimum\";\n}\n\nfunction isNumericUpperKind(kind: OrderedBoundKind): kind is \"maximum\" | \"exclusiveMaximum\" {\n return kind === \"maximum\" || kind === \"exclusiveMaximum\";\n}\n\nfunction describeConstraintTag(constraint: OrderedBoundConstraint): string {\n return `@${constraint.constraintKind}`;\n}\n\nfunction compareConstraintStrength(\n current: OrderedBoundConstraint,\n previous: OrderedBoundConstraint\n): number {\n const family = orderedBoundFamily(current.constraintKind);\n\n if (family === \"numeric-lower\") {\n if (\n !isNumericLowerKind(current.constraintKind) ||\n !isNumericLowerKind(previous.constraintKind)\n ) {\n throw new Error(\"numeric-lower family received non-numeric lower-bound constraint\");\n }\n\n if (current.value !== previous.value) {\n return current.value > previous.value ? 1 : -1;\n }\n if (current.constraintKind === \"exclusiveMinimum\" && previous.constraintKind === \"minimum\") {\n return 1;\n }\n if (current.constraintKind === \"minimum\" && previous.constraintKind === \"exclusiveMinimum\") {\n return -1;\n }\n return 0;\n }\n\n if (family === \"numeric-upper\") {\n if (\n !isNumericUpperKind(current.constraintKind) ||\n !isNumericUpperKind(previous.constraintKind)\n ) {\n throw new Error(\"numeric-upper family received non-numeric upper-bound constraint\");\n }\n\n if (current.value !== previous.value) {\n return current.value < previous.value ? 1 : -1;\n }\n if (current.constraintKind === \"exclusiveMaximum\" && previous.constraintKind === \"maximum\") {\n return 1;\n }\n if (current.constraintKind === \"maximum\" && previous.constraintKind === \"exclusiveMaximum\") {\n return -1;\n }\n return 0;\n }\n\n switch (family) {\n case \"minLength\":\n case \"minItems\":\n if (current.value === previous.value) {\n return 0;\n }\n return current.value > previous.value ? 1 : -1;\n case \"maxLength\":\n case \"maxItems\":\n if (current.value === previous.value) {\n return 0;\n }\n return current.value < previous.value ? 1 : -1;\n default: {\n const _exhaustive: never = family;\n return _exhaustive;\n }\n }\n}\n\nfunction checkConstraintBroadening(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const strongestByKey = new Map<string, OrderedBoundConstraint>();\n\n for (const constraint of constraints) {\n if (!isOrderedBoundConstraint(constraint)) {\n continue;\n }\n\n const key = `${orderedBoundFamily(constraint.constraintKind)}:${pathKey(constraint)}`;\n const previous = strongestByKey.get(key);\n if (previous === undefined) {\n strongestByKey.set(key, constraint);\n continue;\n }\n\n const strength = compareConstraintStrength(constraint, previous);\n if (strength < 0) {\n const displayFieldName = formatPathTargetFieldName(\n fieldName,\n constraint.path?.segments ?? []\n );\n addConstraintBroadening(\n ctx,\n `Field \"${displayFieldName}\": ${describeConstraintTag(constraint)} (${String(constraint.value)}) is broader than earlier ${describeConstraintTag(previous)} (${String(previous.value)}). Constraints can only narrow.`,\n constraint.provenance,\n previous.provenance\n );\n continue;\n }\n\n if (strength <= 0) {\n continue;\n }\n\n strongestByKey.set(key, constraint);\n }\n}\n\n// =============================================================================\n// CONTRADICTION DETECTION\n// =============================================================================\n\nfunction checkNumericContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const min = findNumeric(constraints, \"minimum\");\n const max = findNumeric(constraints, \"maximum\");\n const exMin = findNumeric(constraints, \"exclusiveMinimum\");\n const exMax = findNumeric(constraints, \"exclusiveMaximum\");\n\n // minimum > maximum\n if (min !== undefined && max !== undefined && min.value > max.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minimum (${String(min.value)}) is greater than maximum (${String(max.value)})`,\n min.provenance,\n max.provenance\n );\n }\n\n // exclusiveMinimum >= maximum\n if (exMin !== undefined && max !== undefined && exMin.value >= max.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": exclusiveMinimum (${String(exMin.value)}) is greater than or equal to maximum (${String(max.value)})`,\n exMin.provenance,\n max.provenance\n );\n }\n\n // minimum >= exclusiveMaximum\n if (min !== undefined && exMax !== undefined && min.value >= exMax.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minimum (${String(min.value)}) is greater than or equal to exclusiveMaximum (${String(exMax.value)})`,\n min.provenance,\n exMax.provenance\n );\n }\n\n // exclusiveMinimum >= exclusiveMaximum\n if (exMin !== undefined && exMax !== undefined && exMin.value >= exMax.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": exclusiveMinimum (${String(exMin.value)}) is greater than or equal to exclusiveMaximum (${String(exMax.value)})`,\n exMin.provenance,\n exMax.provenance\n );\n }\n}\n\nfunction checkLengthContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const minLen = findLength(constraints, \"minLength\");\n const maxLen = findLength(constraints, \"maxLength\");\n\n if (minLen !== undefined && maxLen !== undefined && minLen.value > maxLen.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minLength (${String(minLen.value)}) is greater than maxLength (${String(maxLen.value)})`,\n minLen.provenance,\n maxLen.provenance\n );\n }\n\n const minItems = findLength(constraints, \"minItems\");\n const maxItems = findLength(constraints, \"maxItems\");\n\n if (minItems !== undefined && maxItems !== undefined && minItems.value > maxItems.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minItems (${String(minItems.value)}) is greater than maxItems (${String(maxItems.value)})`,\n minItems.provenance,\n maxItems.provenance\n );\n }\n}\n\nfunction checkAllowedMembersContradiction(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const members = findAllowedMembers(constraints);\n if (members.length < 2) return;\n\n // Intersect all allowedMembers sets; if empty — contradiction\n const firstSet = new Set(members[0]?.members ?? []);\n for (let i = 1; i < members.length; i++) {\n const current = members[i];\n if (current === undefined) continue;\n for (const m of firstSet) {\n if (!current.members.includes(m)) {\n firstSet.delete(m);\n }\n }\n }\n\n if (firstSet.size === 0) {\n const first = members[0];\n const second = members[1];\n if (first !== undefined && second !== undefined) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": allowedMembers constraints have an empty intersection (no valid values remain)`,\n first.provenance,\n second.provenance\n );\n }\n }\n}\n\nfunction checkConstContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const constConstraints = findConstConstraints(constraints);\n if (constConstraints.length < 2) return;\n\n const first = constConstraints[0];\n if (first === undefined) return;\n\n for (let i = 1; i < constConstraints.length; i++) {\n const current = constConstraints[i];\n if (current === undefined) continue;\n if (jsonValueEquals(first.value, current.value)) {\n continue;\n }\n\n addContradiction(\n ctx,\n `Field \"${fieldName}\": conflicting @const constraints require both ${JSON.stringify(first.value)} and ${JSON.stringify(current.value)}`,\n first.provenance,\n current.provenance\n );\n }\n}\n\n// =============================================================================\n// TYPE APPLICABILITY CHECKS\n// =============================================================================\n\n/** Return a readable label for a type node for use in diagnostics. */\nfunction typeLabel(type: TypeNode): string {\n switch (type.kind) {\n case \"primitive\":\n return type.primitiveKind;\n case \"enum\":\n return \"enum\";\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n case \"record\":\n return \"record\";\n case \"union\":\n return \"union\";\n case \"reference\":\n return `reference(${type.name})`;\n case \"dynamic\":\n return `dynamic(${type.dynamicKind})`;\n case \"custom\":\n return `custom(${type.typeId})`;\n default: {\n const _exhaustive: never = type;\n return String(_exhaustive);\n }\n }\n}\n\ntype PathTargetResolution =\n | { readonly kind: \"resolved\"; readonly type: TypeNode }\n | { readonly kind: \"missing-property\"; readonly segment: string }\n | { readonly kind: \"unresolvable\"; readonly type: TypeNode };\n\nfunction dereferenceType(ctx: ValidationContext, type: TypeNode): TypeNode {\n let current = type;\n const seen = new Set<string>();\n\n while (current.kind === \"reference\") {\n if (seen.has(current.name)) {\n return current;\n }\n seen.add(current.name);\n\n const definition = ctx.typeRegistry[current.name];\n if (definition === undefined) {\n return current;\n }\n\n current = definition.type;\n }\n\n return current;\n}\n\nfunction resolvePathTargetType(\n ctx: ValidationContext,\n type: TypeNode,\n segments: readonly string[]\n): PathTargetResolution {\n const effectiveType = dereferenceType(ctx, type);\n\n if (segments.length === 0) {\n return { kind: \"resolved\", type: effectiveType };\n }\n\n if (effectiveType.kind === \"array\") {\n return resolvePathTargetType(ctx, effectiveType.items, segments);\n }\n\n if (effectiveType.kind === \"object\") {\n const [segment, ...rest] = segments;\n if (segment === undefined) {\n throw new Error(\"Invariant violation: object path traversal requires a segment\");\n }\n const property = effectiveType.properties.find((prop) => prop.name === segment);\n if (property === undefined) {\n return { kind: \"missing-property\", segment };\n }\n return resolvePathTargetType(ctx, property.type, rest);\n }\n\n return { kind: \"unresolvable\", type: effectiveType };\n}\n\nfunction formatPathTargetFieldName(fieldName: string, path: readonly string[]): string {\n return path.length === 0 ? fieldName : `${fieldName}.${path.join(\".\")}`;\n}\n\nfunction checkConstraintOnType(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraint: ConstraintNode\n): void {\n const effectiveType = dereferenceType(ctx, type);\n const isNumber = effectiveType.kind === \"primitive\" && effectiveType.primitiveKind === \"number\";\n const isString = effectiveType.kind === \"primitive\" && effectiveType.primitiveKind === \"string\";\n const isArray = effectiveType.kind === \"array\";\n const isEnum = effectiveType.kind === \"enum\";\n const arrayItemType =\n effectiveType.kind === \"array\" ? dereferenceType(ctx, effectiveType.items) : undefined;\n const isStringArray =\n arrayItemType?.kind === \"primitive\" && arrayItemType.primitiveKind === \"string\";\n\n const label = typeLabel(effectiveType);\n\n const ck = constraint.constraintKind;\n\n switch (ck) {\n case \"minimum\":\n case \"maximum\":\n case \"exclusiveMinimum\":\n case \"exclusiveMaximum\":\n case \"multipleOf\": {\n if (!isNumber) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on number fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"minLength\":\n case \"maxLength\":\n case \"pattern\": {\n if (!isString && !isStringArray) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on string fields or string array items, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"minItems\":\n case \"maxItems\":\n case \"uniqueItems\": {\n if (!isArray) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on array fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"allowedMembers\": {\n if (!isEnum) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"allowedMembers\" is only valid on enum fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"const\": {\n const isPrimitiveConstType =\n (effectiveType.kind === \"primitive\" &&\n [\"string\", \"number\", \"boolean\", \"null\"].includes(effectiveType.primitiveKind)) ||\n effectiveType.kind === \"enum\";\n\n if (!isPrimitiveConstType) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"const\" is only valid on primitive or enum fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n break;\n }\n\n if (effectiveType.kind === \"primitive\") {\n const valueType =\n constraint.value === null\n ? \"null\"\n : Array.isArray(constraint.value)\n ? \"array\"\n : typeof constraint.value;\n if (valueType !== effectiveType.primitiveKind) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": @const value type \"${valueType}\" is incompatible with field type \"${effectiveType.primitiveKind}\"`,\n constraint.provenance\n );\n }\n break;\n }\n\n const memberValues = effectiveType.members.map((member) => member.value);\n if (!memberValues.some((member) => jsonValueEquals(member, constraint.value))) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": @const value ${JSON.stringify(constraint.value)} is not one of the enum members`,\n constraint.provenance\n );\n }\n break;\n }\n case \"custom\": {\n checkCustomConstraint(ctx, fieldName, effectiveType, constraint);\n break;\n }\n default: {\n const _exhaustive: never = constraint;\n throw new Error(\n `Unhandled constraint kind: ${(_exhaustive as ConstraintNode).constraintKind}`\n );\n }\n }\n}\n\nfunction checkTypeApplicability(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraints: readonly ConstraintNode[]\n): void {\n for (const constraint of constraints) {\n // Path-targeted constraints (e.g., `@Minimum :value 0`) target a sub-field,\n // not the field itself. Resolve the target path and validate against the\n // resolved target type.\n if (constraint.path) {\n const resolution = resolvePathTargetType(ctx, type, constraint.path.segments);\n const targetFieldName = formatPathTargetFieldName(fieldName, constraint.path.segments);\n\n if (resolution.kind === \"missing-property\") {\n addUnknownPathTarget(\n ctx,\n `Field \"${targetFieldName}\": path-targeted constraint \"${constraint.constraintKind}\" references unknown path segment \"${resolution.segment}\"`,\n constraint.provenance\n );\n continue;\n }\n\n if (resolution.kind === \"unresolvable\") {\n addTypeMismatch(\n ctx,\n `Field \"${targetFieldName}\": path-targeted constraint \"${constraint.constraintKind}\" is invalid because type \"${typeLabel(resolution.type)}\" cannot be traversed`,\n constraint.provenance\n );\n continue;\n }\n\n checkConstraintOnType(ctx, targetFieldName, resolution.type, constraint);\n continue;\n }\n\n checkConstraintOnType(ctx, fieldName, type, constraint);\n }\n}\n\n/**\n * Check a custom constraint against the extension registry.\n *\n * When the registry is available:\n * - If the constraint ID is not found, emit UNKNOWN_EXTENSION warning\n * - If found and the registration has `applicableTypes`, verify the field's\n * type kind is in that list (emit TYPE_MISMATCH if not)\n * - If `applicableTypes` is null, the constraint applies to any type\n *\n * When no registry is available, custom constraints are silently skipped.\n */\nfunction checkCustomConstraint(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraint: ConstraintNode & { readonly constraintKind: \"custom\" }\n): void {\n if (ctx.extensionRegistry === undefined) return;\n\n const registration = ctx.extensionRegistry.findConstraint(constraint.constraintId);\n\n if (registration === undefined) {\n addUnknownExtension(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not registered in the extension registry`,\n constraint.provenance\n );\n return;\n }\n\n // If applicableTypes is null, the constraint applies to any type\n if (registration.applicableTypes === null) return;\n\n if (!registration.applicableTypes.includes(type.kind)) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not applicable to type \"${typeLabel(type)}\"`,\n constraint.provenance\n );\n }\n}\n\n// =============================================================================\n// FIELD VALIDATION\n// =============================================================================\n\nfunction validateFieldNode(ctx: ValidationContext, field: FieldNode): void {\n validateConstraints(ctx, field.name, field.type, field.constraints);\n\n // Recurse into object type properties\n if (field.type.kind === \"object\") {\n for (const prop of field.type.properties) {\n validateObjectProperty(ctx, field.name, prop);\n }\n }\n}\n\nfunction validateObjectProperty(\n ctx: ValidationContext,\n parentName: string,\n prop: ObjectProperty\n): void {\n const qualifiedName = `${parentName}.${prop.name}`;\n validateConstraints(ctx, qualifiedName, prop.type, prop.constraints);\n\n // Recurse further if this property is also an object\n if (prop.type.kind === \"object\") {\n for (const nestedProp of prop.type.properties) {\n validateObjectProperty(ctx, qualifiedName, nestedProp);\n }\n }\n}\n\nfunction validateConstraints(\n ctx: ValidationContext,\n name: string,\n type: TypeNode,\n constraints: readonly ConstraintNode[]\n): void {\n checkNumericContradictions(ctx, name, constraints);\n checkLengthContradictions(ctx, name, constraints);\n checkAllowedMembersContradiction(ctx, name, constraints);\n checkConstContradictions(ctx, name, constraints);\n checkConstraintBroadening(ctx, name, constraints);\n checkTypeApplicability(ctx, name, type, constraints);\n}\n\n// =============================================================================\n// RECURSIVE ELEMENT WALK\n// =============================================================================\n\nfunction validateElement(ctx: ValidationContext, element: FormIRElement): void {\n switch (element.kind) {\n case \"field\":\n validateFieldNode(ctx, element);\n break;\n case \"group\":\n for (const child of element.elements) {\n validateElement(ctx, child);\n }\n break;\n case \"conditional\":\n for (const child of element.elements) {\n validateElement(ctx, child);\n }\n break;\n default: {\n const _exhaustive: never = element;\n throw new Error(`Unhandled element kind: ${(_exhaustive as FormIRElement).kind}`);\n }\n }\n}\n\n// =============================================================================\n// MAIN EXPORT\n// =============================================================================\n\n/**\n * Validate all constraints in a {@link FormIR}.\n *\n * Checks for:\n * - Contradictions between paired constraints (e.g. `minimum > maximum`)\n * - Type applicability violations (e.g. `minLength` on a number field)\n * - Custom constraint type applicability (via extension registry)\n * - Unknown extension constraints (when `extensionRegistry` is provided)\n *\n * @param ir - The form IR to validate.\n * @param options - Optional configuration.\n * @returns A {@link ValidationResult} with diagnostics and a `valid` flag.\n */\nexport function validateIR(ir: FormIR, options?: ValidateIROptions): ValidationResult {\n const ctx: ValidationContext = {\n diagnostics: [],\n extensionRegistry: options?.extensionRegistry,\n typeRegistry: ir.typeRegistry,\n };\n\n for (const element of ir.elements) {\n validateElement(ctx, element);\n }\n\n return {\n diagnostics: ctx.diagnostics,\n valid: ctx.diagnostics.every((d) => d.severity !== \"error\"),\n };\n}\n","/**\n * Extension registry for resolving custom types, constraints, and annotations\n * during JSON Schema generation and IR validation.\n *\n * The registry is created from a list of {@link ExtensionDefinition} objects\n * and provides O(1) lookup by fully-qualified ID (extensionId + \"/\" + name).\n *\n * @packageDocumentation\n */\n\nimport type {\n ExtensionDefinition,\n CustomTypeRegistration,\n CustomConstraintRegistration,\n CustomAnnotationRegistration,\n} from \"@formspec/core\";\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * A registry of extensions that provides lookup by fully-qualified ID.\n *\n * Type IDs follow the format: `<extensionId>/<typeName>`\n * Constraint IDs follow the format: `<extensionId>/<constraintName>`\n * Annotation IDs follow the format: `<extensionId>/<annotationName>`\n */\nexport interface ExtensionRegistry {\n /** The extensions registered in this registry (in registration order). */\n readonly extensions: readonly ExtensionDefinition[];\n\n /**\n * Look up a custom type registration by its fully-qualified type ID.\n *\n * @param typeId - The fully-qualified type ID (e.g., \"x-stripe/monetary/Decimal\").\n * @returns The registration if found, otherwise `undefined`.\n */\n findType(typeId: string): CustomTypeRegistration | undefined;\n\n /**\n * Look up a custom constraint registration by its fully-qualified constraint ID.\n *\n * @param constraintId - The fully-qualified constraint ID.\n * @returns The registration if found, otherwise `undefined`.\n */\n findConstraint(constraintId: string): CustomConstraintRegistration | undefined;\n\n /**\n * Look up a custom annotation registration by its fully-qualified annotation ID.\n *\n * @param annotationId - The fully-qualified annotation ID.\n * @returns The registration if found, otherwise `undefined`.\n */\n findAnnotation(annotationId: string): CustomAnnotationRegistration | undefined;\n}\n\n// =============================================================================\n// IMPLEMENTATION\n// =============================================================================\n\n/**\n * Creates an extension registry from a list of extension definitions.\n *\n * The registry indexes all types, constraints, and annotations by their\n * fully-qualified IDs (`<extensionId>/<name>`) for O(1) lookup during\n * generation and validation.\n *\n * @param extensions - The extension definitions to register.\n * @returns An {@link ExtensionRegistry} instance.\n * @throws If duplicate type/constraint/annotation IDs are detected across extensions.\n */\nexport function createExtensionRegistry(\n extensions: readonly ExtensionDefinition[]\n): ExtensionRegistry {\n const typeMap = new Map<string, CustomTypeRegistration>();\n const constraintMap = new Map<string, CustomConstraintRegistration>();\n const annotationMap = new Map<string, CustomAnnotationRegistration>();\n\n for (const ext of extensions) {\n if (ext.types !== undefined) {\n for (const type of ext.types) {\n const qualifiedId = `${ext.extensionId}/${type.typeName}`;\n if (typeMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom type ID: \"${qualifiedId}\"`);\n }\n typeMap.set(qualifiedId, type);\n }\n }\n\n if (ext.constraints !== undefined) {\n for (const constraint of ext.constraints) {\n const qualifiedId = `${ext.extensionId}/${constraint.constraintName}`;\n if (constraintMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom constraint ID: \"${qualifiedId}\"`);\n }\n constraintMap.set(qualifiedId, constraint);\n }\n }\n\n if (ext.annotations !== undefined) {\n for (const annotation of ext.annotations) {\n const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;\n if (annotationMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom annotation ID: \"${qualifiedId}\"`);\n }\n annotationMap.set(qualifiedId, annotation);\n }\n }\n }\n\n return {\n extensions,\n findType: (typeId: string) => typeMap.get(typeId),\n findConstraint: (constraintId: string) => constraintMap.get(constraintId),\n findAnnotation: (annotationId: string) => annotationMap.get(annotationId),\n };\n}\n","/**\n * Method schema generator.\n *\n * Generates schemas for method parameters and return types, routing through\n * the canonical IR pipeline (TypeScript type → TypeNode → JSON Schema 2020-12).\n */\n\nimport type * as ts from \"typescript\";\nimport type { MethodInfo, ParameterInfo } from \"../analyzer/class-analyzer.js\";\nimport { resolveTypeNode } from \"../analyzer/class-analyzer.js\";\nimport type { TypeDefinition } from \"@formspec/core\";\nimport { generateJsonSchemaFromIR, type JsonSchema2020 } from \"../json-schema/ir-generator.js\";\nimport { IR_VERSION } from \"@formspec/core\";\n\n/**\n * Runtime-loaded FormSpec schemas, compatible with the CLI's FormSpecSchemas type.\n */\nexport interface LoadedFormSpecSchemas {\n /** The FormSpec export name */\n name: string;\n /** Generated JSON Schema */\n jsonSchema: unknown;\n /** Generated UI Schema (FormSpec/JSON Forms) */\n uiSchema: unknown;\n}\n\n/**\n * Generated schemas for a method.\n */\nexport interface MethodSchemas {\n /** Method name */\n name: string;\n /** Parameter schemas (from FormSpec or static analysis) */\n params: MethodParamsSchemas | null;\n /** Return type schema */\n returnType: JsonSchema2020;\n}\n\n/**\n * Parameter schemas for a method.\n */\nexport interface MethodParamsSchemas {\n /** JSON Schema for parameters */\n jsonSchema: JsonSchema2020;\n /** UI Schema / FormSpec for parameters (if available) */\n uiSchema: object | null;\n /** Name of the FormSpec export used (if any) */\n formSpecExport: string | null;\n}\n\n/**\n * Resolves a TypeScript type to a JSON Schema 2020-12 sub-schema via the IR.\n */\nfunction typeToJsonSchema(type: ts.Type, checker: ts.TypeChecker): JsonSchema2020 {\n const typeRegistry: Record<string, TypeDefinition> = {};\n const visiting = new Set<ts.Type>();\n const typeNode = resolveTypeNode(type, checker, \"\", typeRegistry, visiting);\n\n const fieldProvenance = { surface: \"tsdoc\" as const, file: \"\", line: 0, column: 0 };\n\n // Build a minimal FormIR wrapping a single field to reuse the IR generator.\n const ir = {\n kind: \"form-ir\" as const,\n irVersion: IR_VERSION,\n elements: [\n {\n kind: \"field\" as const,\n name: \"__result\",\n type: typeNode,\n required: true,\n constraints: [],\n annotations: [],\n provenance: fieldProvenance,\n },\n ],\n typeRegistry,\n provenance: fieldProvenance,\n };\n\n const schema = generateJsonSchemaFromIR(ir);\n // Extract the single field's sub-schema from the wrapper.\n const fieldSchema = schema.properties?.[\"__result\"];\n if (fieldSchema) {\n // If there are $defs, attach them to the field schema for completeness.\n if (schema.$defs && Object.keys(schema.$defs).length > 0) {\n return { ...fieldSchema, $defs: schema.$defs };\n }\n return fieldSchema;\n }\n return { type: \"object\" };\n}\n\n/**\n * Generates schemas for a method's parameters and return type.\n *\n * If a parameter references a FormSpec via `InferSchema<typeof X>`,\n * the schemas are taken from the loaded FormSpec at runtime.\n * Otherwise, schemas are generated from static type analysis via the IR.\n *\n * @param method - The method information from static analysis\n * @param checker - TypeScript type checker\n * @param loadedFormSpecs - Map of FormSpec export names to their schemas\n * @returns Generated method schemas\n */\nexport function generateMethodSchemas(\n method: MethodInfo,\n checker: ts.TypeChecker,\n loadedFormSpecs: Map<string, LoadedFormSpecSchemas>\n): MethodSchemas {\n // Generate return type schema via IR\n const returnType = typeToJsonSchema(method.returnType, checker);\n\n // Handle parameters\n const params = generateParamsSchemas(method.parameters, checker, loadedFormSpecs);\n\n return {\n name: method.name,\n params,\n returnType,\n };\n}\n\n/**\n * Generates schemas for method parameters.\n */\nfunction generateParamsSchemas(\n parameters: ParameterInfo[],\n checker: ts.TypeChecker,\n loadedFormSpecs: Map<string, LoadedFormSpecSchemas>\n): MethodParamsSchemas | null {\n if (parameters.length === 0) {\n return null;\n }\n\n // Check if any parameter uses InferSchema<typeof X>\n for (const param of parameters) {\n if (param.formSpecExportName) {\n const formSpec = loadedFormSpecs.get(param.formSpecExportName);\n if (formSpec) {\n return {\n jsonSchema: formSpec.jsonSchema as JsonSchema2020,\n uiSchema: formSpec.uiSchema as object | null,\n formSpecExport: param.formSpecExportName,\n };\n }\n\n // FormSpec not found - fall back to static analysis\n console.warn(\n `Warning: FormSpec export \"${param.formSpecExportName}\" not found, using static analysis`\n );\n }\n }\n\n // Generate from static type analysis via IR\n if (parameters.length === 1 && parameters[0]) {\n const param = parameters[0];\n const jsonSchema = typeToJsonSchema(param.type, checker);\n return {\n jsonSchema,\n uiSchema: null,\n formSpecExport: null,\n };\n }\n\n // Multiple parameters - create object schema\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n for (const param of parameters) {\n const paramSchema = typeToJsonSchema(param.type, checker);\n properties[param.name] = paramSchema;\n if (!param.optional) {\n required.push(param.name);\n }\n }\n\n return {\n jsonSchema: {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n },\n uiSchema: null,\n formSpecExport: null,\n };\n}\n\n/**\n * Collects all FormSpec export names referenced by methods.\n *\n * Use this to determine which exports to load at runtime.\n *\n * @param methods - Array of method infos\n * @returns Set of FormSpec export names\n */\nexport function collectFormSpecReferences(methods: MethodInfo[]): Set<string> {\n const references = new Set<string>();\n\n for (const method of methods) {\n for (const param of method.parameters) {\n if (param.formSpecExportName) {\n references.add(param.formSpecExportName);\n }\n }\n }\n\n return references;\n}\n"],"mappings":"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","names":["import_core","ts","ts","ts","import_core","text","provenance","path","parsed","members","isBooleanUnion","import_zod","path","import_core"]}
1
+ {"version":3,"sources":["../src/internals.ts","../src/canonicalize/chain-dsl-canonicalizer.ts","../src/canonicalize/tsdoc-canonicalizer.ts","../src/analyzer/program.ts","../src/analyzer/class-analyzer.ts","../src/analyzer/jsdoc-constraints.ts","../src/analyzer/tsdoc-parser.ts","../src/analyzer/json-utils.ts","../src/json-schema/ir-generator.ts","../src/ui-schema/schema.ts","../src/ui-schema/ir-generator.ts","../src/generators/class-schema.ts","../src/validate/constraint-validator.ts","../src/extensions/registry.ts","../src/generators/method-schema.ts"],"sourcesContent":["/**\n * Internal APIs for `@formspec/build`.\n *\n * This entry point exposes low-level analyzer and generator functions\n * used by `@formspec/cli`. These are NOT part of the public API and\n * may change without notice between versions.\n *\n * @remarks\n * Prefer the high-level functions from `@formspec/build` (e.g.,\n * `generateSchemasFromClass`, `buildFormSchemas`) for most use cases.\n *\n * @packageDocumentation\n */\n\n// Canonicalize: DSL → FormIR\nexport { canonicalizeChainDSL } from \"./canonicalize/index.js\";\n\n// Canonicalization: TSDoc → FormIR\nexport { canonicalizeTSDoc } from \"./canonicalize/index.js\";\nexport type { TSDocSource } from \"./canonicalize/index.js\";\n\n// Analyzer: program context and type lookup\nexport {\n createProgramContext,\n findClassByName,\n findInterfaceByName,\n findTypeAliasByName,\n} from \"./analyzer/program.js\";\n\n// Analyzer: IR analysis (class, interface, type alias)\nexport {\n analyzeClassToIR,\n analyzeInterfaceToIR,\n analyzeTypeAliasToIR,\n} from \"./analyzer/class-analyzer.js\";\nexport type {\n IRClassAnalysis,\n FieldLayoutMetadata,\n AnalyzeTypeAliasToIRResult,\n} from \"./analyzer/class-analyzer.js\";\n\n// Generators: class schema (now routes through IR)\nexport { generateClassSchemas } from \"./generators/class-schema.js\";\n\n// JSON Schema 2020-12: IR-based generator\nexport { generateJsonSchemaFromIR } from \"./json-schema/ir-generator.js\";\nexport type { JsonSchema2020 } from \"./json-schema/ir-generator.js\";\n\n// UI Schema: IR-based generator\nexport { generateUiSchemaFromIR } from \"./ui-schema/ir-generator.js\";\n\n// Validate: constraint validation and contradiction detection\nexport { validateIR } from \"./validate/index.js\";\nexport type {\n ValidationDiagnostic,\n ValidationResult,\n ValidateIROptions,\n} from \"./validate/index.js\";\n\n// Extensions: extension registry for custom types, constraints, annotations\nexport { createExtensionRegistry } from \"./extensions/index.js\";\nexport type { ExtensionRegistry } from \"./extensions/index.js\";\n\n// Generators: method schema\nexport { generateMethodSchemas, collectFormSpecReferences } from \"./generators/method-schema.js\";\nexport type { LoadedFormSpecSchemas, MethodSchemas } from \"./generators/method-schema.js\";\n","/**\n * Canonicalizer that translates chain DSL `FormSpec` objects into the\n * canonical FormIR intermediate representation.\n *\n * This module maps the runtime objects produced by `@formspec/dsl` builder\n * functions (`field.*`, `group`, `when`, `formspec`) into the IR that all\n * downstream phases (validation, JSON Schema generation, UI Schema generation)\n * consume.\n */\n\nimport type {\n // Source types (chain DSL)\n AnyField,\n ArrayField,\n BooleanField,\n Conditional,\n DynamicEnumField,\n DynamicSchemaField,\n EnumOptionValue,\n FormElement,\n FormSpec,\n Group,\n NumberField,\n ObjectField,\n StaticEnumField,\n TextField,\n // IR types\n JsonValue,\n AnnotationNode,\n ArrayTypeNode,\n ConstraintNode,\n ConditionalLayoutNode,\n DisplayNameAnnotationNode,\n DynamicTypeNode,\n EnumMember,\n EnumTypeNode,\n FieldNode,\n FormIR,\n FormIRElement,\n GroupLayoutNode,\n LengthConstraintNode,\n NumericConstraintNode,\n ObjectProperty,\n PatternConstraintNode,\n ObjectTypeNode,\n PlaceholderAnnotationNode,\n PrimitiveTypeNode,\n Provenance,\n TypeNode,\n} from \"@formspec/core\";\nimport { IR_VERSION } from \"@formspec/core\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Default provenance for chain DSL nodes (no source location available). */\nconst CHAIN_DSL_PROVENANCE: Provenance = {\n surface: \"chain-dsl\",\n file: \"\",\n line: 0,\n column: 0,\n} as const;\n\n// =============================================================================\n// TYPE GUARDS\n// =============================================================================\n\nfunction isGroup(el: FormElement): el is Group<readonly FormElement[]> {\n return el._type === \"group\";\n}\n\nfunction isConditional(\n el: FormElement\n): el is Conditional<string, unknown, readonly FormElement[]> {\n return el._type === \"conditional\";\n}\n\nfunction isField(el: FormElement): el is AnyField {\n return el._type === \"field\";\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Translates a chain DSL `FormSpec` into the canonical `FormIR`.\n *\n * @param form - A form specification created via `formspec(...)` from `@formspec/dsl`\n * @returns The canonical intermediate representation\n */\nexport function canonicalizeChainDSL(form: FormSpec<readonly FormElement[]>): FormIR {\n return {\n kind: \"form-ir\",\n irVersion: IR_VERSION,\n elements: canonicalizeElements(form.elements),\n typeRegistry: {},\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n// =============================================================================\n// ELEMENT CANONICALIZATION\n// =============================================================================\n\n/**\n * Canonicalizes an array of chain DSL form elements into IR elements.\n */\nfunction canonicalizeElements(elements: readonly FormElement[]): FormIRElement[] {\n return elements.map(canonicalizeElement);\n}\n\n/**\n * Dispatches a single form element to its specific canonicalization function.\n */\nfunction canonicalizeElement(element: FormElement): FormIRElement {\n if (isField(element)) {\n return canonicalizeField(element);\n }\n if (isGroup(element)) {\n return canonicalizeGroup(element);\n }\n if (isConditional(element)) {\n return canonicalizeConditional(element);\n }\n const _exhaustive: never = element;\n throw new Error(`Unknown element type: ${JSON.stringify(_exhaustive)}`);\n}\n\n// =============================================================================\n// FIELD CANONICALIZATION\n// =============================================================================\n\n/**\n * Dispatches a field element to its type-specific canonicalization function.\n */\nfunction canonicalizeField(field: AnyField): FieldNode {\n switch (field._field) {\n case \"text\":\n return canonicalizeTextField(field);\n case \"number\":\n return canonicalizeNumberField(field);\n case \"boolean\":\n return canonicalizeBooleanField(field);\n case \"enum\":\n return canonicalizeStaticEnumField(field);\n case \"dynamic_enum\":\n return canonicalizeDynamicEnumField(field);\n case \"dynamic_schema\":\n return canonicalizeDynamicSchemaField(field);\n case \"array\":\n return canonicalizeArrayField(field);\n case \"object\":\n return canonicalizeObjectField(field);\n default: {\n const _exhaustive: never = field;\n throw new Error(`Unknown field type: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\n// =============================================================================\n// SPECIFIC FIELD TYPE CANONICALIZERS\n// =============================================================================\n\nfunction canonicalizeTextField(field: TextField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"string\" };\n const constraints: ConstraintNode[] = [];\n\n if (field.minLength !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minLength\",\n value: field.minLength,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.maxLength !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maxLength\",\n value: field.maxLength,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.pattern !== undefined) {\n const c: PatternConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"pattern\",\n pattern: field.pattern,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label, field.placeholder),\n constraints\n );\n}\n\nfunction canonicalizeNumberField(field: NumberField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"number\" };\n const constraints: ConstraintNode[] = [];\n\n if (field.min !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minimum\",\n value: field.min,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.max !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maximum\",\n value: field.max,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n if (field.multipleOf !== undefined) {\n const c: NumericConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"multipleOf\",\n value: field.multipleOf,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label),\n constraints\n );\n}\n\nfunction canonicalizeBooleanField(field: BooleanField<string>): FieldNode {\n const type: PrimitiveTypeNode = { kind: \"primitive\", primitiveKind: \"boolean\" };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeStaticEnumField(\n field: StaticEnumField<string, readonly EnumOptionValue[]>\n): FieldNode {\n const members: EnumMember[] = field.options.map((opt) => {\n if (typeof opt === \"string\") {\n return { value: opt } satisfies EnumMember;\n }\n // Object option with id/label\n return { value: opt.id, displayName: opt.label } satisfies EnumMember;\n });\n\n const type: EnumTypeNode = { kind: \"enum\", members };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeDynamicEnumField(field: DynamicEnumField<string, string>): FieldNode {\n const type: DynamicTypeNode = {\n kind: \"dynamic\",\n dynamicKind: \"enum\",\n sourceKey: field.source,\n parameterFields: field.params ? [...field.params] : [],\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeDynamicSchemaField(field: DynamicSchemaField<string>): FieldNode {\n const type: DynamicTypeNode = {\n kind: \"dynamic\",\n dynamicKind: \"schema\",\n sourceKey: field.schemaSource,\n parameterFields: [],\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\nfunction canonicalizeArrayField(field: ArrayField<string, readonly FormElement[]>): FieldNode {\n // Array items form an object type from the sub-elements\n const itemProperties = buildObjectProperties(field.items);\n const itemsType: ObjectTypeNode = {\n kind: \"object\",\n properties: itemProperties,\n additionalProperties: true,\n };\n const type: ArrayTypeNode = { kind: \"array\", items: itemsType };\n\n const constraints: ConstraintNode[] = [];\n if (field.minItems !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"minItems\",\n value: field.minItems,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n if (field.maxItems !== undefined) {\n const c: LengthConstraintNode = {\n kind: \"constraint\",\n constraintKind: \"maxItems\",\n value: field.maxItems,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n constraints.push(c);\n }\n\n return buildFieldNode(\n field.name,\n type,\n field.required,\n buildAnnotations(field.label),\n constraints\n );\n}\n\nfunction canonicalizeObjectField(field: ObjectField<string, readonly FormElement[]>): FieldNode {\n const properties = buildObjectProperties(field.properties);\n const type: ObjectTypeNode = {\n kind: \"object\",\n properties,\n additionalProperties: true,\n };\n return buildFieldNode(field.name, type, field.required, buildAnnotations(field.label));\n}\n\n// =============================================================================\n// LAYOUT CANONICALIZATION\n// =============================================================================\n\nfunction canonicalizeGroup(g: Group<readonly FormElement[]>): GroupLayoutNode {\n return {\n kind: \"group\",\n label: g.label,\n elements: canonicalizeElements(g.elements),\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\nfunction canonicalizeConditional(\n c: Conditional<string, unknown, readonly FormElement[]>\n): ConditionalLayoutNode {\n return {\n kind: \"conditional\",\n fieldName: c.field,\n // Conditional values from the chain DSL are JSON-serializable primitives\n // (strings, numbers, booleans) produced by the `is()` predicate helper.\n value: assertJsonValue(c.value),\n elements: canonicalizeElements(c.elements),\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/**\n * Validates that a value is JSON-serializable (`JsonValue`).\n * The chain DSL's `is()` helper constrains conditional values to\n * JSON-compatible primitives, but the TypeScript type is `unknown`.\n * This runtime guard replaces an `as` cast with a validated assertion.\n */\nfunction assertJsonValue(v: unknown): JsonValue {\n if (v === null || typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\") {\n return v;\n }\n if (Array.isArray(v)) {\n return v.map(assertJsonValue);\n }\n if (typeof v === \"object\") {\n const result: Record<string, JsonValue> = {};\n for (const [key, val] of Object.entries(v)) {\n result[key] = assertJsonValue(val);\n }\n return result;\n }\n // Remaining types (function, symbol, bigint, undefined) are not JSON-serializable\n throw new TypeError(`Conditional value is not a valid JsonValue: ${typeof v}`);\n}\n\n/**\n * Builds a FieldNode from common field properties.\n */\nfunction buildFieldNode(\n name: string,\n type: TypeNode,\n required: boolean | undefined,\n annotations: AnnotationNode[],\n constraints: ConstraintNode[] = []\n): FieldNode {\n return {\n kind: \"field\",\n name,\n type,\n required: required === true,\n constraints,\n annotations,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n}\n\n/**\n * Builds annotation nodes from optional label and placeholder values.\n */\nfunction buildAnnotations(label?: string, placeholder?: string): AnnotationNode[] {\n const annotations: AnnotationNode[] = [];\n\n if (label !== undefined) {\n const a: DisplayNameAnnotationNode = {\n kind: \"annotation\",\n annotationKind: \"displayName\",\n value: label,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n annotations.push(a);\n }\n\n if (placeholder !== undefined) {\n const a: PlaceholderAnnotationNode = {\n kind: \"annotation\",\n annotationKind: \"placeholder\",\n value: placeholder,\n provenance: CHAIN_DSL_PROVENANCE,\n };\n annotations.push(a);\n }\n\n return annotations;\n}\n\n/**\n * Converts an array of form elements into ObjectProperty nodes.\n * Used for ObjectField properties and ArrayField items.\n *\n * Only field elements produce properties; groups and conditionals within\n * an object/array context are recursively flattened to extract their fields.\n *\n * Fields inside conditional branches are always marked `optional: true`\n * because their presence in the data depends on the condition being met.\n * This matches the DSL's type inference behavior where conditional fields\n * produce optional properties in `InferFormSchema`.\n *\n * @param elements - The form elements to convert\n * @param insideConditional - Whether these elements are inside a conditional branch\n */\nfunction buildObjectProperties(\n elements: readonly FormElement[],\n insideConditional = false\n): ObjectProperty[] {\n const properties: ObjectProperty[] = [];\n\n for (const el of elements) {\n if (isField(el)) {\n const fieldNode = canonicalizeField(el);\n properties.push({\n name: fieldNode.name,\n type: fieldNode.type,\n // Fields inside a conditional branch are always optional in the\n // data schema, regardless of their `required` flag — the condition\n // may not be met, so the field may be absent.\n optional: insideConditional || !fieldNode.required,\n constraints: fieldNode.constraints,\n annotations: fieldNode.annotations,\n provenance: CHAIN_DSL_PROVENANCE,\n });\n } else if (isGroup(el)) {\n // Groups inside object/array items contribute their fields by flattening.\n // Groups do not affect optionality — pass through the current state.\n properties.push(...buildObjectProperties(el.elements, insideConditional));\n } else if (isConditional(el)) {\n // Conditionals inside object/array items contribute their fields by\n // flattening, but all fields inside are forced optional.\n properties.push(...buildObjectProperties(el.elements, true));\n }\n }\n\n return properties;\n}\n","/**\n * TSDoc canonicalizer — assembles an {@link IRClassAnalysis} into a canonical\n * {@link FormIR}, applying layout metadata from `@Group` and `@ShowWhen`\n * TSDoc tags.\n *\n * The analysis functions in `class-analyzer.ts` produce `FieldNode[]`,\n * `fieldLayouts`, and `typeRegistry` directly. This canonicalizer uses\n * the layout metadata to wrap fields in `GroupLayoutNode` and\n * `ConditionalLayoutNode` elements.\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n GroupLayoutNode,\n ConditionalLayoutNode,\n Provenance,\n} from \"@formspec/core\";\nimport { IR_VERSION } from \"@formspec/core\";\nimport type { IRClassAnalysis, FieldLayoutMetadata } from \"../analyzer/class-analyzer.js\";\n\n/**\n * Source-level metadata for provenance tracking.\n */\nexport interface TSDocSource {\n /** Absolute path to the source file. */\n readonly file: string;\n}\n\n/**\n * Wraps an {@link IRClassAnalysis} (from `analyzeClassToIR`,\n * `analyzeInterfaceToIR`, or `analyzeTypeAliasToIR`) into a canonical\n * {@link FormIR}.\n *\n * Fields with `@Group` TSDoc tags are grouped into `GroupLayoutNode` elements.\n * Fields with `@ShowWhen` TSDoc tags are wrapped in `ConditionalLayoutNode` elements.\n * When both are present, the conditional wraps the field inside the group.\n *\n * @param analysis - IR analysis result (fields are already FieldNode[])\n * @param source - Optional source file metadata for provenance\n * @returns The canonical FormIR\n */\nexport function canonicalizeTSDoc(analysis: IRClassAnalysis, source?: TSDocSource): FormIR {\n const file = source?.file ?? \"\";\n\n const provenance: Provenance = {\n surface: \"tsdoc\",\n file,\n line: 1,\n column: 0,\n };\n\n const elements = assembleElements(analysis.fields, analysis.fieldLayouts, provenance);\n\n return {\n kind: \"form-ir\",\n irVersion: IR_VERSION,\n elements,\n typeRegistry: analysis.typeRegistry,\n ...(analysis.annotations !== undefined &&\n analysis.annotations.length > 0 && { annotations: analysis.annotations }),\n provenance,\n };\n}\n\n/**\n * Assembles flat fields and their layout metadata into a tree of\n * `FormIRElement[]` with groups and conditionals.\n *\n * Fields are processed in order. Consecutive fields with the same\n * `@Group` label are collected into a single `GroupLayoutNode`.\n * Fields with `@ShowWhen` are wrapped in `ConditionalLayoutNode`.\n */\nfunction assembleElements(\n fields: readonly FieldNode[],\n layouts: readonly FieldLayoutMetadata[],\n provenance: Provenance\n): readonly FormIRElement[] {\n const elements: FormIRElement[] = [];\n\n // Group consecutive fields with the same group label together.\n // We use an ordered map to preserve insertion order of groups.\n const groupMap = new Map<string, FormIRElement[]>();\n const topLevelOrder: (\n | { type: \"group\"; label: string }\n | { type: \"element\"; element: FormIRElement }\n )[] = [];\n\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n const layout = layouts[i];\n if (!field || !layout) continue;\n\n // Wrap in conditional if @ShowWhen is present\n const element = wrapInConditional(field, layout, provenance);\n\n if (layout.groupLabel !== undefined) {\n const label = layout.groupLabel;\n let groupElements = groupMap.get(label);\n if (!groupElements) {\n groupElements = [];\n groupMap.set(label, groupElements);\n topLevelOrder.push({ type: \"group\", label });\n }\n groupElements.push(element);\n } else {\n topLevelOrder.push({ type: \"element\", element });\n }\n }\n\n // Assemble the final element array in order\n for (const entry of topLevelOrder) {\n if (entry.type === \"group\") {\n const groupElements = groupMap.get(entry.label);\n if (groupElements) {\n const groupNode: GroupLayoutNode = {\n kind: \"group\",\n label: entry.label,\n elements: groupElements,\n provenance,\n };\n elements.push(groupNode);\n // Clear so duplicate group labels in topLevelOrder don't re-emit\n groupMap.delete(entry.label);\n }\n } else {\n elements.push(entry.element);\n }\n }\n\n return elements;\n}\n\n/**\n * Wraps a field in a `ConditionalLayoutNode` if the layout has `showWhen` metadata.\n */\nfunction wrapInConditional(\n field: FieldNode,\n layout: FieldLayoutMetadata,\n provenance: Provenance\n): FormIRElement {\n if (layout.showWhen === undefined) {\n return field;\n }\n\n const conditional: ConditionalLayoutNode = {\n kind: \"conditional\",\n fieldName: layout.showWhen.field,\n value: layout.showWhen.value,\n elements: [field],\n provenance,\n };\n\n return conditional;\n}\n","/**\n * TypeScript program setup for static analysis.\n *\n * Creates a TypeScript program with type checker from a source file,\n * using the project's tsconfig.json for compiler options.\n */\n\nimport * as ts from \"typescript\";\nimport * as path from \"node:path\";\n\n/**\n * Result of creating a TypeScript program for analysis.\n */\nexport interface ProgramContext {\n /** The TypeScript program */\n program: ts.Program;\n /** Type checker for resolving types */\n checker: ts.TypeChecker;\n /** The source file being analyzed */\n sourceFile: ts.SourceFile;\n}\n\n/**\n * Creates a TypeScript program for analyzing a source file.\n *\n * Looks for tsconfig.json in the file's directory or parent directories.\n * Falls back to default compiler options if no config is found.\n *\n * @param filePath - Absolute path to the TypeScript source file\n * @returns Program context with checker and source file\n */\nexport function createProgramContext(filePath: string): ProgramContext {\n const absolutePath = path.resolve(filePath);\n const fileDir = path.dirname(absolutePath);\n\n // Find tsconfig.json - using ts.sys.fileExists which has `this: void` requirement\n const configPath = ts.findConfigFile(fileDir, ts.sys.fileExists.bind(ts.sys), \"tsconfig.json\");\n\n let compilerOptions: ts.CompilerOptions;\n let fileNames: string[];\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile.bind(ts.sys));\n if (configFile.error) {\n throw new Error(\n `Error reading tsconfig.json: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, \"\\n\")}`\n );\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path.dirname(configPath)\n );\n\n if (parsed.errors.length > 0) {\n const errorMessages = parsed.errors\n .map((e) => ts.flattenDiagnosticMessageText(e.messageText, \"\\n\"))\n .join(\"\\n\");\n throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);\n }\n\n compilerOptions = parsed.options;\n // Include the target file in the program\n fileNames = parsed.fileNames.includes(absolutePath)\n ? parsed.fileNames\n : [...parsed.fileNames, absolutePath];\n } else {\n // Fallback to default options\n compilerOptions = {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.NodeNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n strict: true,\n skipLibCheck: true,\n declaration: true,\n };\n fileNames = [absolutePath];\n }\n\n const program = ts.createProgram(fileNames, compilerOptions);\n const sourceFile = program.getSourceFile(absolutePath);\n\n if (!sourceFile) {\n throw new Error(`Could not find source file: ${absolutePath}`);\n }\n\n return {\n program,\n checker: program.getTypeChecker(),\n sourceFile,\n };\n}\n\n/**\n * Generic AST node finder by name. Walks the source file tree and returns\n * the first node matching the predicate with the given name.\n */\nfunction findNodeByName<T extends ts.Node>(\n sourceFile: ts.SourceFile,\n name: string,\n predicate: (node: ts.Node) => node is T,\n getName: (node: T) => string | undefined\n): T | null {\n let result: T | null = null;\n\n function visit(node: ts.Node): void {\n if (result) return;\n\n if (predicate(node) && getName(node) === name) {\n result = node;\n return;\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return result;\n}\n\n/**\n * Finds a class declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param className - Name of the class to find\n * @returns The class declaration node, or null if not found\n */\nexport function findClassByName(\n sourceFile: ts.SourceFile,\n className: string\n): ts.ClassDeclaration | null {\n return findNodeByName(sourceFile, className, ts.isClassDeclaration, (n) => n.name?.text);\n}\n\n/**\n * Finds an interface declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param interfaceName - Name of the interface to find\n * @returns The interface declaration node, or null if not found\n */\nexport function findInterfaceByName(\n sourceFile: ts.SourceFile,\n interfaceName: string\n): ts.InterfaceDeclaration | null {\n return findNodeByName(sourceFile, interfaceName, ts.isInterfaceDeclaration, (n) => n.name.text);\n}\n\n/**\n * Finds a type alias declaration by name in a source file.\n *\n * @param sourceFile - The source file to search\n * @param aliasName - Name of the type alias to find\n * @returns The type alias declaration node, or null if not found\n */\nexport function findTypeAliasByName(\n sourceFile: ts.SourceFile,\n aliasName: string\n): ts.TypeAliasDeclaration | null {\n return findNodeByName(sourceFile, aliasName, ts.isTypeAliasDeclaration, (n) => n.name.text);\n}\n","/**\n * Class analyzer for extracting fields, types, and JSDoc constraints.\n *\n * Produces `IRClassAnalysis` containing `FieldNode[]` and `typeRegistry`\n * directly from class, interface, or type alias declarations.\n * All downstream generation routes through the canonical FormIR.\n */\n\nimport * as ts from \"typescript\";\nimport type {\n FieldNode,\n TypeNode,\n EnumTypeNode,\n EnumMember,\n ConstraintNode,\n AnnotationNode,\n Provenance,\n ObjectProperty,\n RecordTypeNode,\n TypeDefinition,\n JsonValue,\n} from \"@formspec/core\";\nimport {\n extractJSDocConstraintNodes,\n extractJSDocAnnotationNodes,\n extractDefaultValueAnnotation,\n} from \"./jsdoc-constraints.js\";\nimport { extractDisplayNameMetadata } from \"./tsdoc-parser.js\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\n\n// =============================================================================\n// TYPE GUARDS\n// =============================================================================\n\n/**\n * Type guard for ts.ObjectType — checks that the TypeFlags.Object bit is set.\n */\nfunction isObjectType(type: ts.Type): type is ts.ObjectType {\n return !!(type.flags & ts.TypeFlags.Object);\n}\n\n/**\n * Type guard for ts.TypeReference — checks ObjectFlags.Reference on top of ObjectType.\n * The internal `as` cast is isolated inside this guard and is required because\n * TypeScript's public API does not expose objectFlags on ts.Type directly.\n */\nfunction isTypeReference(type: ts.Type): type is ts.TypeReference {\n // as cast is isolated inside type guard\n return (\n !!(type.flags & ts.TypeFlags.Object) &&\n !!((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference)\n );\n}\n\n/**\n * Placeholder used while a named object type is still being expanded.\n *\n * The object identity matters: final empty-object schemas are distinct\n * instances, so we can tell an in-progress registry entry from a real one.\n */\nconst RESOLVING_TYPE_PLACEHOLDER: TypeNode = {\n kind: \"object\",\n properties: [],\n additionalProperties: true,\n};\n\nfunction makeParseOptions(\n extensionRegistry: ExtensionRegistry | undefined,\n fieldType?: TypeNode\n): import(\"./tsdoc-parser.js\").ParseTSDocOptions | undefined {\n if (extensionRegistry === undefined && fieldType === undefined) {\n return undefined;\n }\n\n return {\n ...(extensionRegistry !== undefined && { extensionRegistry }),\n ...(fieldType !== undefined && { fieldType }),\n };\n}\n\n// =============================================================================\n// IR OUTPUT TYPES\n// =============================================================================\n\n/**\n * Layout metadata extracted from `@Group` and `@ShowWhen` TSDoc tags.\n * One entry per field, in the same order as `fields`.\n */\nexport interface FieldLayoutMetadata {\n /** Group label from `@Group(\"label\")`, or undefined if ungrouped. */\n readonly groupLabel?: string;\n /** ShowWhen condition from `@ShowWhen({ field, value })`, or undefined if always visible. */\n readonly showWhen?: { readonly field: string; readonly value: JsonValue };\n}\n\n/**\n * Result of analyzing a class/interface/type alias into canonical IR.\n */\nexport interface IRClassAnalysis {\n /** Type name */\n readonly name: string;\n /** Analyzed fields as canonical IR FieldNodes */\n readonly fields: readonly FieldNode[];\n /** Layout metadata per field (same order/length as `fields`). */\n readonly fieldLayouts: readonly FieldLayoutMetadata[];\n /** Named type definitions referenced by fields */\n readonly typeRegistry: Record<string, TypeDefinition>;\n /** Root-level metadata for the analyzed declaration. */\n readonly annotations?: readonly AnnotationNode[];\n /** Instance methods (retained for downstream method-schema generation) */\n readonly instanceMethods: readonly MethodInfo[];\n /** Static methods */\n readonly staticMethods: readonly MethodInfo[];\n}\n\n/**\n * Result of analyzing a type alias into IR — either success or error.\n */\nexport type AnalyzeTypeAliasToIRResult =\n | { readonly ok: true; readonly analysis: IRClassAnalysis }\n | { readonly ok: false; readonly error: string };\n\n// =============================================================================\n// IR ANALYSIS — PUBLIC API\n// =============================================================================\n\n/**\n * Analyzes a class declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeClassToIR(\n classDecl: ts.ClassDeclaration,\n checker: ts.TypeChecker,\n file = \"\",\n extensionRegistry?: ExtensionRegistry\n): IRClassAnalysis {\n const name = classDecl.name?.text ?? \"AnonymousClass\";\n const fields: FieldNode[] = [];\n const fieldLayouts: FieldLayoutMetadata[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(\n classDecl,\n file,\n makeParseOptions(extensionRegistry)\n );\n const visiting = new Set<ts.Type>();\n const instanceMethods: MethodInfo[] = [];\n const staticMethods: MethodInfo[] = [];\n\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member)) {\n const fieldNode = analyzeFieldToIR(\n member,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (fieldNode) {\n fields.push(fieldNode);\n fieldLayouts.push({});\n }\n } else if (ts.isMethodDeclaration(member)) {\n const methodInfo = analyzeMethod(member, checker);\n if (methodInfo) {\n const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);\n if (isStatic) {\n staticMethods.push(methodInfo);\n } else {\n instanceMethods.push(methodInfo);\n }\n }\n }\n }\n\n return {\n name,\n fields,\n fieldLayouts,\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods,\n staticMethods,\n };\n}\n\n/**\n * Analyzes an interface declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeInterfaceToIR(\n interfaceDecl: ts.InterfaceDeclaration,\n checker: ts.TypeChecker,\n file = \"\",\n extensionRegistry?: ExtensionRegistry\n): IRClassAnalysis {\n const name = interfaceDecl.name.text;\n const fields: FieldNode[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(\n interfaceDecl,\n file,\n makeParseOptions(extensionRegistry)\n );\n const visiting = new Set<ts.Type>();\n\n for (const member of interfaceDecl.members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(\n member,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (fieldNode) {\n fields.push(fieldNode);\n }\n }\n }\n\n const fieldLayouts: FieldLayoutMetadata[] = fields.map(() => ({}));\n return {\n name,\n fields,\n fieldLayouts,\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods: [],\n staticMethods: [],\n };\n}\n\n/**\n * Analyzes a type alias declaration and produces canonical IR FieldNodes.\n */\nexport function analyzeTypeAliasToIR(\n typeAlias: ts.TypeAliasDeclaration,\n checker: ts.TypeChecker,\n file = \"\",\n extensionRegistry?: ExtensionRegistry\n): AnalyzeTypeAliasToIRResult {\n if (!ts.isTypeLiteralNode(typeAlias.type)) {\n const sourceFile = typeAlias.getSourceFile();\n const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- enum reverse mapping can be undefined for compiler-internal kinds\n const kindDesc = ts.SyntaxKind[typeAlias.type.kind] ?? \"unknown\";\n return {\n ok: false,\n error: `Type alias \"${typeAlias.name.text}\" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`,\n };\n }\n\n const name = typeAlias.name.text;\n const fields: FieldNode[] = [];\n const typeRegistry: Record<string, TypeDefinition> = {};\n const annotations = extractJSDocAnnotationNodes(\n typeAlias,\n file,\n makeParseOptions(extensionRegistry)\n );\n const visiting = new Set<ts.Type>();\n\n for (const member of typeAlias.type.members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(\n member,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (fieldNode) {\n fields.push(fieldNode);\n }\n }\n }\n\n return {\n ok: true,\n analysis: {\n name,\n fields,\n fieldLayouts: fields.map(() => ({})),\n typeRegistry,\n ...(annotations.length > 0 && { annotations }),\n instanceMethods: [],\n staticMethods: [],\n },\n };\n}\n\n// =============================================================================\n// IR FIELD ANALYSIS — PRIVATE\n// =============================================================================\n\n/**\n * Analyzes a class property declaration into a canonical IR FieldNode.\n */\nfunction analyzeFieldToIR(\n prop: ts.PropertyDeclaration,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): FieldNode | null {\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const tsType = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n const provenance = provenanceForNode(prop, file);\n\n // Resolve ts.Type → TypeNode\n let type = resolveTypeNode(\n tsType,\n checker,\n file,\n typeRegistry,\n visiting,\n prop,\n extensionRegistry\n );\n\n // Collect constraints\n const constraints: ConstraintNode[] = [];\n\n // Inherit constraints from type alias declarations (lower precedence)\n if (prop.type) {\n constraints.push(\n ...extractTypeAliasConstraintNodes(prop.type, checker, file, extensionRegistry)\n );\n }\n\n // Extract JSDoc constraints\n constraints.push(...extractJSDocConstraintNodes(prop, file, makeParseOptions(extensionRegistry, type)));\n\n // Collect annotations\n let annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@displayName, @description, @deprecated)\n annotations.push(\n ...extractJSDocAnnotationNodes(prop, file, makeParseOptions(extensionRegistry, type))\n );\n\n // Default value annotation\n const defaultAnnotation = extractDefaultValueAnnotation(prop.initializer, file);\n if (defaultAnnotation && !annotations.some((a) => a.annotationKind === \"defaultValue\")) {\n annotations.push(defaultAnnotation);\n }\n\n ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));\n\n return {\n kind: \"field\",\n name,\n type,\n required: !optional,\n constraints,\n annotations,\n provenance,\n };\n}\n\n/**\n * Analyzes an interface/type-alias property signature into a canonical IR FieldNode.\n */\nfunction analyzeInterfacePropertyToIR(\n prop: ts.PropertySignature,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): FieldNode | null {\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const tsType = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n const provenance = provenanceForNode(prop, file);\n\n // Resolve ts.Type → TypeNode\n let type = resolveTypeNode(\n tsType,\n checker,\n file,\n typeRegistry,\n visiting,\n prop,\n extensionRegistry\n );\n\n // Collect constraints\n const constraints: ConstraintNode[] = [];\n\n // Inherit constraints from type alias declarations\n if (prop.type) {\n constraints.push(\n ...extractTypeAliasConstraintNodes(prop.type, checker, file, extensionRegistry)\n );\n }\n\n // JSDoc constraints\n constraints.push(...extractJSDocConstraintNodes(prop, file, makeParseOptions(extensionRegistry, type)));\n\n // Collect annotations\n let annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@displayName, @description, @deprecated)\n annotations.push(\n ...extractJSDocAnnotationNodes(prop, file, makeParseOptions(extensionRegistry, type))\n );\n\n ({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));\n\n return {\n kind: \"field\",\n name,\n type,\n required: !optional,\n constraints,\n annotations,\n provenance,\n };\n}\n\n/**\n * Rewrites enum-member display-name annotations into EnumMember.displayName\n * values and strips those annotations from the field-level annotation list.\n *\n * The TSDoc surface uses `@displayName :value Label` for enum member labels.\n * Plain `@displayName Label` annotations remain as field-level titles.\n */\nfunction applyEnumMemberDisplayNames(\n type: TypeNode,\n annotations: readonly AnnotationNode[]\n): { type: TypeNode; annotations: AnnotationNode[] } {\n if (\n !annotations.some(\n (annotation) =>\n annotation.annotationKind === \"displayName\" && annotation.value.trim().startsWith(\":\")\n )\n ) {\n return { type, annotations: [...annotations] };\n }\n\n const consumed = new Set<AnnotationNode>();\n const nextType = rewriteEnumDisplayNames(type, annotations, consumed);\n\n if (consumed.size === 0) {\n return { type, annotations: [...annotations] };\n }\n\n return {\n type: nextType,\n annotations: annotations.filter((annotation) => !consumed.has(annotation)),\n };\n}\n\nfunction rewriteEnumDisplayNames(\n type: TypeNode,\n annotations: readonly AnnotationNode[],\n consumed: Set<AnnotationNode>\n): TypeNode {\n switch (type.kind) {\n case \"enum\":\n return applyEnumMemberDisplayNamesToEnum(type, annotations, consumed);\n\n case \"union\": {\n return {\n ...type,\n members: type.members.map((member) =>\n rewriteEnumDisplayNames(member, annotations, consumed)\n ),\n };\n }\n\n default:\n return type;\n }\n}\n\nfunction applyEnumMemberDisplayNamesToEnum(\n type: EnumTypeNode,\n annotations: readonly AnnotationNode[],\n consumed: Set<AnnotationNode>\n): EnumTypeNode {\n const displayNames = new Map<string, string>();\n\n for (const annotation of annotations) {\n if (annotation.annotationKind !== \"displayName\") continue;\n\n const parsed = parseEnumMemberDisplayName(annotation.value);\n if (!parsed) continue;\n\n // Once parsed as a member-target display name, never let it fall back to a\n // field-level title, even if the target value does not exist.\n consumed.add(annotation);\n\n const member = type.members.find((m) => String(m.value) === parsed.value);\n if (!member) continue;\n\n displayNames.set(String(member.value), parsed.label);\n }\n\n if (displayNames.size === 0) {\n return type;\n }\n\n return {\n ...type,\n members: type.members.map((member) => {\n const displayName = displayNames.get(String(member.value));\n return displayName !== undefined ? { ...member, displayName } : member;\n }),\n };\n}\n\nfunction parseEnumMemberDisplayName(value: string): { value: string; label: string } | null {\n const trimmed = value.trim();\n const match = /^:([^\\s]+)\\s+([\\s\\S]+)$/.exec(trimmed);\n if (!match?.[1] || !match[2]) return null;\n\n const label = match[2].trim();\n if (label === \"\") return null;\n\n return { value: match[1], label };\n}\n\nfunction resolveRegisteredCustomType(\n sourceNode: ts.Node | undefined,\n extensionRegistry: ExtensionRegistry | undefined,\n checker: ts.TypeChecker\n): TypeNode | null {\n if (sourceNode === undefined || extensionRegistry === undefined) {\n return null;\n }\n\n const typeNode = extractTypeNodeFromSource(sourceNode);\n if (typeNode === undefined) {\n return null;\n }\n\n return resolveRegisteredCustomTypeFromTypeNode(typeNode, extensionRegistry, checker);\n}\n\nfunction resolveRegisteredCustomTypeFromTypeNode(\n typeNode: ts.TypeNode,\n extensionRegistry: ExtensionRegistry,\n checker: ts.TypeChecker\n): TypeNode | null {\n if (ts.isParenthesizedTypeNode(typeNode)) {\n return resolveRegisteredCustomTypeFromTypeNode(typeNode.type, extensionRegistry, checker);\n }\n\n const typeName = getTypeNodeRegistrationName(typeNode);\n if (typeName === null) {\n return null;\n }\n\n const registration = extensionRegistry.findTypeByName(typeName);\n if (registration !== undefined) {\n return {\n kind: \"custom\",\n typeId: `${registration.extensionId}/${registration.registration.typeName}`,\n payload: null,\n };\n }\n\n if (ts.isTypeReferenceNode(typeNode) && ts.isIdentifier(typeNode.typeName)) {\n const aliasDecl = checker\n .getSymbolAtLocation(typeNode.typeName)\n ?.declarations?.find(ts.isTypeAliasDeclaration);\n if (aliasDecl !== undefined) {\n return resolveRegisteredCustomTypeFromTypeNode(aliasDecl.type, extensionRegistry, checker);\n }\n }\n\n return null;\n}\n\nfunction extractTypeNodeFromSource(sourceNode: ts.Node): ts.TypeNode | undefined {\n if (\n ts.isPropertyDeclaration(sourceNode) ||\n ts.isPropertySignature(sourceNode) ||\n ts.isParameter(sourceNode) ||\n ts.isTypeAliasDeclaration(sourceNode)\n ) {\n return sourceNode.type;\n }\n\n if (ts.isTypeNode(sourceNode)) {\n return sourceNode;\n }\n\n return undefined;\n}\n\nfunction getTypeNodeRegistrationName(typeNode: ts.TypeNode): string | null {\n if (ts.isTypeReferenceNode(typeNode)) {\n return ts.isIdentifier(typeNode.typeName) ? typeNode.typeName.text : typeNode.typeName.right.text;\n }\n\n if (ts.isParenthesizedTypeNode(typeNode)) {\n return getTypeNodeRegistrationName(typeNode.type);\n }\n\n if (\n typeNode.kind === ts.SyntaxKind.BigIntKeyword ||\n typeNode.kind === ts.SyntaxKind.StringKeyword ||\n typeNode.kind === ts.SyntaxKind.NumberKeyword ||\n typeNode.kind === ts.SyntaxKind.BooleanKeyword\n ) {\n return typeNode.getText();\n }\n\n return null;\n}\n\n// =============================================================================\n// TYPE RESOLUTION — ts.Type → TypeNode\n// =============================================================================\n\n/**\n * Resolves a TypeScript type to a canonical IR TypeNode.\n */\nexport function resolveTypeNode(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n sourceNode?: ts.Node,\n extensionRegistry?: ExtensionRegistry\n): TypeNode {\n const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);\n if (customType) {\n return customType;\n }\n\n // --- Primitives ---\n if (type.flags & ts.TypeFlags.String) {\n return { kind: \"primitive\", primitiveKind: \"string\" };\n }\n if (type.flags & ts.TypeFlags.Number) {\n return { kind: \"primitive\", primitiveKind: \"number\" };\n }\n if (type.flags & ts.TypeFlags.Boolean) {\n return { kind: \"primitive\", primitiveKind: \"boolean\" };\n }\n if (type.flags & ts.TypeFlags.Null) {\n return { kind: \"primitive\", primitiveKind: \"null\" };\n }\n if (type.flags & ts.TypeFlags.Undefined) {\n // Undefined maps to null for nullable semantics in JSON Schema\n return { kind: \"primitive\", primitiveKind: \"null\" };\n }\n\n // --- String literal ---\n if (type.isStringLiteral()) {\n return {\n kind: \"enum\",\n members: [{ value: type.value }],\n };\n }\n\n // --- Number literal ---\n if (type.isNumberLiteral()) {\n return {\n kind: \"enum\",\n members: [{ value: type.value }],\n };\n }\n\n // --- Union types ---\n if (type.isUnion()) {\n return resolveUnionType(\n type,\n checker,\n file,\n typeRegistry,\n visiting,\n sourceNode,\n extensionRegistry\n );\n }\n\n // --- Array types ---\n if (checker.isArrayType(type)) {\n return resolveArrayType(\n type,\n checker,\n file,\n typeRegistry,\n visiting,\n sourceNode,\n extensionRegistry\n );\n }\n\n // --- Object types ---\n if (isObjectType(type)) {\n return resolveObjectType(type, checker, file, typeRegistry, visiting, extensionRegistry);\n }\n\n // --- Fallback: treat unknown/any/void as string ---\n return { kind: \"primitive\", primitiveKind: \"string\" };\n}\n\nfunction resolveUnionType(\n type: ts.UnionType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n sourceNode?: ts.Node,\n extensionRegistry?: ExtensionRegistry\n): TypeNode {\n const typeName = getNamedTypeName(type);\n const namedDecl = getNamedTypeDeclaration(type);\n\n if (typeName && typeName in typeRegistry) {\n return { kind: \"reference\", name: typeName, typeArguments: [] };\n }\n\n const allTypes = type.types;\n const unionMemberTypeNodes = extractUnionMemberTypeNodes(sourceNode, checker);\n const nonNullSourceNodes = unionMemberTypeNodes.filter(\n (memberTypeNode) => !isNullishTypeNode(resolveAliasedTypeNode(memberTypeNode, checker))\n );\n const nonNullTypes = allTypes.filter(\n (memberType) => !(memberType.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))\n );\n const nonNullMembers = nonNullTypes.map((memberType, index) => ({\n memberType,\n sourceNode:\n nonNullSourceNodes.length === nonNullTypes.length ? nonNullSourceNodes[index] : undefined,\n }));\n const hasNull = allTypes.some((t) => t.flags & ts.TypeFlags.Null);\n const memberDisplayNames = new Map<string, string>();\n if (namedDecl) {\n for (const [value, label] of extractDisplayNameMetadata(namedDecl).memberDisplayNames) {\n memberDisplayNames.set(value, label);\n }\n }\n if (sourceNode) {\n for (const [value, label] of extractDisplayNameMetadata(sourceNode).memberDisplayNames) {\n memberDisplayNames.set(value, label);\n }\n }\n\n const registerNamed = (result: TypeNode): TypeNode => {\n if (!typeName) {\n return result;\n }\n const annotations = namedDecl\n ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry))\n : undefined;\n typeRegistry[typeName] = {\n name: typeName,\n type: result,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl ?? sourceNode, file),\n };\n return { kind: \"reference\", name: typeName, typeArguments: [] };\n };\n\n const applyMemberLabels = (members: readonly (string | number)[]): EnumMember[] =>\n members.map((value) => {\n const displayName = memberDisplayNames.get(String(value));\n return displayName !== undefined ? { value, displayName } : { value };\n });\n\n const isBooleanUnion =\n nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts.TypeFlags.BooleanLiteral);\n\n if (isBooleanUnion) {\n const boolNode: TypeNode = { kind: \"primitive\", primitiveKind: \"boolean\" };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [boolNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : boolNode;\n return registerNamed(result);\n }\n\n const allStringLiterals = nonNullTypes.every((t) => t.isStringLiteral());\n if (allStringLiterals && nonNullTypes.length > 0) {\n const stringTypes = nonNullTypes.filter((t): t is ts.StringLiteralType => t.isStringLiteral());\n const enumNode: TypeNode = {\n kind: \"enum\",\n members: applyMemberLabels(stringTypes.map((t) => t.value)),\n };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : enumNode;\n return registerNamed(result);\n }\n\n const allNumberLiterals = nonNullTypes.every((t) => t.isNumberLiteral());\n if (allNumberLiterals && nonNullTypes.length > 0) {\n const numberTypes = nonNullTypes.filter((t): t is ts.NumberLiteralType => t.isNumberLiteral());\n const enumNode: TypeNode = {\n kind: \"enum\",\n members: applyMemberLabels(numberTypes.map((t) => t.value)),\n };\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : enumNode;\n return registerNamed(result);\n }\n\n if (nonNullMembers.length === 1 && nonNullMembers[0]) {\n const inner = resolveTypeNode(\n nonNullMembers[0].memberType,\n checker,\n file,\n typeRegistry,\n visiting,\n nonNullMembers[0].sourceNode ?? sourceNode,\n extensionRegistry\n );\n const result: TypeNode = hasNull\n ? {\n kind: \"union\",\n members: [inner, { kind: \"primitive\", primitiveKind: \"null\" }],\n }\n : inner;\n return registerNamed(result);\n }\n\n const members = nonNullMembers.map(({ memberType, sourceNode: memberSourceNode }) =>\n resolveTypeNode(\n memberType,\n checker,\n file,\n typeRegistry,\n visiting,\n memberSourceNode ?? sourceNode,\n extensionRegistry\n )\n );\n if (hasNull) {\n members.push({ kind: \"primitive\", primitiveKind: \"null\" });\n }\n return registerNamed({ kind: \"union\", members });\n}\n\nfunction resolveArrayType(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n sourceNode?: ts.Node,\n extensionRegistry?: ExtensionRegistry\n): TypeNode {\n const typeArgs = isTypeReference(type) ? type.typeArguments : undefined;\n const elementType = typeArgs?.[0];\n const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);\n\n const items = elementType\n ? resolveTypeNode(\n elementType,\n checker,\n file,\n typeRegistry,\n visiting,\n elementSourceNode,\n extensionRegistry\n )\n : ({ kind: \"primitive\", primitiveKind: \"string\" } satisfies TypeNode);\n\n return { kind: \"array\", items };\n}\n\n/**\n * Returns a `RecordTypeNode` if `type` is a pure dictionary type (string index\n * signature with no named properties), or `null` otherwise.\n *\n * This handles both `Record<string, T>` (a mapped/aliased type) and inline\n * `{ [k: string]: T }` index signature types per spec 003 §2.5.\n */\nfunction tryResolveRecordType(\n type: ts.ObjectType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): RecordTypeNode | null {\n // Only types with no named properties qualify as pure dictionaries.\n if (type.getProperties().length > 0) {\n return null;\n }\n const indexInfo = checker.getIndexInfoOfType(type, ts.IndexKind.String);\n if (!indexInfo) {\n return null;\n }\n\n const valueType = resolveTypeNode(\n indexInfo.type,\n checker,\n file,\n typeRegistry,\n visiting,\n undefined,\n extensionRegistry\n );\n return { kind: \"record\", valueType };\n}\n\nfunction typeNodeContainsReference(type: TypeNode, targetName: string): boolean {\n switch (type.kind) {\n case \"reference\":\n return type.name === targetName;\n case \"array\":\n return typeNodeContainsReference(type.items, targetName);\n case \"record\":\n return typeNodeContainsReference(type.valueType, targetName);\n case \"union\":\n return type.members.some((member) => typeNodeContainsReference(member, targetName));\n case \"object\":\n return type.properties.some((property) =>\n typeNodeContainsReference(property.type, targetName)\n );\n case \"primitive\":\n case \"enum\":\n case \"dynamic\":\n case \"custom\":\n return false;\n default: {\n const _exhaustive: never = type;\n return _exhaustive;\n }\n }\n}\n\nfunction resolveObjectType(\n type: ts.ObjectType,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): TypeNode {\n const typeName = getNamedTypeName(type);\n const namedTypeName = typeName ?? undefined;\n const namedDecl = getNamedTypeDeclaration(type);\n const shouldRegisterNamedType =\n namedTypeName !== undefined &&\n !(namedTypeName === \"Record\" && namedDecl?.getSourceFile().fileName !== file);\n const clearNamedTypeRegistration = (): void => {\n if (namedTypeName === undefined || !shouldRegisterNamedType) {\n return;\n }\n Reflect.deleteProperty(typeRegistry, namedTypeName);\n };\n\n if (visiting.has(type)) {\n // Recursive object expansion is deferred through the named-type registry.\n // Anonymous cycles still collapse to a closed empty object sentinel.\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n return { kind: \"object\", properties: [], additionalProperties: false };\n }\n\n // Seed the registry with a placeholder before traversing children so any\n // recursive property reference can resolve to a stable `$ref`.\n if (namedTypeName !== undefined && shouldRegisterNamedType && !typeRegistry[namedTypeName]) {\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: RESOLVING_TYPE_PLACEHOLDER,\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n }\n\n visiting.add(type);\n\n // Detect previously resolved named types before walking the object body.\n if (\n namedTypeName !== undefined &&\n shouldRegisterNamedType &&\n typeRegistry[namedTypeName]?.type !== undefined\n ) {\n if (typeRegistry[namedTypeName].type !== RESOLVING_TYPE_PLACEHOLDER) {\n visiting.delete(type);\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n }\n\n // Detect pure dictionary types (Record<string, T> or { [k: string]: T })\n // after the recursion guard/placeholder setup so recursive records can point\n // back at the named type instead of collapsing to an empty object.\n const recordNode = tryResolveRecordType(\n type,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (recordNode) {\n visiting.delete(type);\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n const isRecursiveRecord = typeNodeContainsReference(recordNode.valueType, namedTypeName);\n if (!isRecursiveRecord) {\n clearNamedTypeRegistration();\n return recordNode;\n }\n const annotations = namedDecl\n ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry))\n : undefined;\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: recordNode,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n return recordNode;\n }\n\n const properties: ObjectProperty[] = [];\n\n // Get FieldInfo-level analysis from named type declarations for constraint propagation\n const fieldInfoMap = getNamedTypeFieldNodeInfoMap(\n type,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n\n for (const prop of type.getProperties()) {\n const declaration = prop.valueDeclaration ?? prop.declarations?.[0];\n if (!declaration) continue;\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);\n const optional = !!(prop.flags & ts.SymbolFlags.Optional);\n const propTypeNode = resolveTypeNode(\n propType,\n checker,\n file,\n typeRegistry,\n visiting,\n declaration,\n extensionRegistry\n );\n\n // Get constraints and annotations from the declaration if available\n const fieldNodeInfo = fieldInfoMap?.get(prop.name);\n\n properties.push({\n name: prop.name,\n type: propTypeNode,\n optional,\n constraints: fieldNodeInfo?.constraints ?? [],\n annotations: fieldNodeInfo?.annotations ?? [],\n provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file),\n });\n }\n\n visiting.delete(type);\n\n const objectNode: TypeNode = {\n kind: \"object\",\n properties,\n additionalProperties: true,\n };\n\n // Register named types\n if (namedTypeName !== undefined && shouldRegisterNamedType) {\n const annotations = namedDecl\n ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry))\n : undefined;\n typeRegistry[namedTypeName] = {\n name: namedTypeName,\n type: objectNode,\n ...(annotations !== undefined && annotations.length > 0 && { annotations }),\n provenance: provenanceForDeclaration(namedDecl, file),\n };\n return { kind: \"reference\", name: namedTypeName, typeArguments: [] };\n }\n\n return objectNode;\n}\n\n// =============================================================================\n// NAMED TYPE FIELD INFO MAP — for nested constraint propagation\n// =============================================================================\n\ninterface FieldNodeInfo {\n readonly constraints: readonly ConstraintNode[];\n readonly annotations: readonly AnnotationNode[];\n readonly provenance: Provenance;\n}\n\n/**\n * Builds a map from property name to constraint/annotation info for named types.\n * This enables propagating TSDoc constraints from nested type declarations.\n */\nfunction getNamedTypeFieldNodeInfoMap(\n type: ts.Type,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): Map<string, FieldNodeInfo> | null {\n const symbols = [type.getSymbol(), type.aliasSymbol].filter(\n (s): s is ts.Symbol => s?.declarations != null && s.declarations.length > 0\n );\n\n for (const symbol of symbols) {\n const declarations = symbol.declarations;\n if (!declarations) continue;\n\n // Try class declaration\n const classDecl = declarations.find(ts.isClassDeclaration);\n if (classDecl) {\n const map = new Map<string, FieldNodeInfo>();\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name)) {\n const fieldNode = analyzeFieldToIR(\n member,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (fieldNode) {\n map.set(fieldNode.name, {\n constraints: [...fieldNode.constraints],\n annotations: [...fieldNode.annotations],\n provenance: fieldNode.provenance,\n });\n }\n }\n }\n return map;\n }\n\n // Try interface declaration\n const interfaceDecl = declarations.find(ts.isInterfaceDeclaration);\n if (interfaceDecl) {\n return buildFieldNodeInfoMap(\n interfaceDecl.members,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n }\n\n // Try type alias with type literal body\n const typeAliasDecl = declarations.find(ts.isTypeAliasDeclaration);\n if (typeAliasDecl && ts.isTypeLiteralNode(typeAliasDecl.type)) {\n return buildFieldNodeInfoMap(\n typeAliasDecl.type.members,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n }\n }\n\n return null;\n}\n\nfunction extractArrayElementTypeNode(\n sourceNode: ts.Node | undefined,\n checker: ts.TypeChecker\n): ts.TypeNode | undefined {\n const typeNode = sourceNode === undefined ? undefined : extractTypeNodeFromSource(sourceNode);\n if (typeNode === undefined) {\n return undefined;\n }\n const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);\n if (ts.isArrayTypeNode(resolvedTypeNode)) {\n return resolvedTypeNode.elementType;\n }\n if (\n ts.isTypeReferenceNode(resolvedTypeNode) &&\n ts.isIdentifier(resolvedTypeNode.typeName) &&\n resolvedTypeNode.typeName.text === \"Array\" &&\n resolvedTypeNode.typeArguments?.[0]\n ) {\n return resolvedTypeNode.typeArguments[0];\n }\n return undefined;\n}\n\nfunction extractUnionMemberTypeNodes(\n sourceNode: ts.Node | undefined,\n checker: ts.TypeChecker\n): readonly ts.TypeNode[] {\n const typeNode = sourceNode === undefined ? undefined : extractTypeNodeFromSource(sourceNode);\n if (!typeNode) {\n return [];\n }\n const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);\n return ts.isUnionTypeNode(resolvedTypeNode) ? [...resolvedTypeNode.types] : [];\n}\n\nfunction resolveAliasedTypeNode(\n typeNode: ts.TypeNode,\n checker: ts.TypeChecker,\n visited: Set<ts.TypeAliasDeclaration> = new Set<ts.TypeAliasDeclaration>()\n): ts.TypeNode {\n if (ts.isParenthesizedTypeNode(typeNode)) {\n return resolveAliasedTypeNode(typeNode.type, checker, visited);\n }\n\n if (!ts.isTypeReferenceNode(typeNode) || !ts.isIdentifier(typeNode.typeName)) {\n return typeNode;\n }\n\n const symbol = checker.getSymbolAtLocation(typeNode.typeName);\n const aliasDecl = symbol?.declarations?.find(ts.isTypeAliasDeclaration);\n if (aliasDecl === undefined || visited.has(aliasDecl)) {\n return typeNode;\n }\n\n visited.add(aliasDecl);\n return resolveAliasedTypeNode(aliasDecl.type, checker, visited);\n}\n\nfunction isNullishTypeNode(typeNode: ts.TypeNode): boolean {\n if (typeNode.kind === ts.SyntaxKind.NullKeyword || typeNode.kind === ts.SyntaxKind.UndefinedKeyword) {\n return true;\n }\n\n return (\n ts.isLiteralTypeNode(typeNode) &&\n (typeNode.literal.kind === ts.SyntaxKind.NullKeyword ||\n typeNode.literal.kind === ts.SyntaxKind.UndefinedKeyword)\n );\n}\n\nfunction buildFieldNodeInfoMap(\n members: ts.NodeArray<ts.TypeElement>,\n checker: ts.TypeChecker,\n file: string,\n typeRegistry: Record<string, TypeDefinition>,\n visiting: Set<ts.Type>,\n extensionRegistry?: ExtensionRegistry\n): Map<string, FieldNodeInfo> {\n const map = new Map<string, FieldNodeInfo>();\n for (const member of members) {\n if (ts.isPropertySignature(member)) {\n const fieldNode = analyzeInterfacePropertyToIR(\n member,\n checker,\n file,\n typeRegistry,\n visiting,\n extensionRegistry\n );\n if (fieldNode) {\n map.set(fieldNode.name, {\n constraints: [...fieldNode.constraints],\n annotations: [...fieldNode.annotations],\n provenance: fieldNode.provenance,\n });\n }\n }\n }\n return map;\n}\n\n// =============================================================================\n// TYPE ALIAS CONSTRAINT PROPAGATION\n// =============================================================================\n\n/** Maximum depth for transitive type alias constraint propagation. */\nconst MAX_ALIAS_CHAIN_DEPTH = 8;\n\n/**\n * Given a type node referencing a type alias, extracts IR ConstraintNodes\n * from the alias declaration's JSDoc tags.\n *\n * Follows alias chains transitively: if `type Percentage = Integer` and\n * `type Integer = number`, constraints from both `Percentage` and `Integer`\n * are collected. Constraints from closer aliases appear first in the result\n * (higher precedence). Recursion is capped at {@link MAX_ALIAS_CHAIN_DEPTH}\n * levels; exceeding the limit throws to surface pathological alias chains.\n */\nfunction extractTypeAliasConstraintNodes(\n typeNode: ts.TypeNode,\n checker: ts.TypeChecker,\n file: string,\n extensionRegistry?: ExtensionRegistry,\n depth = 0\n): ConstraintNode[] {\n if (!ts.isTypeReferenceNode(typeNode)) return [];\n\n if (depth >= MAX_ALIAS_CHAIN_DEPTH) {\n const aliasName = typeNode.typeName.getText();\n throw new Error(\n `Type alias chain exceeds maximum depth of ${String(MAX_ALIAS_CHAIN_DEPTH)} ` +\n `at alias \"${aliasName}\" in ${file}. ` +\n `Simplify the alias chain or check for circular references.`\n );\n }\n\n const symbol = checker.getSymbolAtLocation(typeNode.typeName);\n if (!symbol?.declarations) return [];\n\n const aliasDecl = symbol.declarations.find(ts.isTypeAliasDeclaration);\n if (!aliasDecl) return [];\n\n // Don't extract from object type aliases\n if (ts.isTypeLiteralNode(aliasDecl.type)) return [];\n\n const aliasFieldType = resolveTypeNode(\n checker.getTypeAtLocation(aliasDecl.type),\n checker,\n file,\n {},\n new Set<ts.Type>(),\n aliasDecl.type,\n extensionRegistry\n );\n const constraints = extractJSDocConstraintNodes(\n aliasDecl,\n file,\n makeParseOptions(extensionRegistry, aliasFieldType)\n );\n\n // Transitively follow alias chains (e.g., Percentage → Integer → number)\n // Constraints from parent aliases are appended after the immediate alias's\n // constraints, giving the immediate alias higher precedence.\n constraints.push(\n ...extractTypeAliasConstraintNodes(\n aliasDecl.type,\n checker,\n file,\n extensionRegistry,\n depth + 1\n )\n );\n\n return constraints;\n}\n\n// =============================================================================\n// PROVENANCE HELPERS\n// =============================================================================\n\nfunction provenanceForNode(node: ts.Node, file: string): Provenance {\n const sourceFile = node.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n };\n}\n\nfunction provenanceForFile(file: string): Provenance {\n return { surface: \"tsdoc\", file, line: 0, column: 0 };\n}\n\nfunction provenanceForDeclaration(node: ts.Node | undefined, file: string): Provenance {\n if (!node) {\n return provenanceForFile(file);\n }\n return provenanceForNode(node, file);\n}\n\n// =============================================================================\n// NAMED TYPE HELPERS\n// =============================================================================\n\n/**\n * Extracts a stable type name from a ts.Type when it originates from\n * a named declaration (class, interface, or type alias).\n */\nfunction getNamedTypeName(type: ts.Type): string | null {\n const symbol = type.getSymbol();\n if (symbol?.declarations) {\n const decl = symbol.declarations[0];\n if (\n decl &&\n (ts.isClassDeclaration(decl) ||\n ts.isInterfaceDeclaration(decl) ||\n ts.isTypeAliasDeclaration(decl))\n ) {\n const name = ts.isClassDeclaration(decl) ? decl.name?.text : decl.name.text;\n if (name) return name;\n }\n }\n\n const aliasSymbol = type.aliasSymbol;\n if (aliasSymbol?.declarations) {\n const aliasDecl = aliasSymbol.declarations.find(ts.isTypeAliasDeclaration);\n if (aliasDecl) {\n return aliasDecl.name.text;\n }\n }\n\n return null;\n}\n\n/**\n * Returns the declaration that defines a named type, if available.\n */\nfunction getNamedTypeDeclaration(type: ts.Type): ts.Declaration | undefined {\n const symbol = type.getSymbol();\n if (symbol?.declarations) {\n const decl = symbol.declarations[0];\n if (\n decl &&\n (ts.isClassDeclaration(decl) ||\n ts.isInterfaceDeclaration(decl) ||\n ts.isTypeAliasDeclaration(decl))\n ) {\n return decl;\n }\n }\n\n const aliasSymbol = type.aliasSymbol;\n if (aliasSymbol?.declarations) {\n return aliasSymbol.declarations.find(ts.isTypeAliasDeclaration);\n }\n\n return undefined;\n}\n\n// =============================================================================\n// SHARED OUTPUT TYPES\n// =============================================================================\n\n/**\n * Analyzed method information.\n */\nexport interface MethodInfo {\n /** Method name */\n name: string;\n /** Method parameters */\n parameters: ParameterInfo[];\n /** Return type node */\n returnTypeNode: ts.TypeNode | undefined;\n /** Resolved return type */\n returnType: ts.Type;\n}\n\n/**\n * Analyzed parameter information.\n */\nexport interface ParameterInfo {\n /** Parameter name */\n name: string;\n /** TypeScript type node */\n typeNode: ts.TypeNode | undefined;\n /** Resolved type */\n type: ts.Type;\n /** If this is InferSchema<typeof X>, the export name X */\n formSpecExportName: string | null;\n /** Whether the parameter is optional (has ? or default value) */\n optional: boolean;\n}\n\n// =============================================================================\n// SHARED HELPERS\n// =============================================================================\n\n/**\n * Analyzes a method declaration to extract method info.\n * Shared between IR and legacy paths.\n */\nfunction analyzeMethod(method: ts.MethodDeclaration, checker: ts.TypeChecker): MethodInfo | null {\n if (!ts.isIdentifier(method.name)) {\n return null;\n }\n\n const name = method.name.text;\n const parameters: ParameterInfo[] = [];\n\n for (const param of method.parameters) {\n if (ts.isIdentifier(param.name)) {\n const paramInfo = analyzeParameter(param, checker);\n parameters.push(paramInfo);\n }\n }\n\n const returnTypeNode = method.type;\n const signature = checker.getSignatureFromDeclaration(method);\n const returnType = signature\n ? checker.getReturnTypeOfSignature(signature)\n : checker.getTypeAtLocation(method);\n\n return { name, parameters, returnTypeNode, returnType };\n}\n\nfunction analyzeParameter(param: ts.ParameterDeclaration, checker: ts.TypeChecker): ParameterInfo {\n const name = ts.isIdentifier(param.name) ? param.name.text : \"param\";\n const typeNode = param.type;\n const type = checker.getTypeAtLocation(param);\n const formSpecExportName = detectFormSpecReference(typeNode);\n const optional = param.questionToken !== undefined || param.initializer !== undefined;\n\n return { name, typeNode, type, formSpecExportName, optional };\n}\n\nfunction detectFormSpecReference(typeNode: ts.TypeNode | undefined): string | null {\n if (!typeNode) return null;\n\n if (!ts.isTypeReferenceNode(typeNode)) return null;\n\n const typeName = ts.isIdentifier(typeNode.typeName)\n ? typeNode.typeName.text\n : ts.isQualifiedName(typeNode.typeName)\n ? typeNode.typeName.right.text\n : null;\n\n if (typeName !== \"InferSchema\" && typeName !== \"InferFormSchema\") return null;\n\n const typeArg = typeNode.typeArguments?.[0];\n if (!typeArg || !ts.isTypeQueryNode(typeArg)) return null;\n\n if (ts.isIdentifier(typeArg.exprName)) {\n return typeArg.exprName.text;\n }\n\n if (ts.isQualifiedName(typeArg.exprName)) {\n return typeArg.exprName.right.text;\n }\n\n return null;\n}\n","/**\n * JSDoc constraint and annotation extractor.\n *\n * Extracts constraints and annotation tags from JSDoc comments on\n * class/interface fields and returns canonical IR nodes directly:\n * - {@link ConstraintNode} for set-influencing tags (@minimum, @pattern, etc.)\n * - {@link AnnotationNode} for value-influencing tags (@displayName, etc.)\n *\n * The IR extraction path uses the official `@microsoft/tsdoc` parser for\n * all canonical tags.\n *\n * Supported constraints correspond to the built-in FormSpec constraint tags\n * (e.g., `@minimum`, `@maximum`, `@pattern`).\n */\n\nimport * as ts from \"typescript\";\nimport type { ConstraintNode, AnnotationNode, JsonValue } from \"@formspec/core\";\nimport {\n parseTSDocTags,\n hasDeprecatedTagTSDoc,\n type ParseTSDocOptions,\n} from \"./tsdoc-parser.js\";\n\n// =============================================================================\n// IR API — uses @microsoft/tsdoc for structured parsing\n// =============================================================================\n\n/**\n * Extracts constraints from JSDoc comments on a TypeScript AST node and returns\n * canonical {@link ConstraintNode} objects.\n *\n * Uses the official `@microsoft/tsdoc` parser for structured tag extraction.\n * Constraints are registered as custom block tags in the TSDoc configuration.\n *\n * @param node - The AST node to inspect for JSDoc tags\n * @param file - Absolute path to the source file for provenance\n * @returns Canonical constraint nodes for each valid constraint tag\n */\nexport function extractJSDocConstraintNodes(\n node: ts.Node,\n file = \"\",\n options?: ParseTSDocOptions\n): ConstraintNode[] {\n const result = parseTSDocTags(node, file, options);\n return [...result.constraints];\n}\n\n/**\n * Extracts canonical annotation tags from a node and returns\n * {@link AnnotationNode} objects.\n *\n * @param node - The AST node to inspect for annotation tags\n * @param file - Absolute path to the source file for provenance\n * @returns Canonical annotation nodes\n */\nexport function extractJSDocAnnotationNodes(\n node: ts.Node,\n file = \"\",\n options?: ParseTSDocOptions\n): AnnotationNode[] {\n const result = parseTSDocTags(node, file, options);\n return [...result.annotations];\n}\n\n/**\n * Checks if a node has a TSDoc `@deprecated` tag.\n *\n * Uses the TSDoc parser for structured detection.\n */\nexport function hasDeprecatedTag(node: ts.Node): boolean {\n return hasDeprecatedTagTSDoc(node);\n}\n\n/**\n * Extracts a default value from a property initializer and returns a\n * {@link DefaultValueAnnotationNode} if present.\n *\n * Only extracts literal values (strings, numbers, booleans, null).\n */\nexport function extractDefaultValueAnnotation(\n initializer: ts.Expression | undefined,\n file = \"\"\n): AnnotationNode | null {\n if (!initializer) return null;\n\n let value: JsonValue | undefined;\n\n if (ts.isStringLiteral(initializer)) {\n value = initializer.text;\n } else if (ts.isNumericLiteral(initializer)) {\n value = Number(initializer.text);\n } else if (initializer.kind === ts.SyntaxKind.TrueKeyword) {\n value = true;\n } else if (initializer.kind === ts.SyntaxKind.FalseKeyword) {\n value = false;\n } else if (initializer.kind === ts.SyntaxKind.NullKeyword) {\n value = null;\n } else if (ts.isPrefixUnaryExpression(initializer)) {\n if (\n initializer.operator === ts.SyntaxKind.MinusToken &&\n ts.isNumericLiteral(initializer.operand)\n ) {\n value = -Number(initializer.operand.text);\n }\n }\n\n if (value === undefined) return null;\n\n const sourceFile = initializer.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(initializer.getStart());\n\n return {\n kind: \"annotation\",\n annotationKind: \"defaultValue\",\n value,\n provenance: {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n },\n };\n}\n","/**\n * TSDoc-based structured tag parser.\n *\n * Bridges the TypeScript compiler AST with the official `@microsoft/tsdoc`\n * parser to extract constraint and annotation tags from JSDoc comments\n * on class/interface/type-alias properties.\n *\n * The parser recognises two categories of tags:\n *\n * 1. **Constraint tags** (all alphanumeric, TSDoc-compliant):\n * `@minimum`, `@maximum`, `@exclusiveMinimum`, `@exclusiveMaximum`,\n * `@multipleOf`, `@minLength`, `@maxLength`, `@minItems`, `@maxItems`,\n * `@uniqueItems`, `@pattern`, `@enumOptions`, `@const`\n * — Parsed via TSDocParser as custom block tags.\n * Both camelCase and PascalCase forms are accepted (e.g., `@Minimum`).\n *\n * 2. **Annotation tags** (`@displayName`, `@description`, `@format`, `@placeholder`):\n * These are parsed as structured custom block tags and mapped directly\n * onto annotation IR nodes.\n *\n * The `@deprecated` tag is a standard TSDoc block tag, parsed structurally.\n *\n * **Fallback strategy**: TSDoc treats `{` / `}` as inline tag delimiters and\n * `@` as a tag prefix, so content containing these characters (e.g. JSON\n * objects in `@EnumOptions`, regex patterns with `@` in `@Pattern`) gets\n * mangled by the TSDoc parser. For these tags, the raw text is extracted\n * via the TS compiler's `ts.getJSDocTags()` API which preserves content\n * verbatim.\n */\n\nimport * as ts from \"typescript\";\nimport {\n TSDocParser,\n TSDocConfiguration,\n TSDocTagDefinition,\n TSDocTagSyntaxKind,\n DocPlainText,\n DocSoftBreak,\n TextRange,\n type DocNode,\n type DocBlock,\n} from \"@microsoft/tsdoc\";\nimport {\n BUILTIN_CONSTRAINT_DEFINITIONS,\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n type ConstraintNode,\n type AnnotationNode,\n type Provenance,\n type NumericConstraintNode,\n type LengthConstraintNode,\n type PathTarget,\n type JsonValue,\n type TypeNode,\n} from \"@formspec/core\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\nimport { tryParseJson } from \"./json-utils.js\";\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/**\n * Constraint tag name → constraint kind mapping for numeric constraints.\n * Keys are camelCase matching BUILTIN_CONSTRAINT_DEFINITIONS.\n */\nconst NUMERIC_CONSTRAINT_MAP: Record<string, NumericConstraintNode[\"constraintKind\"]> = {\n minimum: \"minimum\",\n maximum: \"maximum\",\n exclusiveMinimum: \"exclusiveMinimum\",\n exclusiveMaximum: \"exclusiveMaximum\",\n multipleOf: \"multipleOf\",\n};\n\n/**\n * Constraint tag name → constraint kind mapping for length constraints.\n * Keys are camelCase matching BUILTIN_CONSTRAINT_DEFINITIONS.\n */\nconst LENGTH_CONSTRAINT_MAP: Record<string, LengthConstraintNode[\"constraintKind\"]> = {\n minLength: \"minLength\",\n maxLength: \"maxLength\",\n minItems: \"minItems\",\n maxItems: \"maxItems\",\n};\n\n/**\n * Tags whose content may contain TSDoc-significant characters (`{}`, `@`)\n * and must be extracted via the TS compiler JSDoc API rather than the\n * TSDoc DocNode tree to avoid content mangling.\n *\n * - `@pattern`: regex patterns commonly contain `@` (e.g. email validation)\n * - `@enumOptions`: JSON arrays may contain object literals with `{}`\n * - `@defaultValue`: JSON defaults may contain objects, arrays, or quoted strings\n */\nconst TAGS_REQUIRING_RAW_TEXT = new Set([\"pattern\", \"enumOptions\", \"defaultValue\"]);\n\n/**\n * Creates a TSDocConfiguration with FormSpec custom block tag definitions\n * registered for all constraint tags.\n */\nfunction createFormSpecTSDocConfig(extensionTagNames: readonly string[] = []): TSDocConfiguration {\n const config = new TSDocConfiguration();\n\n // Register each constraint tag as a custom block tag (allowMultiple so\n // repeated tags don't produce warnings).\n for (const tagName of Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS)) {\n config.addTagDefinition(\n new TSDocTagDefinition({\n tagName: \"@\" + tagName,\n syntaxKind: TSDocTagSyntaxKind.BlockTag,\n allowMultiple: true,\n })\n );\n }\n\n // Register annotation tags that participate in the canonical IR.\n for (const tagName of [\"displayName\", \"description\", \"format\", \"placeholder\"]) {\n config.addTagDefinition(\n new TSDocTagDefinition({\n tagName: \"@\" + tagName,\n syntaxKind: TSDocTagSyntaxKind.BlockTag,\n allowMultiple: true,\n })\n );\n }\n\n for (const tagName of extensionTagNames) {\n config.addTagDefinition(\n new TSDocTagDefinition({\n tagName: \"@\" + tagName,\n syntaxKind: TSDocTagSyntaxKind.BlockTag,\n allowMultiple: true,\n })\n );\n }\n\n return config;\n}\n\n/**\n * Shared parser instance — thread-safe because TSDocParser is stateless;\n * all parse state lives in the returned ParserContext.\n */\nconst parserCache = new Map<string, TSDocParser>();\n\nfunction getParser(options?: ParseTSDocOptions): TSDocParser {\n const extensionTagNames = [\n ...(options?.extensionRegistry?.extensions.flatMap((extension) =>\n (extension.constraintTags ?? []).map((tag) => tag.tagName)\n ) ?? []),\n ].sort();\n const cacheKey = extensionTagNames.join(\"|\");\n const existing = parserCache.get(cacheKey);\n if (existing) {\n return existing;\n }\n\n const parser = new TSDocParser(createFormSpecTSDocConfig(extensionTagNames));\n parserCache.set(cacheKey, parser);\n return parser;\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Result of parsing a single JSDoc comment attached to a TS AST node.\n */\nexport interface TSDocParseResult {\n /** Constraint IR nodes extracted from custom block tags. */\n readonly constraints: readonly ConstraintNode[];\n /** Annotation IR nodes extracted from canonical TSDoc block tags. */\n readonly annotations: readonly AnnotationNode[];\n}\n\n/**\n * Optional extension-aware parsing inputs for TSDoc extraction.\n */\nexport interface ParseTSDocOptions {\n /**\n * Extension registry used to resolve custom tags and custom-type-specific\n * broadening of built-in constraint tags.\n */\n readonly extensionRegistry?: ExtensionRegistry;\n /**\n * Effective field/type node for the declaration being parsed. Required when\n * built-in tags may broaden onto a custom type.\n */\n readonly fieldType?: TypeNode;\n}\n\n/**\n * Display-name metadata extracted from a node's JSDoc tags.\n *\n * The root display name is returned separately from member-target labels so\n * callers can apply the former to the enclosing type/form and the latter to\n * enum members.\n */\nexport interface DisplayNameMetadata {\n readonly displayName?: string;\n readonly memberDisplayNames: ReadonlyMap<string, string>;\n}\n\n/**\n * Parses the JSDoc comment attached to a TypeScript AST node using the\n * official TSDoc parser and returns canonical IR constraint and annotation\n * nodes.\n *\n * For constraint tags (`@minimum`, `@pattern`, `@enumOptions`, etc.),\n * the structured TSDoc parser is used. Canonical annotation tags\n * (`@displayName`, `@description`) are also parsed structurally.\n *\n * @param node - The TS AST node to inspect (PropertyDeclaration, PropertySignature, etc.)\n * @param file - Absolute source file path for provenance\n * @returns Parsed constraint and annotation nodes\n */\nexport function parseTSDocTags(\n node: ts.Node,\n file = \"\",\n options?: ParseTSDocOptions\n): TSDocParseResult {\n const constraints: ConstraintNode[] = [];\n const annotations: AnnotationNode[] = [];\n let displayName: string | undefined;\n let description: string | undefined;\n let placeholder: string | undefined;\n let displayNameProvenance: Provenance | undefined;\n let descriptionProvenance: Provenance | undefined;\n let placeholderProvenance: Provenance | undefined;\n\n // ----- Phase 1: TSDoc structural parse for constraint tags -----\n const sourceFile = node.getSourceFile();\n const sourceText = sourceFile.getFullText();\n const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());\n\n if (commentRanges) {\n for (const range of commentRanges) {\n // Only parse /** ... */ comments (kind 3 = MultiLineCommentTrivia)\n if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {\n continue;\n }\n const commentText = sourceText.substring(range.pos, range.end);\n if (!commentText.startsWith(\"/**\")) {\n continue;\n }\n\n const parser = getParser(options);\n const parserContext = parser.parseRange(\n TextRange.fromStringRange(sourceText, range.pos, range.end)\n );\n const docComment = parserContext.docComment;\n\n // Extract constraint nodes from custom blocks.\n // Tags in TAGS_REQUIRING_RAW_TEXT are skipped here and handled via the\n // TS compiler API in Phase 1b below.\n for (const block of docComment.customBlocks) {\n const tagName = normalizeConstraintTagName(block.blockTag.tagName.substring(1)); // Remove leading @ and normalize to camelCase\n if (\n tagName === \"displayName\" ||\n tagName === \"description\" ||\n tagName === \"format\" ||\n tagName === \"placeholder\"\n ) {\n const text = extractBlockText(block).trim();\n if (text === \"\") continue;\n\n const provenance = provenanceForComment(range, sourceFile, file, tagName);\n if (tagName === \"displayName\") {\n if (!isMemberTargetDisplayName(text) && displayName === undefined) {\n displayName = text;\n displayNameProvenance = provenance;\n }\n } else if (tagName === \"format\") {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"format\",\n value: text,\n provenance,\n });\n } else {\n if (tagName === \"description\" && description === undefined) {\n description = text;\n descriptionProvenance = provenance;\n } else if (tagName === \"placeholder\" && placeholder === undefined) {\n placeholder = text;\n placeholderProvenance = provenance;\n }\n }\n continue;\n }\n\n if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;\n\n const text = extractBlockText(block).trim();\n const expectedType = isBuiltinConstraintName(tagName)\n ? BUILTIN_CONSTRAINT_DEFINITIONS[tagName]\n : undefined;\n if (text === \"\" && expectedType !== \"boolean\") continue;\n\n const provenance = provenanceForComment(range, sourceFile, file, tagName);\n const constraintNode = parseConstraintValue(tagName, text, provenance, options);\n if (constraintNode) {\n constraints.push(constraintNode);\n }\n }\n\n // Extract @deprecated from the standard deprecated block\n if (docComment.deprecatedBlock !== undefined) {\n const message = extractBlockText(docComment.deprecatedBlock).trim();\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"deprecated\",\n ...(message !== \"\" && { message }),\n provenance: provenanceForComment(range, sourceFile, file, \"deprecated\"),\n });\n }\n\n if (description === undefined && docComment.remarksBlock !== undefined) {\n const remarks = extractBlockText(docComment.remarksBlock).trim();\n if (remarks !== \"\") {\n description = remarks;\n descriptionProvenance = provenanceForComment(range, sourceFile, file, \"remarks\");\n }\n }\n }\n }\n\n if (displayName !== undefined && displayNameProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"displayName\",\n value: displayName,\n provenance: displayNameProvenance,\n });\n }\n\n if (description !== undefined && descriptionProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"description\",\n value: description,\n provenance: descriptionProvenance,\n });\n }\n\n if (placeholder !== undefined && placeholderProvenance !== undefined) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"placeholder\",\n value: placeholder,\n provenance: placeholderProvenance,\n });\n }\n\n // ----- Phase 1b: TS compiler API for tags with TSDoc-incompatible content -----\n // @pattern, @enumOptions, and @defaultValue content can contain `@`, `{}`,\n // or quoted JSON payloads that the TSDoc parser treats as structural markers.\n // We extract these via the TS compiler API which preserves content verbatim.\n const jsDocTagsAll = ts.getJSDocTags(node);\n for (const tag of jsDocTagsAll) {\n const tagName = normalizeConstraintTagName(tag.tagName.text);\n if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;\n\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText.trim() === \"\") continue;\n\n const text = commentText.trim();\n const provenance = provenanceForJSDocTag(tag, file);\n if (tagName === \"defaultValue\") {\n const defaultValueNode = parseDefaultValueValue(text, provenance);\n annotations.push(defaultValueNode);\n continue;\n }\n\n const constraintNode = parseConstraintValue(tagName, text, provenance, options);\n if (constraintNode) {\n constraints.push(constraintNode);\n }\n }\n\n return { constraints, annotations };\n}\n\n/**\n * Checks if a TS AST node has a `@deprecated` tag using the TSDoc parser.\n *\n * Falls back to the TS compiler API for nodes without doc comments.\n */\nexport function hasDeprecatedTagTSDoc(node: ts.Node): boolean {\n const sourceFile = node.getSourceFile();\n const sourceText = sourceFile.getFullText();\n const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());\n\n if (commentRanges) {\n for (const range of commentRanges) {\n if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) continue;\n const commentText = sourceText.substring(range.pos, range.end);\n if (!commentText.startsWith(\"/**\")) continue;\n\n const parser = getParser();\n const parserContext = parser.parseRange(\n TextRange.fromStringRange(sourceText, range.pos, range.end)\n );\n if (parserContext.docComment.deprecatedBlock !== undefined) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Extracts root and member-target display-name metadata from a node's JSDoc tags.\n *\n * Member-target display-name tags use the syntax `@displayName :member Label`.\n * The first non-target `@displayName` is returned as the root display name.\n */\nexport function extractDisplayNameMetadata(node: ts.Node): DisplayNameMetadata {\n let displayName: string | undefined;\n const memberDisplayNames = new Map<string, string>();\n\n for (const tag of ts.getJSDocTags(node)) {\n const tagName = normalizeConstraintTagName(tag.tagName.text);\n if (tagName !== \"displayName\") continue;\n\n const commentText = getTagCommentText(tag);\n if (commentText === undefined) continue;\n\n const text = commentText.trim();\n if (text === \"\") continue;\n\n const memberTarget = parseMemberTargetDisplayName(text);\n if (memberTarget) {\n memberDisplayNames.set(memberTarget.target, memberTarget.label);\n continue;\n }\n\n displayName ??= text;\n }\n\n return {\n ...(displayName !== undefined && { displayName }),\n memberDisplayNames,\n };\n}\n\n// =============================================================================\n// PUBLIC HELPERS — path target extraction\n// =============================================================================\n\n/**\n * Extracts a path-target prefix (`:fieldName`) from constraint tag text.\n * Returns the parsed PathTarget and remaining text, or null if no path target.\n *\n * @example\n * extractPathTarget(\":value 0\") // → { path: { segments: [\"value\"] }, remainingText: \"0\" }\n * extractPathTarget(\"42\") // → null\n */\nexport function extractPathTarget(\n text: string\n): { path: PathTarget; remainingText: string } | null {\n const trimmed = text.trimStart();\n const match = /^:([a-zA-Z_]\\w*)\\s+([\\s\\S]*)$/.exec(trimmed);\n if (!match?.[1] || !match[2]) return null;\n return {\n path: { segments: [match[1]] },\n remainingText: match[2],\n };\n}\n\n// =============================================================================\n// PRIVATE HELPERS — TSDoc text extraction\n// =============================================================================\n\n/**\n * Recursively extracts plain text content from a TSDoc DocNode tree.\n *\n * Walks child nodes and concatenates DocPlainText and DocSoftBreak content.\n */\nfunction extractBlockText(block: DocBlock): string {\n return extractPlainText(block.content);\n}\n\nfunction extractPlainText(node: DocNode): string {\n let result = \"\";\n if (node instanceof DocPlainText) {\n return node.text;\n }\n if (node instanceof DocSoftBreak) {\n return \" \";\n }\n if (typeof node.getChildNodes === \"function\") {\n for (const child of node.getChildNodes()) {\n result += extractPlainText(child);\n }\n }\n return result;\n}\n\n// =============================================================================\n// PRIVATE HELPERS — constraint value parsing\n// =============================================================================\n\n/**\n * Parses a raw text value extracted from a TSDoc block tag into an IR\n * ConstraintNode based on the tag name and BUILTIN_CONSTRAINT_DEFINITIONS.\n *\n * @param tagName - camelCase-normalized constraint tag name (callers normalize before calling)\n */\nfunction parseConstraintValue(\n tagName: string,\n text: string,\n provenance: Provenance,\n options?: ParseTSDocOptions\n): ConstraintNode | null {\n const customConstraint = parseExtensionConstraintValue(tagName, text, provenance, options);\n if (customConstraint) {\n return customConstraint;\n }\n\n if (!isBuiltinConstraintName(tagName)) {\n return null;\n }\n\n // Extract optional path target (e.g., \":value 0\" → path=[\"value\"], text=\"0\")\n const pathResult = extractPathTarget(text);\n const effectiveText = pathResult ? pathResult.remainingText : text;\n const path = pathResult?.path;\n\n const expectedType = BUILTIN_CONSTRAINT_DEFINITIONS[tagName];\n\n if (expectedType === \"number\") {\n const value = Number(effectiveText);\n if (Number.isNaN(value)) {\n return null;\n }\n\n const numericKind = NUMERIC_CONSTRAINT_MAP[tagName];\n if (numericKind) {\n return {\n kind: \"constraint\",\n constraintKind: numericKind,\n value,\n ...(path && { path }),\n provenance,\n };\n }\n\n const lengthKind = LENGTH_CONSTRAINT_MAP[tagName];\n if (lengthKind) {\n return {\n kind: \"constraint\",\n constraintKind: lengthKind,\n value,\n ...(path && { path }),\n provenance,\n };\n }\n\n return null;\n }\n\n if (expectedType === \"boolean\") {\n const trimmed = effectiveText.trim();\n if (trimmed !== \"\" && trimmed !== \"true\") {\n return null;\n }\n\n if (tagName === \"uniqueItems\") {\n return {\n kind: \"constraint\",\n constraintKind: \"uniqueItems\",\n value: true,\n ...(path && { path }),\n provenance,\n };\n }\n\n return null;\n }\n\n if (expectedType === \"json\") {\n if (tagName === \"const\") {\n const trimmedText = effectiveText.trim();\n if (trimmedText === \"\") return null;\n\n try {\n const parsed = JSON.parse(trimmedText) as JsonValue;\n return {\n kind: \"constraint\",\n constraintKind: \"const\",\n value: parsed,\n ...(path && { path }),\n provenance,\n };\n } catch {\n // Bare strings like `@const USD` are accepted as a shorthand for\n // string-valued const constraints. Non-string malformed JSON still\n // gets rejected later during IR validation if the field type is\n // incompatible with this fallback string value.\n return {\n kind: \"constraint\",\n constraintKind: \"const\",\n value: trimmedText,\n ...(path && { path }),\n provenance,\n };\n }\n }\n\n const parsed = tryParseJson(effectiveText);\n if (!Array.isArray(parsed)) {\n return null;\n }\n const members: (string | number)[] = [];\n for (const item of parsed) {\n if (typeof item === \"string\" || typeof item === \"number\") {\n members.push(item);\n } else if (typeof item === \"object\" && item !== null && \"id\" in item) {\n const id = (item as Record<string, unknown>)[\"id\"];\n if (typeof id === \"string\" || typeof id === \"number\") {\n members.push(id);\n }\n }\n }\n return {\n kind: \"constraint\",\n constraintKind: \"allowedMembers\",\n members,\n ...(path && { path }),\n provenance,\n };\n }\n\n // expectedType === \"string\" — only remaining case after number and json\n return {\n kind: \"constraint\",\n constraintKind: \"pattern\",\n pattern: effectiveText,\n ...(path && { path }),\n provenance,\n };\n}\n\nfunction parseExtensionConstraintValue(\n tagName: string,\n text: string,\n provenance: Provenance,\n options?: ParseTSDocOptions\n): ConstraintNode | null {\n const pathResult = extractPathTarget(text);\n const effectiveText = pathResult ? pathResult.remainingText : text;\n const path = pathResult?.path;\n const registry = options?.extensionRegistry;\n if (registry === undefined) {\n return null;\n }\n\n const directTag = registry.findConstraintTag(tagName);\n if (directTag !== undefined) {\n return makeCustomConstraintNode(\n directTag.extensionId,\n directTag.registration.constraintName,\n directTag.registration.parseValue(effectiveText),\n provenance,\n path,\n registry\n );\n }\n\n if (!isBuiltinConstraintName(tagName)) {\n return null;\n }\n\n const broadenedTypeId = getBroadenedCustomTypeId(options?.fieldType);\n if (broadenedTypeId === undefined) {\n return null;\n }\n\n const broadened = registry.findBuiltinConstraintBroadening(broadenedTypeId, tagName);\n if (broadened === undefined) {\n return null;\n }\n\n return makeCustomConstraintNode(\n broadened.extensionId,\n broadened.registration.constraintName,\n broadened.registration.parseValue(effectiveText),\n provenance,\n path,\n registry\n );\n}\n\nfunction getBroadenedCustomTypeId(fieldType: TypeNode | undefined): string | undefined {\n if (fieldType?.kind === \"custom\") {\n return fieldType.typeId;\n }\n\n if (fieldType?.kind !== \"union\") {\n return undefined;\n }\n\n const customMembers = fieldType.members.filter(\n (member): member is Extract<TypeNode, { kind: \"custom\" }> => member.kind === \"custom\"\n );\n if (customMembers.length !== 1) {\n return undefined;\n }\n\n const nonCustomMembers = fieldType.members.filter((member) => member.kind !== \"custom\");\n const allOtherMembersAreNull = nonCustomMembers.every(\n (member) => member.kind === \"primitive\" && member.primitiveKind === \"null\"\n );\n\n const customMember = customMembers[0];\n return allOtherMembersAreNull && customMember !== undefined ? customMember.typeId : undefined;\n}\n\nfunction makeCustomConstraintNode(\n extensionId: string,\n constraintName: string,\n payload: JsonValue,\n provenance: Provenance,\n path: PathTarget | undefined,\n registry: ExtensionRegistry\n): ConstraintNode {\n const constraintId = `${extensionId}/${constraintName}`;\n const registration = registry.findConstraint(constraintId);\n if (registration === undefined) {\n throw new Error(\n `Custom TSDoc tag resolved to unregistered constraint \"${constraintId}\". Register the constraint before using its tag.`\n );\n }\n\n return {\n kind: \"constraint\",\n constraintKind: \"custom\",\n constraintId,\n payload,\n compositionRule: registration.compositionRule,\n ...(path && { path }),\n provenance,\n };\n}\n\n/**\n * Parses a raw `@defaultValue` tag payload into a JSON value annotation.\n */\nfunction parseDefaultValueValue(text: string, provenance: Provenance): AnnotationNode {\n const trimmed = text.trim();\n let value: JsonValue;\n\n if (trimmed === \"null\") {\n value = null;\n } else if (trimmed === \"true\") {\n value = true;\n } else if (trimmed === \"false\") {\n value = false;\n } else {\n const parsed = tryParseJson(trimmed);\n value = parsed !== null ? (parsed as JsonValue) : trimmed;\n }\n\n return {\n kind: \"annotation\",\n annotationKind: \"defaultValue\",\n value,\n provenance,\n };\n}\n\nfunction isMemberTargetDisplayName(text: string): boolean {\n return parseMemberTargetDisplayName(text) !== null;\n}\n\nfunction parseMemberTargetDisplayName(\n text: string\n): { readonly target: string; readonly label: string } | null {\n const match = /^:([^\\s]+)\\s+([\\s\\S]+)$/.exec(text);\n if (!match?.[1] || !match[2]) return null;\n return { target: match[1], label: match[2].trim() };\n}\n\n// =============================================================================\n// PRIVATE HELPERS — provenance\n// =============================================================================\n\nfunction provenanceForComment(\n range: ts.CommentRange,\n sourceFile: ts.SourceFile,\n file: string,\n tagName: string\n): Provenance {\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(range.pos);\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n tagName: \"@\" + tagName,\n };\n}\n\nfunction provenanceForJSDocTag(tag: ts.JSDocTag, file: string): Provenance {\n const sourceFile = tag.getSourceFile();\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(tag.getStart());\n return {\n surface: \"tsdoc\",\n file,\n line: line + 1,\n column: character,\n tagName: \"@\" + tag.tagName.text,\n };\n}\n\n/**\n * Extracts the text content from a TypeScript JSDoc tag's comment.\n */\nfunction getTagCommentText(tag: ts.JSDocTag): string | undefined {\n if (tag.comment === undefined) {\n return undefined;\n }\n if (typeof tag.comment === \"string\") {\n return tag.comment;\n }\n return ts.getTextOfJSDocComment(tag.comment);\n}\n","/**\n * Shared JSON parsing utilities for the analyzer pipeline.\n */\n\n/**\n * Attempts to parse `text` as JSON.\n *\n * Returns the parsed value on success, or `null` if the input is not valid\n * JSON. This is the canonical \"try-parse\" wrapper used by the constraint tag\n * parsers so that every `JSON.parse` call in this package is consistent and\n * centrally tested.\n *\n * Note: when the input is the literal string `\"null\"`, the return value is\n * also `null` (valid JSON). This helper therefore cannot distinguish parse\n * failure from a successfully-parsed JSON `null`. Callers that need to\n * distinguish these cases should use a different API (for example, a wrapper\n * that returns a discriminated result such as `{ ok: boolean, value?: unknown }`).\n *\n * @param text - Raw string to parse\n * @returns The parsed value, or `null` on parse failure\n */\nexport function tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return null;\n }\n}\n","/**\n * JSON Schema 2020-12 generator that consumes the canonical FormIR.\n *\n * This generator is a pure function of the IR. It never consults the TypeScript\n * AST or surface syntax directly — only the IR (per the JSON Schema vocabulary spec §1.2).\n *\n * @see https://json-schema.org/draft/2020-12/schema\n * @see https://json-schema.org/draft/2020-12/schema\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n TypeNode,\n PrimitiveTypeNode,\n EnumTypeNode,\n ArrayTypeNode,\n ObjectTypeNode,\n RecordTypeNode,\n UnionTypeNode,\n ReferenceTypeNode,\n DynamicTypeNode,\n CustomTypeNode,\n ConstraintNode,\n AnnotationNode,\n ObjectProperty,\n JsonValue,\n} from \"@formspec/core\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\n\n// =============================================================================\n// OUTPUT TYPE\n// =============================================================================\n\n/**\n * A JSON Schema 2020-12 document, sub-schema, or keyword collection.\n *\n * This interface covers the subset of JSON Schema 2020-12 that this generator\n * emits, plus an index signature for custom `x-formspec-*` extension keywords.\n */\nexport interface JsonSchema2020 {\n $schema?: string;\n $ref?: string;\n $defs?: Record<string, JsonSchema2020>;\n type?: string;\n properties?: Record<string, JsonSchema2020>;\n required?: string[];\n items?: JsonSchema2020;\n additionalProperties?: boolean | JsonSchema2020;\n enum?: readonly (string | number)[];\n const?: JsonValue;\n allOf?: readonly JsonSchema2020[];\n oneOf?: readonly JsonSchema2020[];\n anyOf?: readonly JsonSchema2020[];\n // Constraints\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n multipleOf?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n maxItems?: number;\n pattern?: string;\n uniqueItems?: boolean;\n format?: string;\n // Annotations\n title?: string;\n description?: string;\n default?: unknown;\n deprecated?: boolean;\n // Extensions (open for vendor-prefixed keywords, e.g., x-formspec-*, x-stripe-*)\n // The vendor prefix is configurable (white-labelable).\n [key: `x-${string}`]: unknown;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/**\n * Mutable accumulator passed through the generation traversal.\n *\n * Using a context object rather than return-value threading keeps the\n * recursive generators simple and avoids repeated object spreading.\n */\ninterface GeneratorContext {\n /** Named type schemas collected during traversal, keyed by reference name. */\n readonly defs: Record<string, JsonSchema2020>;\n /** Optional extension registry for resolving custom IR nodes. */\n readonly extensionRegistry: ExtensionRegistry | undefined;\n /** Vendor prefix passed through to extension toJsonSchema handlers. */\n readonly vendorPrefix: string;\n}\n\n/**\n * Options for generating JSON Schema from a canonical FormIR.\n */\nexport interface GenerateJsonSchemaFromIROptions {\n /**\n * Registry used to resolve custom types, constraints, and annotations.\n *\n * JSON Schema generation throws when custom IR nodes are present without a\n * matching registration in this registry.\n */\n readonly extensionRegistry?: ExtensionRegistry | undefined;\n /**\n * Vendor prefix passed to extension `toJsonSchema` hooks.\n * @defaultValue \"x-formspec\"\n */\n readonly vendorPrefix?: string | undefined;\n}\n\nfunction makeContext(options?: GenerateJsonSchemaFromIROptions): GeneratorContext {\n const vendorPrefix = options?.vendorPrefix ?? \"x-formspec\";\n if (!vendorPrefix.startsWith(\"x-\")) {\n throw new Error(\n `Invalid vendorPrefix \"${vendorPrefix}\". Extension JSON Schema keywords must start with \"x-\".`\n );\n }\n\n return {\n defs: {},\n extensionRegistry: options?.extensionRegistry,\n vendorPrefix,\n };\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Generates a JSON Schema 2020-12 object from a canonical FormIR.\n *\n * Groups and conditionals are flattened — they influence UI layout but do not\n * affect the data schema. All fields appear at the level they would occupy in\n * the output data.\n *\n * Named types in the `typeRegistry` are emitted as `$defs` entries and\n * referenced via `$ref` (per PP7 — high-fidelity output).\n *\n * @example\n * ```typescript\n * import { canonicalizeDSL } from \"./canonicalize/index.js\";\n * import { generateJsonSchemaFromIR } from \"./json-schema/ir-generator.js\";\n * import { formspec, field } from \"@formspec/dsl\";\n *\n * const form = formspec(\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n * const ir = canonicalizeDSL(form);\n * const schema = generateJsonSchemaFromIR(ir);\n * // {\n * // $schema: \"https://json-schema.org/draft/2020-12/schema\",\n * // type: \"object\",\n * // properties: {\n * // name: { type: \"string\", title: \"Name\" },\n * // age: { type: \"number\", minimum: 0 }\n * // },\n * // required: [\"name\"]\n * // }\n * ```\n *\n * Advanced API — most consumers should use `generateJsonSchema()` or\n * `buildFormSchemas()`, which canonicalize form definitions automatically.\n * Callers of this function are responsible for providing pre-canonicalized IR.\n *\n * @param ir - The canonical FormIR produced by a canonicalizer\n * @returns A plain JSON-serializable JSON Schema 2020-12 object\n */\nexport function generateJsonSchemaFromIR(\n ir: FormIR,\n options?: GenerateJsonSchemaFromIROptions\n): JsonSchema2020 {\n const ctx = makeContext(options);\n\n // Seed $defs from the type registry so referenced types are available even if\n // the field tree traversal never visits them (e.g., unreferenced types added\n // by a TSDoc canonicalizer pass).\n for (const [name, typeDef] of Object.entries(ir.typeRegistry)) {\n ctx.defs[name] = generateTypeNode(typeDef.type, ctx);\n if (typeDef.annotations && typeDef.annotations.length > 0) {\n applyAnnotations(ctx.defs[name], typeDef.annotations, ctx);\n }\n }\n\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n collectFields(ir.elements, properties, required, ctx);\n\n // Deduplicate required (same field can appear across conditional branches).\n const uniqueRequired = [...new Set(required)];\n\n const result: JsonSchema2020 = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties,\n ...(uniqueRequired.length > 0 && { required: uniqueRequired }),\n };\n\n if (ir.annotations && ir.annotations.length > 0) {\n applyAnnotations(result, ir.annotations, ctx);\n }\n\n if (Object.keys(ctx.defs).length > 0) {\n result.$defs = ctx.defs;\n }\n\n return result;\n}\n\n// =============================================================================\n// ELEMENT TRAVERSAL\n// =============================================================================\n\n/**\n * Recursively visits all IR elements, collecting field schemas and required names.\n *\n * Groups and conditionals are transparent to the schema — their children are\n * lifted to the enclosing level (per the JSON Schema vocabulary spec §1.2).\n */\nfunction collectFields(\n elements: readonly FormIRElement[],\n properties: Record<string, JsonSchema2020>,\n required: string[],\n ctx: GeneratorContext\n): void {\n for (const element of elements) {\n switch (element.kind) {\n case \"field\":\n properties[element.name] = generateFieldSchema(element, ctx);\n if (element.required) {\n required.push(element.name);\n }\n break;\n\n case \"group\":\n // Groups are UI-only; flatten children into the enclosing schema.\n collectFields(element.elements, properties, required, ctx);\n break;\n\n case \"conditional\":\n // Conditional visibility is UI-only; all fields remain in the schema.\n collectFields(element.elements, properties, required, ctx);\n break;\n\n default: {\n const _exhaustive: never = element;\n void _exhaustive;\n }\n }\n }\n}\n\n// =============================================================================\n// FIELD SCHEMA GENERATION\n// =============================================================================\n\n/**\n * Generates the JSON Schema sub-schema for a single FieldNode.\n */\nfunction generateFieldSchema(field: FieldNode, ctx: GeneratorContext): JsonSchema2020 {\n const schema = generateTypeNode(field.type, ctx);\n const itemStringSchema =\n schema.type === \"array\" && schema.items?.type === \"string\" ? schema.items : undefined;\n\n // Partition constraints into direct (no path) and path-targeted.\n const directConstraints: ConstraintNode[] = [];\n const itemConstraints: ConstraintNode[] = [];\n const pathConstraints: ConstraintNode[] = [];\n for (const c of field.constraints) {\n if (c.path) {\n pathConstraints.push(c);\n } else if (itemStringSchema !== undefined && isStringItemConstraint(c)) {\n itemConstraints.push(c);\n } else {\n directConstraints.push(c);\n }\n }\n\n // Apply direct constraints. multipleOf:1 on a number type is a special case:\n // it promotes the type to \"integer\" and removes the multipleOf keyword.\n applyConstraints(schema, directConstraints, ctx);\n\n if (itemStringSchema !== undefined) {\n applyConstraints(itemStringSchema, itemConstraints, ctx);\n }\n\n // Apply annotations (title, description, default, deprecated, etc.).\n const rootAnnotations: AnnotationNode[] = [];\n const itemAnnotations: AnnotationNode[] = [];\n for (const annotation of field.annotations) {\n if (itemStringSchema !== undefined && annotation.annotationKind === \"format\") {\n itemAnnotations.push(annotation);\n } else {\n rootAnnotations.push(annotation);\n }\n }\n\n applyAnnotations(schema, rootAnnotations, ctx);\n if (itemStringSchema !== undefined) {\n applyAnnotations(itemStringSchema, itemAnnotations, ctx);\n }\n\n // If no path-targeted constraints, return as-is.\n if (pathConstraints.length === 0) {\n return schema;\n }\n\n return applyPathTargetedConstraints(schema, pathConstraints, ctx);\n}\n\n/**\n * Returns true if a constraint should be applied to the `items` schema of a\n * primitive `string[]` rather than the array itself.\n *\n * `@const` is intentionally excluded: arrays cannot carry primitive const\n * constraints in FormSpec, so `@const` on `string[]` remains a validation\n * error instead of targeting the item schema.\n */\nfunction isStringItemConstraint(constraint: ConstraintNode): boolean {\n switch (constraint.constraintKind) {\n case \"minLength\":\n case \"maxLength\":\n case \"pattern\":\n return true;\n default:\n return false;\n }\n}\n\n/**\n * Applies path-targeted constraints to a schema via allOf composition.\n *\n * For $ref schemas: wraps in allOf with property overrides.\n * For inline object schemas: applies directly to nested properties.\n * For array schemas: applies path constraints to the items sub-schema.\n */\nfunction applyPathTargetedConstraints(\n schema: JsonSchema2020,\n pathConstraints: readonly ConstraintNode[],\n ctx: GeneratorContext\n): JsonSchema2020 {\n // Array transparency: path-targeted constraints target the item type.\n if (schema.type === \"array\" && schema.items) {\n schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx);\n return schema;\n }\n\n // Group path constraints by target field name (first path segment).\n // Callers guarantee all entries have a defined `path` (filtered upstream).\n const byTarget = new Map<string, ConstraintNode[]>();\n for (const c of pathConstraints) {\n const target = c.path?.segments[0];\n if (!target) continue;\n const group = byTarget.get(target) ?? [];\n group.push(c);\n byTarget.set(target, group);\n }\n\n // Build the property overrides object.\n const propertyOverrides: Record<string, JsonSchema2020> = {};\n for (const [target, constraints] of byTarget) {\n const subSchema: JsonSchema2020 = {};\n applyConstraints(subSchema, constraints, ctx);\n propertyOverrides[target] = subSchema;\n }\n\n // $ref schema: wrap in allOf to preserve $ref semantics while adding overrides.\n if (schema.$ref) {\n const { $ref, ...rest } = schema;\n const refPart: JsonSchema2020 = { $ref };\n const overridePart: JsonSchema2020 = {\n properties: propertyOverrides,\n ...rest,\n };\n return { allOf: [refPart, overridePart] };\n }\n\n // Inline object schema: merge property overrides directly where possible.\n if (schema.type === \"object\" && schema.properties) {\n const missingOverrides: Record<string, JsonSchema2020> = {};\n\n for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {\n if (schema.properties[target]) {\n Object.assign(schema.properties[target], overrideSchema);\n } else {\n // Do not introduce new properties directly; compose via allOf instead\n // to preserve additionalProperties semantics on the base object.\n missingOverrides[target] = overrideSchema;\n }\n }\n\n if (Object.keys(missingOverrides).length === 0) {\n return schema;\n }\n\n return {\n allOf: [schema, { properties: missingOverrides }],\n };\n }\n\n // allOf schema (already composed): add property overrides as another member.\n if (schema.allOf) {\n schema.allOf = [...schema.allOf, { properties: propertyOverrides }];\n return schema;\n }\n\n // Fallback: for non-object/non-$ref schemas, path-targeted constraints do not\n // apply in a meaningful way. Return the original schema unchanged and rely\n // on validation diagnostics to surface misuse of path-based constraints.\n return schema;\n}\n\n// =============================================================================\n// TYPE NODE GENERATION\n// =============================================================================\n\n/**\n * Converts a TypeNode to a JSON Schema sub-schema.\n *\n * This function is intentionally exhaustive — all TypeNode variants are handled.\n * TypeScript's exhaustiveness check via the default branch ensures new variants\n * added to the IR are caught at compile time.\n */\nfunction generateTypeNode(type: TypeNode, ctx: GeneratorContext): JsonSchema2020 {\n switch (type.kind) {\n case \"primitive\":\n return generatePrimitiveType(type);\n\n case \"enum\":\n return generateEnumType(type);\n\n case \"array\":\n return generateArrayType(type, ctx);\n\n case \"object\":\n return generateObjectType(type, ctx);\n\n case \"record\":\n return generateRecordType(type, ctx);\n\n case \"union\":\n return generateUnionType(type, ctx);\n\n case \"reference\":\n return generateReferenceType(type);\n\n case \"dynamic\":\n return generateDynamicType(type);\n\n case \"custom\":\n return generateCustomType(type, ctx);\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = type;\n return _exhaustive;\n }\n }\n}\n\n/**\n * Maps primitive IR types to JSON Schema type keywords.\n *\n * Note: `integer` is NOT a primitive kind in the IR. Integer semantics are\n * expressed via a `multipleOf: 1` constraint on a number type; `applyConstraints`\n * handles the promotion (per the JSON Schema vocabulary spec §2.1).\n */\nfunction generatePrimitiveType(type: PrimitiveTypeNode): JsonSchema2020 {\n return { type: type.primitiveKind };\n}\n\n/**\n * Generates JSON Schema for a static enum type.\n *\n * When any member has a displayName, the output uses the `oneOf` form with\n * per-member `const`/`title` entries (per the JSON Schema vocabulary spec §2.3). Otherwise the\n * flat `enum` keyword is used (simpler, equally valid).\n */\nfunction generateEnumType(type: EnumTypeNode): JsonSchema2020 {\n const hasDisplayNames = type.members.some((m) => m.displayName !== undefined);\n\n if (hasDisplayNames) {\n return {\n oneOf: type.members.map((m) => {\n const entry: JsonSchema2020 = { const: m.value };\n if (m.displayName !== undefined) {\n entry.title = m.displayName;\n }\n return entry;\n }),\n };\n }\n\n return { enum: type.members.map((m) => m.value) };\n}\n\n/**\n * Generates JSON Schema for an array type.\n * Per 2020-12, `items` is a single schema (not an array); tuple types use\n * `prefixItems` + `items: false`.\n */\nfunction generateArrayType(type: ArrayTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n return {\n type: \"array\",\n items: generateTypeNode(type.items, ctx),\n };\n}\n\n/**\n * Generates JSON Schema for an object type.\n *\n * `additionalProperties` is emitted only when the IR explicitly closes the\n * object. Ordinary static object types now canonicalize to\n * `additionalProperties: true`, which omits the keyword per spec 003 §2.5.\n */\nfunction generateObjectType(type: ObjectTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n for (const prop of type.properties) {\n properties[prop.name] = generatePropertySchema(prop, ctx);\n if (!prop.optional) {\n required.push(prop.name);\n }\n }\n\n const schema: JsonSchema2020 = { type: \"object\", properties };\n\n if (required.length > 0) {\n schema.required = required;\n }\n\n if (!type.additionalProperties) {\n schema.additionalProperties = false;\n }\n\n return schema;\n}\n\n/**\n * Generates JSON Schema for a record (dictionary) type per spec 003 §2.5.\n *\n * `Record<string, T>` and `{ [k: string]: T }` both emit:\n * `{ \"type\": \"object\", \"additionalProperties\": <T schema> }`\n *\n * No `properties` key is emitted — the record has no named properties.\n */\nfunction generateRecordType(type: RecordTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n return {\n type: \"object\",\n additionalProperties: generateTypeNode(type.valueType, ctx),\n };\n}\n\n/**\n * Generates a schema for an ObjectProperty, applying its use-site constraints\n * and annotations (per the JSON Schema vocabulary spec §5.4 — inline allOf at use site).\n */\nfunction generatePropertySchema(prop: ObjectProperty, ctx: GeneratorContext): JsonSchema2020 {\n const schema = generateTypeNode(prop.type, ctx);\n applyConstraints(schema, prop.constraints, ctx);\n applyAnnotations(schema, prop.annotations, ctx);\n return schema;\n}\n\n/**\n * Generates JSON Schema for a union type.\n *\n * Union handling strategy (per spec 003):\n * - Boolean shorthand: `true | false` → `{ type: \"boolean\" }` (not oneOf/anyOf)\n * - Nullable unions: `T | null` → `{ \"oneOf\": [<T schema>, { \"type\": \"null\" }] }` (§2.3)\n * - All other unions → `anyOf` (members may overlap; discriminated union\n * detection is deferred to a future phase per design doc 003 §7.4)\n */\nfunction generateUnionType(type: UnionTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n // Boolean shorthand: union of true-literal and false-literal → type: \"boolean\"\n if (isBooleanUnion(type)) {\n return { type: \"boolean\" };\n }\n\n // Nullable union: `T | null` → oneOf per spec 003 §2.3.\n // A nullable union is any union where exactly one member is the null primitive.\n if (isNullableUnion(type)) {\n return {\n oneOf: type.members.map((m) => generateTypeNode(m, ctx)),\n };\n }\n\n // Default: anyOf for non-discriminated object unions (spec 003 §7.4).\n // Discriminated union detection (shared required property with distinct consts)\n // is deferred to a future phase.\n return {\n anyOf: type.members.map((m) => generateTypeNode(m, ctx)),\n };\n}\n\n/**\n * Returns true if the union is `true | false` (boolean shorthand).\n */\nfunction isBooleanUnion(type: UnionTypeNode): boolean {\n if (type.members.length !== 2) return false;\n const kinds = type.members.map((m) => m.kind);\n // Both must be primitives; check if both are \"boolean\" primitives.\n // The IR currently does not have a boolean literal node, so boolean union\n // is represented as two primitive boolean members.\n return (\n kinds.every((k) => k === \"primitive\") &&\n type.members.every((m) => m.kind === \"primitive\" && m.primitiveKind === \"boolean\")\n );\n}\n\n/**\n * Returns true if the union is a nullable wrapper union (`T | null` for any T).\n *\n * A nullable union is a two-member union where exactly one member is the `null`\n * primitive type and the other member is any non-null type.\n * Per spec 003 §2.3, nullable unions map to `oneOf` (not `anyOf`).\n */\nfunction isNullableUnion(type: UnionTypeNode): boolean {\n if (type.members.length !== 2) return false;\n const nullCount = type.members.filter(\n (m) => m.kind === \"primitive\" && m.primitiveKind === \"null\"\n ).length;\n return nullCount === 1;\n}\n\n/**\n * Generates JSON Schema for a reference type.\n *\n * The referenced type's schema is stored in `$defs` (seeded from the type\n * registry before traversal begins). The reference simply emits a `$ref`.\n */\nfunction generateReferenceType(type: ReferenceTypeNode): JsonSchema2020 {\n return { $ref: `#/$defs/${type.name}` };\n}\n\n/**\n * Generates JSON Schema for a dynamic type (runtime-resolved enum or schema).\n *\n * Dynamic enums emit `x-formspec-source` and optionally `x-formspec-params`.\n * Dynamic schemas emit `x-formspec-schemaSource` with `additionalProperties: true`\n * since the actual schema is determined at runtime (per the JSON Schema vocabulary spec §3.2).\n */\nfunction generateDynamicType(type: DynamicTypeNode): JsonSchema2020 {\n if (type.dynamicKind === \"enum\") {\n const schema: JsonSchema2020 = {\n type: \"string\",\n \"x-formspec-source\": type.sourceKey,\n };\n if (type.parameterFields.length > 0) {\n schema[\"x-formspec-params\"] = [...type.parameterFields];\n }\n return schema;\n }\n\n // dynamicKind === \"schema\"\n return {\n type: \"object\",\n additionalProperties: true,\n \"x-formspec-schemaSource\": type.sourceKey,\n };\n}\n\n// =============================================================================\n// CONSTRAINT APPLICATION\n// =============================================================================\n\n/**\n * Applies constraint nodes onto an existing JSON Schema object (mutates in place).\n *\n * All callers pass freshly-created objects so there is no aliasing risk.\n *\n * Special rule (per the JSON Schema vocabulary spec §2.1): `multipleOf: 1` on a `\"number\"` type\n * promotes to `\"integer\"` and suppresses the `multipleOf` keyword (integer is a\n * subtype of number; expressing it via multipleOf:1 is redundant).\n *\n * Path-targeted constraints are handled separately by `applyPathTargetedConstraints`.\n */\nfunction applyConstraints(\n schema: JsonSchema2020,\n constraints: readonly ConstraintNode[],\n ctx: GeneratorContext\n): void {\n for (const constraint of constraints) {\n switch (constraint.constraintKind) {\n case \"minimum\":\n schema.minimum = constraint.value;\n break;\n\n case \"maximum\":\n schema.maximum = constraint.value;\n break;\n\n case \"exclusiveMinimum\":\n schema.exclusiveMinimum = constraint.value;\n break;\n\n case \"exclusiveMaximum\":\n schema.exclusiveMaximum = constraint.value;\n break;\n\n case \"multipleOf\": {\n const { value } = constraint;\n if (value === 1 && schema.type === \"number\") {\n // Promote number → integer; omit the multipleOf keyword (redundant).\n schema.type = \"integer\";\n } else {\n schema.multipleOf = value;\n }\n break;\n }\n\n case \"minLength\":\n schema.minLength = constraint.value;\n break;\n\n case \"maxLength\":\n schema.maxLength = constraint.value;\n break;\n\n case \"minItems\":\n schema.minItems = constraint.value;\n break;\n\n case \"maxItems\":\n schema.maxItems = constraint.value;\n break;\n\n case \"pattern\":\n schema.pattern = constraint.pattern;\n break;\n\n case \"uniqueItems\":\n schema.uniqueItems = constraint.value;\n break;\n\n case \"const\":\n schema.const = constraint.value;\n break;\n\n case \"allowedMembers\":\n // EnumMemberConstraintNode — not yet emitted to JSON Schema (Phase 6 validation).\n break;\n\n case \"custom\":\n applyCustomConstraint(schema, constraint, ctx);\n break;\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = constraint;\n void _exhaustive;\n }\n }\n }\n}\n\n// =============================================================================\n// ANNOTATION APPLICATION\n// =============================================================================\n\n/**\n * Applies annotation nodes onto an existing JSON Schema object (mutates in place).\n *\n * Mapping per the JSON Schema vocabulary spec §2.8:\n * - `displayName` → `title`\n * - `description` → `description`\n * - `defaultValue` → `default`\n * - `deprecated` → `deprecated: true` (2020-12 standard annotation)\n * - `format` → `format`\n *\n * UI-only annotations (`placeholder`, `formatHint`) are silently ignored here —\n * they belong in the UI Schema, not the data schema.\n */\nfunction applyAnnotations(\n schema: JsonSchema2020,\n annotations: readonly AnnotationNode[],\n ctx: GeneratorContext\n): void {\n for (const annotation of annotations) {\n switch (annotation.annotationKind) {\n case \"displayName\":\n schema.title = annotation.value;\n break;\n\n case \"description\":\n schema.description = annotation.value;\n break;\n\n case \"defaultValue\":\n schema.default = annotation.value;\n break;\n\n case \"format\":\n schema.format = annotation.value;\n break;\n\n case \"deprecated\":\n schema.deprecated = true;\n if (annotation.message !== undefined && annotation.message !== \"\") {\n schema[\"x-formspec-deprecation-description\"] = annotation.message;\n }\n break;\n\n case \"placeholder\":\n // UI-only — belongs in UI Schema, not emitted here.\n break;\n\n case \"formatHint\":\n // UI-only — belongs in UI Schema, not emitted here.\n break;\n\n case \"custom\":\n applyCustomAnnotation(schema, annotation, ctx);\n break;\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = annotation;\n void _exhaustive;\n }\n }\n }\n}\n\nfunction generateCustomType(type: CustomTypeNode, ctx: GeneratorContext): JsonSchema2020 {\n const registration = ctx.extensionRegistry?.findType(type.typeId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom type \"${type.typeId}\" without a matching extension registration`\n );\n }\n\n // Trust boundary: extensions are responsible for returning valid JSON Schema.\n // Core only depends on Record<string, unknown> here, so we cast at the edge.\n return registration.toJsonSchema(type.payload, ctx.vendorPrefix) as JsonSchema2020;\n}\n\nfunction applyCustomConstraint(\n schema: JsonSchema2020,\n constraint: Extract<ConstraintNode, { constraintKind: \"custom\" }>,\n ctx: GeneratorContext\n): void {\n const registration = ctx.extensionRegistry?.findConstraint(constraint.constraintId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom constraint \"${constraint.constraintId}\" without a matching extension registration`\n );\n }\n\n assignVendorPrefixedExtensionKeywords(\n schema,\n registration.toJsonSchema(constraint.payload, ctx.vendorPrefix),\n ctx.vendorPrefix,\n `custom constraint \"${constraint.constraintId}\"`\n );\n}\n\nfunction applyCustomAnnotation(\n schema: JsonSchema2020,\n annotation: Extract<AnnotationNode, { annotationKind: \"custom\" }>,\n ctx: GeneratorContext\n): void {\n const registration = ctx.extensionRegistry?.findAnnotation(annotation.annotationId);\n if (registration === undefined) {\n throw new Error(\n `Cannot generate JSON Schema for custom annotation \"${annotation.annotationId}\" without a matching extension registration`\n );\n }\n\n if (registration.toJsonSchema === undefined) {\n return;\n }\n\n assignVendorPrefixedExtensionKeywords(\n schema,\n registration.toJsonSchema(annotation.value, ctx.vendorPrefix),\n ctx.vendorPrefix,\n `custom annotation \"${annotation.annotationId}\"`\n );\n}\n\nfunction assignVendorPrefixedExtensionKeywords(\n schema: JsonSchema2020,\n extensionSchema: Record<string, unknown>,\n vendorPrefix: string,\n source: string\n): void {\n for (const [key, value] of Object.entries(extensionSchema)) {\n if (!key.startsWith(`${vendorPrefix}-`)) {\n throw new Error(\n `Cannot apply ${source}: extension hooks may only emit \"${vendorPrefix}-*\" JSON Schema keywords`\n );\n }\n schema[key as `x-${string}`] = value;\n }\n}\n","/**\n * Zod schemas for JSON Forms UI Schema.\n *\n * These schemas are the source of truth for UI Schema validation.\n * TypeScript types are derived from these schemas via `z.infer<>`.\n *\n * @see https://jsonforms.io/docs/uischema/\n */\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Primitive helpers\n// =============================================================================\n\n/** JSON Pointer string (e.g., \"#/properties/fieldName\") */\nconst jsonPointerSchema = z.string();\n\n// =============================================================================\n// Rule Effect and Element Type enums\n// =============================================================================\n\n/**\n * Zod schema for rule effect values.\n */\nexport const ruleEffectSchema = z.enum([\"SHOW\", \"HIDE\", \"ENABLE\", \"DISABLE\"]);\n\n/**\n * Rule effect types for conditional visibility.\n */\nexport type RuleEffect = z.infer<typeof ruleEffectSchema>;\n\n/**\n * Zod schema for UI Schema element type strings.\n */\nexport const uiSchemaElementTypeSchema = z.enum([\n \"Control\",\n \"VerticalLayout\",\n \"HorizontalLayout\",\n \"Group\",\n \"Categorization\",\n \"Category\",\n \"Label\",\n]);\n\n/**\n * UI Schema element types.\n */\nexport type UISchemaElementType = z.infer<typeof uiSchemaElementTypeSchema>;\n\n// =============================================================================\n// Rule Condition Schema (recursive)\n// =============================================================================\n\n// Forward-declare the recursive TypeScript type.\n// We use an interface here (rather than z.infer<>) because the recursive\n// z.lazy() type annotation requires us to pre-declare the shape.\n/**\n * JSON Schema subset used in rule conditions.\n */\nexport interface RuleConditionSchema {\n const?: unknown;\n enum?: readonly unknown[];\n type?: string;\n not?: RuleConditionSchema;\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n minLength?: number;\n properties?: Record<string, RuleConditionSchema>;\n required?: string[];\n allOf?: RuleConditionSchema[];\n}\n\n// Build the Zod schema referencing the pre-declared interface.\n// We use z.ZodType<RuleConditionSchema> so the recursive reference works.\n// The interface uses `?` (exact optional), and z.ZodType checks output only,\n// so the optional fields (which Zod infers as `T | undefined`) are compatible\n// because `T | undefined` is assignable to the optional field slot.\n//\n// @ts-expect-error -- exactOptionalPropertyTypes: the Zod output type for optional\n// fields is `T | undefined`, but our interface uses `?` (exact optional, key may\n// be absent). This is a known mismatch when using z.ZodType<T> with\n// exactOptionalPropertyTypes:true; the runtime behavior is correct.\nexport const ruleConditionSchema: z.ZodType<RuleConditionSchema> = z.lazy(() =>\n z\n .object({\n const: z.unknown().optional(),\n enum: z.array(z.unknown()).readonly().optional(),\n type: z.string().optional(),\n not: ruleConditionSchema.optional(),\n minimum: z.number().optional(),\n maximum: z.number().optional(),\n exclusiveMinimum: z.number().optional(),\n exclusiveMaximum: z.number().optional(),\n minLength: z.number().optional(),\n properties: z.record(z.string(), ruleConditionSchema).optional(),\n required: z.array(z.string()).optional(),\n allOf: z.array(ruleConditionSchema).optional(),\n })\n .strict()\n);\n\n// =============================================================================\n// Schema-Based Condition and Rule\n// =============================================================================\n\n/**\n * Zod schema for a schema-based rule condition.\n */\nexport const schemaBasedConditionSchema = z\n .object({\n scope: jsonPointerSchema,\n schema: ruleConditionSchema,\n })\n .strict();\n\n/**\n * Condition for a rule.\n */\nexport type SchemaBasedCondition = z.infer<typeof schemaBasedConditionSchema>;\n\n/**\n * Zod schema for a UI Schema rule.\n */\nexport const ruleSchema = z\n .object({\n effect: ruleEffectSchema,\n condition: schemaBasedConditionSchema,\n })\n .strict();\n\n/**\n * Rule for conditional element visibility/enablement.\n */\nexport type Rule = z.infer<typeof ruleSchema>;\n\n// =============================================================================\n// UI Schema Element Schemas (recursive via z.lazy)\n// =============================================================================\n\n// Forward-declare UISchemaElement so layout schemas can reference it.\n// We declare the type up-front and wire the Zod schema below.\n/**\n * Union of all UI Schema element types.\n */\nexport type UISchemaElement =\n | ControlElement\n | VerticalLayout\n | HorizontalLayout\n | GroupLayout\n | Categorization\n | Category\n | LabelElement;\n\n// The Zod schema for UISchemaElement is defined as a const using z.lazy(),\n// which defers evaluation until first use. This allows all element schemas\n// below to be referenced even though they are declared after this line.\nexport const uiSchemaElementSchema: z.ZodType<UISchemaElement> = z.lazy(() =>\n z.union([\n controlSchema,\n verticalLayoutSchema,\n horizontalLayoutSchema,\n groupLayoutSchema,\n categorizationSchema,\n categorySchema,\n labelElementSchema,\n ])\n) as z.ZodType<UISchemaElement>;\n\n// -----------------------------------------------------------------------------\n// Control\n// -----------------------------------------------------------------------------\n\n/**\n * Zod schema for a Control element.\n */\nexport const controlSchema = z\n .object({\n type: z.literal(\"Control\"),\n scope: jsonPointerSchema,\n label: z.union([z.string(), z.literal(false)]).optional(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\n/**\n * A Control element that binds to a JSON Schema property.\n */\nexport type ControlElement = z.infer<typeof controlSchema>;\n\n// -----------------------------------------------------------------------------\n// VerticalLayout\n// -----------------------------------------------------------------------------\n\n// Pre-declare the interface so the Zod schema can reference UISchemaElement.\n/**\n * A vertical layout element.\n */\nexport interface VerticalLayout {\n type: \"VerticalLayout\";\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const verticalLayoutSchema: z.ZodType<VerticalLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"VerticalLayout\"),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// HorizontalLayout\n// -----------------------------------------------------------------------------\n\n/**\n * A horizontal layout element.\n */\nexport interface HorizontalLayout {\n type: \"HorizontalLayout\";\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const horizontalLayoutSchema: z.ZodType<HorizontalLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"HorizontalLayout\"),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// GroupLayout\n// -----------------------------------------------------------------------------\n\n/**\n * A group element with a label.\n */\nexport interface GroupLayout {\n type: \"Group\";\n label: string;\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const groupLayoutSchema: z.ZodType<GroupLayout> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Group\"),\n label: z.string(),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// Category\n// -----------------------------------------------------------------------------\n\n/**\n * A Category element, used inside a Categorization layout.\n */\nexport interface Category {\n type: \"Category\";\n label: string;\n elements: UISchemaElement[];\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const categorySchema: z.ZodType<Category> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Category\"),\n label: z.string(),\n elements: z.array(uiSchemaElementSchema),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// Categorization\n// -----------------------------------------------------------------------------\n\n/**\n * A Categorization element (tab-based layout).\n */\nexport interface Categorization {\n type: \"Categorization\";\n elements: Category[];\n label?: string | undefined;\n rule?: Rule | undefined;\n options?: Record<string, unknown> | undefined;\n [k: string]: unknown;\n}\n\nexport const categorizationSchema: z.ZodType<Categorization> = z.lazy(() =>\n z\n .object({\n type: z.literal(\"Categorization\"),\n elements: z.array(categorySchema),\n label: z.string().optional(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough()\n);\n\n// -----------------------------------------------------------------------------\n// LabelElement\n// -----------------------------------------------------------------------------\n\n/**\n * Zod schema for a Label element.\n */\nexport const labelElementSchema = z\n .object({\n type: z.literal(\"Label\"),\n text: z.string(),\n rule: ruleSchema.optional(),\n options: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\n/**\n * A Label element for displaying static text.\n */\nexport type LabelElement = z.infer<typeof labelElementSchema>;\n\n// =============================================================================\n// Root UISchema\n// =============================================================================\n\n/**\n * Root UI Schema (always a layout — not a Control, Category, or Label).\n */\nexport type UISchema = VerticalLayout | HorizontalLayout | GroupLayout | Categorization;\n\n/**\n * Zod schema for the root UI Schema (layout types only).\n */\nexport const uiSchema: z.ZodType<UISchema> = z.lazy(() =>\n z.union([verticalLayoutSchema, horizontalLayoutSchema, groupLayoutSchema, categorizationSchema])\n) as z.ZodType<UISchema>;\n","/**\n * JSON Forms UI Schema generator that operates on the canonical FormIR.\n *\n * This generator consumes the IR produced by the Canonicalize phase and\n * produces a JSON Forms UI Schema. All downstream UI Schema generation\n * should use this module for UI Schema generation.\n */\n\nimport type { FormIR, FormIRElement, FieldNode, GroupLayoutNode } from \"@formspec/core\";\nimport type {\n UISchema,\n UISchemaElement,\n ControlElement,\n GroupLayout,\n Rule,\n RuleConditionSchema,\n} from \"./types.js\";\nimport { uiSchema as uiSchemaValidator } from \"./schema.js\";\nimport { z } from \"zod\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/**\n * Parses a value through a Zod schema, converting validation errors to a\n * descriptive Error.\n */\nfunction parseOrThrow<T>(schema: z.ZodType<T>, value: unknown, label: string): T {\n try {\n return schema.parse(value);\n } catch (error) {\n if (error instanceof z.ZodError) {\n throw new Error(\n `Generated ${label} failed validation:\\n${error.issues.map((i) => ` ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\")}`\n );\n }\n throw error;\n }\n}\n\n/**\n * Converts a field name to a JSON Pointer scope string.\n */\nfunction fieldToScope(fieldName: string): string {\n return `#/properties/${fieldName}`;\n}\n\n/**\n * Creates a SHOW rule for a single conditional field/value pair.\n */\nfunction createShowRule(fieldName: string, value: unknown): Rule {\n return {\n effect: \"SHOW\",\n condition: {\n scope: fieldToScope(fieldName),\n schema: { const: value },\n },\n };\n}\n\n/**\n * Combines two SHOW rules into a single rule using an allOf condition.\n *\n * When elements are nested inside multiple conditionals, all parent conditions\n * must be met for the element to be visible. This function flattens both\n * conditions into a single rule using a top-level allOf so JSON Forms evaluates\n * every predicate simultaneously without nesting rule fragments.\n */\nfunction flattenConditionSchema(scope: string, schema: RuleConditionSchema): RuleConditionSchema[] {\n if (schema.allOf === undefined) {\n if (scope === \"#\") {\n return [schema];\n }\n\n const fieldName = scope.replace(\"#/properties/\", \"\");\n return [\n {\n properties: {\n [fieldName]: schema,\n },\n },\n ];\n }\n\n return schema.allOf.flatMap((member) => flattenConditionSchema(scope, member));\n}\n\nfunction combineRules(parentRule: Rule, childRule: Rule): Rule {\n return {\n effect: \"SHOW\",\n condition: {\n scope: \"#\",\n schema: {\n allOf: [\n ...flattenConditionSchema(parentRule.condition.scope, parentRule.condition.schema),\n ...flattenConditionSchema(childRule.condition.scope, childRule.condition.schema),\n ],\n },\n },\n };\n}\n\n// =============================================================================\n// ELEMENT CONVERSION\n// =============================================================================\n\n/**\n * Converts a FieldNode from the IR to a ControlElement.\n *\n * The label is sourced from the first `displayName` annotation on the field,\n * matching how the chain DSL propagates the `label` option through the\n * canonicalization phase.\n */\nfunction fieldNodeToControl(field: FieldNode, parentRule?: Rule): ControlElement {\n const displayNameAnnotation = field.annotations.find((a) => a.annotationKind === \"displayName\");\n const placeholderAnnotation = field.annotations.find((a) => a.annotationKind === \"placeholder\");\n\n const control: ControlElement = {\n type: \"Control\",\n scope: fieldToScope(field.name),\n ...(displayNameAnnotation !== undefined && { label: displayNameAnnotation.value }),\n ...(placeholderAnnotation !== undefined && {\n options: { placeholder: placeholderAnnotation.value },\n }),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n\n return control;\n}\n\n/**\n * Converts a GroupLayoutNode from the IR to a GroupLayout element.\n *\n * The group's children are recursively converted; the optional parent rule is\n * forwarded to nested elements so that a group inside a conditional inherits\n * the visibility rule.\n */\nfunction groupNodeToLayout(group: GroupLayoutNode, parentRule?: Rule): GroupLayout {\n return {\n type: \"Group\",\n label: group.label,\n elements: irElementsToUiSchema(group.elements, parentRule),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n}\n\n/**\n * Converts an array of IR elements to UI Schema elements.\n *\n * @param elements - The IR elements to convert\n * @param parentRule - Optional rule inherited from a parent ConditionalLayoutNode\n * @returns Array of UI Schema elements\n */\nfunction irElementsToUiSchema(\n elements: readonly FormIRElement[],\n parentRule?: Rule\n): UISchemaElement[] {\n const result: UISchemaElement[] = [];\n\n for (const element of elements) {\n switch (element.kind) {\n case \"field\": {\n result.push(fieldNodeToControl(element, parentRule));\n break;\n }\n\n case \"group\": {\n result.push(groupNodeToLayout(element, parentRule));\n break;\n }\n\n case \"conditional\": {\n // Build the rule for this conditional level.\n const newRule = createShowRule(element.fieldName, element.value);\n // Combine with the inherited parent rule for nested conditionals.\n const combinedRule = parentRule !== undefined ? combineRules(parentRule, newRule) : newRule;\n // Children are flattened into the parent container with the combined\n // rule attached.\n const childElements = irElementsToUiSchema(element.elements, combinedRule);\n result.push(...childElements);\n break;\n }\n\n default: {\n const _exhaustive: never = element;\n void _exhaustive;\n throw new Error(\"Unhandled IR element kind\");\n }\n }\n }\n\n return result;\n}\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Generates a JSON Forms UI Schema from a canonical `FormIR`.\n *\n * Mapping rules:\n * - `FieldNode` → `ControlElement` with `scope: \"#/properties/<name>\"`\n * - `displayName` annotation → `label` on the `ControlElement`\n * - `GroupLayoutNode` → `GroupLayout` with recursively converted `elements`\n * - `ConditionalLayoutNode` → children flattened with a `SHOW` rule\n * - Nested conditionals → combined `allOf` rule\n * - Root wrapper is always `{ type: \"VerticalLayout\", elements: [...] }`\n *\n * @example\n * ```typescript\n * const ir = canonicalizeDSL(\n * formspec(\n * group(\"Customer\", field.text(\"name\", { label: \"Name\" })),\n * when(is(\"status\", \"draft\"), field.text(\"notes\", { label: \"Notes\" })),\n * )\n * );\n *\n * const uiSchema = generateUiSchemaFromIR(ir);\n * // {\n * // type: \"VerticalLayout\",\n * // elements: [\n * // {\n * // type: \"Group\",\n * // label: \"Customer\",\n * // elements: [{ type: \"Control\", scope: \"#/properties/name\", label: \"Name\" }]\n * // },\n * // {\n * // type: \"Control\",\n * // scope: \"#/properties/notes\",\n * // label: \"Notes\",\n * // rule: { effect: \"SHOW\", condition: { scope: \"#/properties/status\", schema: { const: \"draft\" } } }\n * // }\n * // ]\n * // }\n * ```\n *\n * @param ir - The canonical FormIR produced by the Canonicalize phase\n * @returns A validated JSON Forms UI Schema\n */\nexport function generateUiSchemaFromIR(ir: FormIR): UISchema {\n const result: UISchema = {\n type: \"VerticalLayout\",\n elements: irElementsToUiSchema(ir.elements),\n };\n\n return parseOrThrow(uiSchemaValidator, result, \"UI Schema\");\n}\n","/**\n * Class schema generator.\n *\n * Generates JSON Schema 2020-12 and JSON Forms UI Schema from statically\n * analyzed class/interface/type alias declarations, routing through the\n * canonical FormIR pipeline.\n */\n\nimport type { UISchema } from \"../ui-schema/types.js\";\nimport {\n createProgramContext,\n findClassByName,\n findInterfaceByName,\n findTypeAliasByName,\n} from \"../analyzer/program.js\";\nimport {\n analyzeClassToIR,\n analyzeInterfaceToIR,\n analyzeTypeAliasToIR,\n type IRClassAnalysis,\n} from \"../analyzer/class-analyzer.js\";\nimport { canonicalizeTSDoc, type TSDocSource } from \"../canonicalize/index.js\";\nimport {\n generateJsonSchemaFromIR,\n type GenerateJsonSchemaFromIROptions,\n type JsonSchema2020,\n} from \"../json-schema/ir-generator.js\";\nimport { generateUiSchemaFromIR } from \"../ui-schema/ir-generator.js\";\n\n/**\n * Generated schemas for a class.\n */\nexport interface ClassSchemas {\n /** JSON Schema 2020-12 for validation */\n jsonSchema: JsonSchema2020;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema 2020-12 and UI Schema from an IR class analysis.\n *\n * Routes through the canonical IR pipeline:\n * IRClassAnalysis → canonicalizeTSDoc → FormIR → JSON Schema / UI Schema\n *\n * @param analysis - The IR analysis result (from analyzeClassToIR, analyzeInterfaceToIR, or analyzeTypeAliasToIR)\n * @param source - Optional source file metadata for provenance\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateClassSchemas(\n analysis: IRClassAnalysis,\n source?: TSDocSource,\n options?: GenerateJsonSchemaFromIROptions\n): ClassSchemas {\n const ir = canonicalizeTSDoc(analysis, source);\n return {\n jsonSchema: generateJsonSchemaFromIR(ir, options),\n uiSchema: generateUiSchemaFromIR(ir),\n };\n}\n\n/**\n * Options for generating schemas from a decorated class.\n */\nexport interface GenerateFromClassOptions extends GenerateJsonSchemaFromIROptions {\n /** Path to the TypeScript source file */\n filePath: string;\n /** Class name to analyze */\n className: string;\n}\n\n/**\n * Result of generating schemas from a decorated class.\n */\nexport interface GenerateFromClassResult {\n /** JSON Schema 2020-12 for validation */\n jsonSchema: JsonSchema2020;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema and UI Schema from a decorated TypeScript class.\n *\n * This is a high-level entry point that handles the entire pipeline:\n * creating a TypeScript program, finding the class, analyzing it to IR,\n * and generating schemas — all in one call.\n *\n * @example\n * ```typescript\n * const result = generateSchemasFromClass({\n * filePath: \"./src/forms.ts\",\n * className: \"UserForm\",\n * });\n * console.log(result.jsonSchema);\n * ```\n *\n * @param options - File path, class name, and optional compiler options\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateSchemasFromClass(\n options: GenerateFromClassOptions\n): GenerateFromClassResult {\n const ctx = createProgramContext(options.filePath);\n const classDecl = findClassByName(ctx.sourceFile, options.className);\n\n if (!classDecl) {\n throw new Error(`Class \"${options.className}\" not found in ${options.filePath}`);\n }\n\n const analysis = analyzeClassToIR(\n classDecl,\n ctx.checker,\n options.filePath,\n options.extensionRegistry\n );\n return generateClassSchemas(\n analysis,\n { file: options.filePath },\n {\n extensionRegistry: options.extensionRegistry,\n vendorPrefix: options.vendorPrefix,\n }\n );\n}\n\n/**\n * Options for generating schemas from a named type (class, interface, or type alias).\n */\nexport interface GenerateSchemasOptions extends GenerateJsonSchemaFromIROptions {\n /** Path to the TypeScript source file */\n filePath: string;\n /** Name of the exported class, interface, or type alias to analyze */\n typeName: string;\n}\n\n/**\n * Generates JSON Schema and UI Schema from a named TypeScript\n * type — a decorated class, an interface with TSDoc tags, or a type alias.\n *\n * This is the recommended entry point. It automatically detects whether\n * the name resolves to a class, interface, or type alias and uses the\n * appropriate IR analysis pipeline.\n *\n * @example\n * ```typescript\n * const result = generateSchemas({\n * filePath: \"./src/config.ts\",\n * typeName: \"DiscountConfig\",\n * });\n * ```\n *\n * @param options - File path and type name\n * @returns Generated JSON Schema and UI Schema\n */\nexport function generateSchemas(options: GenerateSchemasOptions): GenerateFromClassResult {\n const ctx = createProgramContext(options.filePath);\n const source: TSDocSource = { file: options.filePath };\n\n // Try class first\n const classDecl = findClassByName(ctx.sourceFile, options.typeName);\n if (classDecl) {\n const analysis = analyzeClassToIR(\n classDecl,\n ctx.checker,\n options.filePath,\n options.extensionRegistry\n );\n return generateClassSchemas(analysis, source, options);\n }\n\n // Try interface\n const interfaceDecl = findInterfaceByName(ctx.sourceFile, options.typeName);\n if (interfaceDecl) {\n const analysis = analyzeInterfaceToIR(\n interfaceDecl,\n ctx.checker,\n options.filePath,\n options.extensionRegistry\n );\n return generateClassSchemas(analysis, source, options);\n }\n\n // Try type alias\n const typeAlias = findTypeAliasByName(ctx.sourceFile, options.typeName);\n if (typeAlias) {\n const result = analyzeTypeAliasToIR(\n typeAlias,\n ctx.checker,\n options.filePath,\n options.extensionRegistry\n );\n if (result.ok) {\n return generateClassSchemas(result.analysis, source, options);\n }\n throw new Error(result.error);\n }\n\n throw new Error(\n `Type \"${options.typeName}\" not found as a class, interface, or type alias in ${options.filePath}`\n );\n}\n","/**\n * Constraint validator for the FormSpec IR.\n *\n * Performs the Validate pipeline phase:\n * - Contradiction detection between paired constraints\n * - Type applicability checks (e.g. numeric constraints on string fields)\n * - Custom constraint type applicability (when extension registry is provided)\n * - Unknown extension warnings (when a registry is provided)\n *\n * @packageDocumentation\n */\n\nimport type {\n FormIR,\n FormIRElement,\n FieldNode,\n TypeNode,\n ConstraintNode,\n NumericConstraintNode,\n LengthConstraintNode,\n EnumMemberConstraintNode,\n Provenance,\n ObjectProperty,\n JsonValue,\n} from \"@formspec/core\";\nimport { normalizeConstraintTagName } from \"@formspec/core\";\nimport type { ExtensionRegistry } from \"../extensions/index.js\";\n\n// =============================================================================\n// PUBLIC API TYPES\n// =============================================================================\n\n/**\n * A structured diagnostic produced by constraint validation.\n *\n * The `code` is a stable, machine-readable semantic identifier.\n * Examples: `CONTRADICTING_CONSTRAINTS`, `TYPE_MISMATCH`, `UNKNOWN_EXTENSION`.\n */\nexport interface ValidationDiagnostic {\n readonly code: string;\n readonly message: string;\n readonly severity: \"error\" | \"warning\";\n /** Location of the primary constraint involved in the violation. */\n readonly primaryLocation: Provenance;\n /** Related locations (e.g., the other side of a contradiction pair). */\n readonly relatedLocations: readonly Provenance[];\n}\n\n/** Result of validating a {@link FormIR}. */\nexport interface ValidationResult {\n readonly diagnostics: readonly ValidationDiagnostic[];\n /** `true` if there are no error-severity diagnostics (warnings are OK). */\n readonly valid: boolean;\n}\n\n/** Options for constraint validation. */\nexport interface ValidateIROptions {\n /** @deprecated Ignored. Diagnostic codes are semantic identifiers only. */\n readonly vendorPrefix?: string;\n /**\n * Extension registry for resolving custom constraint type applicability.\n * When provided, custom constraints with `applicableTypes` will be\n * validated against the field's type node kind. Custom constraints\n * whose IDs are absent from this registry emit a WARNING (UNKNOWN_EXTENSION).\n * When omitted, custom constraints are silently skipped.\n */\n readonly extensionRegistry?: ExtensionRegistry;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/** Mutable accumulator threaded through the validation walk. */\ninterface ValidationContext {\n readonly diagnostics: ValidationDiagnostic[];\n readonly extensionRegistry: ExtensionRegistry | undefined;\n readonly typeRegistry: FormIR[\"typeRegistry\"];\n}\n\n// =============================================================================\n// DIAGNOSTIC FACTORIES\n// =============================================================================\n\nfunction addContradiction(\n ctx: ValidationContext,\n message: string,\n primary: Provenance,\n related: Provenance\n): void {\n ctx.diagnostics.push({\n code: \"CONTRADICTING_CONSTRAINTS\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [related],\n });\n}\n\nfunction addTypeMismatch(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"TYPE_MISMATCH\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addUnknownExtension(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"UNKNOWN_EXTENSION\",\n message,\n severity: \"warning\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addUnknownPathTarget(ctx: ValidationContext, message: string, primary: Provenance): void {\n ctx.diagnostics.push({\n code: \"UNKNOWN_PATH_TARGET\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [],\n });\n}\n\nfunction addConstraintBroadening(\n ctx: ValidationContext,\n message: string,\n primary: Provenance,\n related: Provenance\n): void {\n ctx.diagnostics.push({\n code: \"CONSTRAINT_BROADENING\",\n message,\n severity: \"error\",\n primaryLocation: primary,\n relatedLocations: [related],\n });\n}\n\nfunction getExtensionIdFromConstraintId(constraintId: string): string | null {\n const separator = constraintId.lastIndexOf(\"/\");\n if (separator <= 0) {\n return null;\n }\n return constraintId.slice(0, separator);\n}\n\n// =============================================================================\n// CONSTRAINT NARROWING HELPERS\n// =============================================================================\n\n/** Extract the first numeric constraint with the given kind, if present. */\nfunction findNumeric(\n constraints: readonly ConstraintNode[],\n constraintKind: NumericConstraintNode[\"constraintKind\"]\n): NumericConstraintNode | undefined {\n return constraints.find((c): c is NumericConstraintNode => c.constraintKind === constraintKind);\n}\n\n/** Extract the first length constraint with the given kind, if present. */\nfunction findLength(\n constraints: readonly ConstraintNode[],\n constraintKind: LengthConstraintNode[\"constraintKind\"]\n): LengthConstraintNode | undefined {\n return constraints.find((c): c is LengthConstraintNode => c.constraintKind === constraintKind);\n}\n\n/** Extract all allowedMembers constraints. */\nfunction findAllowedMembers(\n constraints: readonly ConstraintNode[]\n): readonly EnumMemberConstraintNode[] {\n return constraints.filter(\n (c): c is EnumMemberConstraintNode => c.constraintKind === \"allowedMembers\"\n );\n}\n\nfunction findConstConstraints(\n constraints: readonly ConstraintNode[]\n): readonly Extract<ConstraintNode, { readonly constraintKind: \"const\" }>[] {\n return constraints.filter(\n (c): c is Extract<ConstraintNode, { readonly constraintKind: \"const\" }> =>\n c.constraintKind === \"const\"\n );\n}\n\nfunction jsonValueEquals(left: JsonValue, right: JsonValue): boolean {\n if (left === right) {\n return true;\n }\n\n if (Array.isArray(left) || Array.isArray(right)) {\n if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {\n return false;\n }\n\n return left.every((item, index) => jsonValueEquals(item, right[index] as JsonValue));\n }\n\n if (isJsonObject(left) || isJsonObject(right)) {\n if (!isJsonObject(left) || !isJsonObject(right)) {\n return false;\n }\n\n const leftKeys = Object.keys(left).sort();\n const rightKeys = Object.keys(right).sort();\n if (leftKeys.length !== rightKeys.length) {\n return false;\n }\n\n return leftKeys.every((key, index) => {\n const rightKey = rightKeys[index];\n if (rightKey !== key) {\n return false;\n }\n const leftValue = left[key];\n const rightValue = right[rightKey];\n return leftValue !== undefined && rightValue !== undefined && jsonValueEquals(leftValue, rightValue);\n });\n }\n\n return false;\n}\n\nfunction isJsonObject(value: JsonValue): value is Record<string, JsonValue> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\ntype OrderedBoundKind =\n | \"minimum\"\n | \"exclusiveMinimum\"\n | \"minLength\"\n | \"minItems\"\n | \"maximum\"\n | \"exclusiveMaximum\"\n | \"maxLength\"\n | \"maxItems\";\n\ntype OrderedBoundConstraint = Extract<\n ConstraintNode,\n { readonly constraintKind: OrderedBoundKind }\n>;\n\ntype OrderedBoundFamily =\n | \"numeric-lower\"\n | \"numeric-upper\"\n | \"minLength\"\n | \"minItems\"\n | \"maxLength\"\n | \"maxItems\";\n\nfunction isOrderedBoundConstraint(\n constraint: ConstraintNode\n): constraint is OrderedBoundConstraint {\n return (\n constraint.constraintKind === \"minimum\" ||\n constraint.constraintKind === \"exclusiveMinimum\" ||\n constraint.constraintKind === \"minLength\" ||\n constraint.constraintKind === \"minItems\" ||\n constraint.constraintKind === \"maximum\" ||\n constraint.constraintKind === \"exclusiveMaximum\" ||\n constraint.constraintKind === \"maxLength\" ||\n constraint.constraintKind === \"maxItems\"\n );\n}\n\nfunction pathKey(constraint: ConstraintNode): string {\n return constraint.path?.segments.join(\".\") ?? \"\";\n}\n\nfunction orderedBoundFamily(kind: OrderedBoundKind): OrderedBoundFamily {\n switch (kind) {\n case \"minimum\":\n case \"exclusiveMinimum\":\n return \"numeric-lower\";\n case \"maximum\":\n case \"exclusiveMaximum\":\n return \"numeric-upper\";\n case \"minLength\":\n return \"minLength\";\n case \"minItems\":\n return \"minItems\";\n case \"maxLength\":\n return \"maxLength\";\n case \"maxItems\":\n return \"maxItems\";\n default: {\n const _exhaustive: never = kind;\n return _exhaustive;\n }\n }\n}\n\nfunction isNumericLowerKind(kind: OrderedBoundKind): kind is \"minimum\" | \"exclusiveMinimum\" {\n return kind === \"minimum\" || kind === \"exclusiveMinimum\";\n}\n\nfunction isNumericUpperKind(kind: OrderedBoundKind): kind is \"maximum\" | \"exclusiveMaximum\" {\n return kind === \"maximum\" || kind === \"exclusiveMaximum\";\n}\n\nfunction describeConstraintTag(constraint: OrderedBoundConstraint): string {\n return `@${constraint.constraintKind}`;\n}\n\nfunction compareConstraintStrength(\n current: OrderedBoundConstraint,\n previous: OrderedBoundConstraint\n): number {\n const family = orderedBoundFamily(current.constraintKind);\n\n if (family === \"numeric-lower\") {\n if (\n !isNumericLowerKind(current.constraintKind) ||\n !isNumericLowerKind(previous.constraintKind)\n ) {\n throw new Error(\"numeric-lower family received non-numeric lower-bound constraint\");\n }\n\n if (current.value !== previous.value) {\n return current.value > previous.value ? 1 : -1;\n }\n if (current.constraintKind === \"exclusiveMinimum\" && previous.constraintKind === \"minimum\") {\n return 1;\n }\n if (current.constraintKind === \"minimum\" && previous.constraintKind === \"exclusiveMinimum\") {\n return -1;\n }\n return 0;\n }\n\n if (family === \"numeric-upper\") {\n if (\n !isNumericUpperKind(current.constraintKind) ||\n !isNumericUpperKind(previous.constraintKind)\n ) {\n throw new Error(\"numeric-upper family received non-numeric upper-bound constraint\");\n }\n\n if (current.value !== previous.value) {\n return current.value < previous.value ? 1 : -1;\n }\n if (current.constraintKind === \"exclusiveMaximum\" && previous.constraintKind === \"maximum\") {\n return 1;\n }\n if (current.constraintKind === \"maximum\" && previous.constraintKind === \"exclusiveMaximum\") {\n return -1;\n }\n return 0;\n }\n\n switch (family) {\n case \"minLength\":\n case \"minItems\":\n if (current.value === previous.value) {\n return 0;\n }\n return current.value > previous.value ? 1 : -1;\n case \"maxLength\":\n case \"maxItems\":\n if (current.value === previous.value) {\n return 0;\n }\n return current.value < previous.value ? 1 : -1;\n default: {\n const _exhaustive: never = family;\n return _exhaustive;\n }\n }\n}\n\nfunction checkConstraintBroadening(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const strongestByKey = new Map<string, OrderedBoundConstraint>();\n\n for (const constraint of constraints) {\n if (!isOrderedBoundConstraint(constraint)) {\n continue;\n }\n\n const key = `${orderedBoundFamily(constraint.constraintKind)}:${pathKey(constraint)}`;\n const previous = strongestByKey.get(key);\n if (previous === undefined) {\n strongestByKey.set(key, constraint);\n continue;\n }\n\n const strength = compareConstraintStrength(constraint, previous);\n if (strength < 0) {\n const displayFieldName = formatPathTargetFieldName(\n fieldName,\n constraint.path?.segments ?? []\n );\n addConstraintBroadening(\n ctx,\n `Field \"${displayFieldName}\": ${describeConstraintTag(constraint)} (${String(constraint.value)}) is broader than earlier ${describeConstraintTag(previous)} (${String(previous.value)}). Constraints can only narrow.`,\n constraint.provenance,\n previous.provenance\n );\n continue;\n }\n\n if (strength <= 0) {\n continue;\n }\n\n strongestByKey.set(key, constraint);\n }\n}\n\ninterface CustomSemanticEntry {\n readonly constraint: Extract<ConstraintNode, { readonly constraintKind: \"custom\" }>;\n readonly comparePayloads: NonNullable<\n NonNullable<ReturnType<ExtensionRegistry[\"findConstraint\"]>>[\"comparePayloads\"]\n >;\n readonly role: NonNullable<NonNullable<ReturnType<ExtensionRegistry[\"findConstraint\"]>>[\"semanticRole\"]>;\n}\n\nfunction compareCustomConstraintStrength(current: CustomSemanticEntry, previous: CustomSemanticEntry): number {\n const order = current.comparePayloads(current.constraint.payload, previous.constraint.payload);\n const equalPayloadTiebreaker =\n order === 0 ? compareSemanticInclusivity(current.role.inclusive, previous.role.inclusive) : order;\n\n switch (current.role.bound) {\n case \"lower\":\n return equalPayloadTiebreaker;\n case \"upper\":\n return equalPayloadTiebreaker === 0 ? 0 : -equalPayloadTiebreaker;\n case \"exact\":\n return order === 0 ? 0 : Number.NaN;\n default: {\n const _exhaustive: never = current.role.bound;\n return _exhaustive;\n }\n }\n}\n\nfunction compareSemanticInclusivity(currentInclusive: boolean, previousInclusive: boolean): number {\n if (currentInclusive === previousInclusive) {\n return 0;\n }\n return currentInclusive ? -1 : 1;\n}\n\nfunction customConstraintsContradict(\n lower: CustomSemanticEntry,\n upper: CustomSemanticEntry\n): boolean {\n const order = lower.comparePayloads(lower.constraint.payload, upper.constraint.payload);\n if (order > 0) {\n return true;\n }\n if (order < 0) {\n return false;\n }\n return !lower.role.inclusive || !upper.role.inclusive;\n}\n\nfunction describeCustomConstraintTag(\n constraint: Extract<ConstraintNode, { readonly constraintKind: \"custom\" }>\n): string {\n return constraint.provenance.tagName ?? constraint.constraintId;\n}\n\nfunction checkCustomConstraintSemantics(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n if (ctx.extensionRegistry === undefined) {\n return;\n }\n\n const strongestByKey = new Map<string, CustomSemanticEntry>();\n const lowerByFamily = new Map<string, CustomSemanticEntry>();\n const upperByFamily = new Map<string, CustomSemanticEntry>();\n\n for (const constraint of constraints) {\n if (constraint.constraintKind !== \"custom\") {\n continue;\n }\n\n const registration = ctx.extensionRegistry.findConstraint(constraint.constraintId);\n if (\n registration?.comparePayloads === undefined ||\n registration.semanticRole === undefined\n ) {\n continue;\n }\n\n const entry: CustomSemanticEntry = {\n constraint,\n comparePayloads: registration.comparePayloads,\n role: registration.semanticRole,\n };\n const familyKey = `${registration.semanticRole.family}:${pathKey(constraint)}`;\n const boundKey = `${familyKey}:${registration.semanticRole.bound}`;\n const previous = strongestByKey.get(boundKey);\n\n if (previous !== undefined) {\n const strength = compareCustomConstraintStrength(entry, previous);\n if (Number.isNaN(strength)) {\n addContradiction(\n ctx,\n `Field \"${formatPathTargetFieldName(fieldName, constraint.path?.segments ?? [])}\": ${describeCustomConstraintTag(constraint)} conflicts with ${describeCustomConstraintTag(previous.constraint)}`,\n constraint.provenance,\n previous.constraint.provenance\n );\n continue;\n }\n\n if (strength < 0) {\n addConstraintBroadening(\n ctx,\n `Field \"${formatPathTargetFieldName(fieldName, constraint.path?.segments ?? [])}\": ${describeCustomConstraintTag(constraint)} is broader than earlier ${describeCustomConstraintTag(previous.constraint)}. Constraints can only narrow.`,\n constraint.provenance,\n previous.constraint.provenance\n );\n continue;\n }\n\n if (strength > 0) {\n strongestByKey.set(boundKey, entry);\n }\n } else {\n strongestByKey.set(boundKey, entry);\n }\n\n if (registration.semanticRole.bound === \"lower\") {\n lowerByFamily.set(familyKey, strongestByKey.get(boundKey) ?? entry);\n } else if (registration.semanticRole.bound === \"upper\") {\n upperByFamily.set(familyKey, strongestByKey.get(boundKey) ?? entry);\n }\n }\n\n for (const [familyKey, lower] of lowerByFamily) {\n const upper = upperByFamily.get(familyKey);\n if (upper === undefined) {\n continue;\n }\n\n if (!customConstraintsContradict(lower, upper)) {\n continue;\n }\n\n addContradiction(\n ctx,\n `Field \"${formatPathTargetFieldName(fieldName, lower.constraint.path?.segments ?? [])}\": ${describeCustomConstraintTag(lower.constraint)} contradicts ${describeCustomConstraintTag(upper.constraint)}`,\n lower.constraint.provenance,\n upper.constraint.provenance\n );\n }\n}\n\n// =============================================================================\n// CONTRADICTION DETECTION\n// =============================================================================\n\nfunction checkNumericContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const min = findNumeric(constraints, \"minimum\");\n const max = findNumeric(constraints, \"maximum\");\n const exMin = findNumeric(constraints, \"exclusiveMinimum\");\n const exMax = findNumeric(constraints, \"exclusiveMaximum\");\n\n // minimum > maximum\n if (min !== undefined && max !== undefined && min.value > max.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minimum (${String(min.value)}) is greater than maximum (${String(max.value)})`,\n min.provenance,\n max.provenance\n );\n }\n\n // exclusiveMinimum >= maximum\n if (exMin !== undefined && max !== undefined && exMin.value >= max.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": exclusiveMinimum (${String(exMin.value)}) is greater than or equal to maximum (${String(max.value)})`,\n exMin.provenance,\n max.provenance\n );\n }\n\n // minimum >= exclusiveMaximum\n if (min !== undefined && exMax !== undefined && min.value >= exMax.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minimum (${String(min.value)}) is greater than or equal to exclusiveMaximum (${String(exMax.value)})`,\n min.provenance,\n exMax.provenance\n );\n }\n\n // exclusiveMinimum >= exclusiveMaximum\n if (exMin !== undefined && exMax !== undefined && exMin.value >= exMax.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": exclusiveMinimum (${String(exMin.value)}) is greater than or equal to exclusiveMaximum (${String(exMax.value)})`,\n exMin.provenance,\n exMax.provenance\n );\n }\n}\n\nfunction checkLengthContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const minLen = findLength(constraints, \"minLength\");\n const maxLen = findLength(constraints, \"maxLength\");\n\n if (minLen !== undefined && maxLen !== undefined && minLen.value > maxLen.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minLength (${String(minLen.value)}) is greater than maxLength (${String(maxLen.value)})`,\n minLen.provenance,\n maxLen.provenance\n );\n }\n\n const minItems = findLength(constraints, \"minItems\");\n const maxItems = findLength(constraints, \"maxItems\");\n\n if (minItems !== undefined && maxItems !== undefined && minItems.value > maxItems.value) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": minItems (${String(minItems.value)}) is greater than maxItems (${String(maxItems.value)})`,\n minItems.provenance,\n maxItems.provenance\n );\n }\n}\n\nfunction checkAllowedMembersContradiction(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const members = findAllowedMembers(constraints);\n if (members.length < 2) return;\n\n // Intersect all allowedMembers sets; if empty — contradiction\n const firstSet = new Set(members[0]?.members ?? []);\n for (let i = 1; i < members.length; i++) {\n const current = members[i];\n if (current === undefined) continue;\n for (const m of firstSet) {\n if (!current.members.includes(m)) {\n firstSet.delete(m);\n }\n }\n }\n\n if (firstSet.size === 0) {\n const first = members[0];\n const second = members[1];\n if (first !== undefined && second !== undefined) {\n addContradiction(\n ctx,\n `Field \"${fieldName}\": allowedMembers constraints have an empty intersection (no valid values remain)`,\n first.provenance,\n second.provenance\n );\n }\n }\n}\n\nfunction checkConstContradictions(\n ctx: ValidationContext,\n fieldName: string,\n constraints: readonly ConstraintNode[]\n): void {\n const constConstraints = findConstConstraints(constraints);\n if (constConstraints.length < 2) return;\n\n const first = constConstraints[0];\n if (first === undefined) return;\n\n for (let i = 1; i < constConstraints.length; i++) {\n const current = constConstraints[i];\n if (current === undefined) continue;\n if (jsonValueEquals(first.value, current.value)) {\n continue;\n }\n\n addContradiction(\n ctx,\n `Field \"${fieldName}\": conflicting @const constraints require both ${JSON.stringify(first.value)} and ${JSON.stringify(current.value)}`,\n first.provenance,\n current.provenance\n );\n }\n}\n\n// =============================================================================\n// TYPE APPLICABILITY CHECKS\n// =============================================================================\n\n/** Return a readable label for a type node for use in diagnostics. */\nfunction typeLabel(type: TypeNode): string {\n switch (type.kind) {\n case \"primitive\":\n return type.primitiveKind;\n case \"enum\":\n return \"enum\";\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n case \"record\":\n return \"record\";\n case \"union\":\n return \"union\";\n case \"reference\":\n return `reference(${type.name})`;\n case \"dynamic\":\n return `dynamic(${type.dynamicKind})`;\n case \"custom\":\n return `custom(${type.typeId})`;\n default: {\n const _exhaustive: never = type;\n return String(_exhaustive);\n }\n }\n}\n\ntype PathTargetResolution =\n | { readonly kind: \"resolved\"; readonly type: TypeNode }\n | { readonly kind: \"missing-property\"; readonly segment: string }\n | { readonly kind: \"unresolvable\"; readonly type: TypeNode };\n\nfunction dereferenceType(ctx: ValidationContext, type: TypeNode): TypeNode {\n let current = type;\n const seen = new Set<string>();\n\n while (current.kind === \"reference\") {\n if (seen.has(current.name)) {\n return current;\n }\n seen.add(current.name);\n\n const definition = ctx.typeRegistry[current.name];\n if (definition === undefined) {\n return current;\n }\n\n current = definition.type;\n }\n\n return current;\n}\n\nfunction resolvePathTargetType(\n ctx: ValidationContext,\n type: TypeNode,\n segments: readonly string[]\n): PathTargetResolution {\n const effectiveType = dereferenceType(ctx, type);\n\n if (segments.length === 0) {\n return { kind: \"resolved\", type: effectiveType };\n }\n\n if (effectiveType.kind === \"array\") {\n return resolvePathTargetType(ctx, effectiveType.items, segments);\n }\n\n if (effectiveType.kind === \"object\") {\n const [segment, ...rest] = segments;\n if (segment === undefined) {\n throw new Error(\"Invariant violation: object path traversal requires a segment\");\n }\n const property = effectiveType.properties.find((prop) => prop.name === segment);\n if (property === undefined) {\n return { kind: \"missing-property\", segment };\n }\n return resolvePathTargetType(ctx, property.type, rest);\n }\n\n return { kind: \"unresolvable\", type: effectiveType };\n}\n\nfunction formatPathTargetFieldName(fieldName: string, path: readonly string[]): string {\n return path.length === 0 ? fieldName : `${fieldName}.${path.join(\".\")}`;\n}\n\nfunction checkConstraintOnType(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraint: ConstraintNode\n): void {\n const effectiveType = dereferenceType(ctx, type);\n const isNumber = effectiveType.kind === \"primitive\" && effectiveType.primitiveKind === \"number\";\n const isString = effectiveType.kind === \"primitive\" && effectiveType.primitiveKind === \"string\";\n const isArray = effectiveType.kind === \"array\";\n const isEnum = effectiveType.kind === \"enum\";\n const arrayItemType =\n effectiveType.kind === \"array\" ? dereferenceType(ctx, effectiveType.items) : undefined;\n const isStringArray =\n arrayItemType?.kind === \"primitive\" && arrayItemType.primitiveKind === \"string\";\n\n const label = typeLabel(effectiveType);\n\n const ck = constraint.constraintKind;\n\n switch (ck) {\n case \"minimum\":\n case \"maximum\":\n case \"exclusiveMinimum\":\n case \"exclusiveMaximum\":\n case \"multipleOf\": {\n if (!isNumber) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on number fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"minLength\":\n case \"maxLength\":\n case \"pattern\": {\n if (!isString && !isStringArray) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on string fields or string array items, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"minItems\":\n case \"maxItems\":\n case \"uniqueItems\": {\n if (!isArray) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"${ck}\" is only valid on array fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"allowedMembers\": {\n if (!isEnum) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"allowedMembers\" is only valid on enum fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n }\n break;\n }\n case \"const\": {\n const isPrimitiveConstType =\n (effectiveType.kind === \"primitive\" &&\n [\"string\", \"number\", \"boolean\", \"null\"].includes(effectiveType.primitiveKind)) ||\n effectiveType.kind === \"enum\";\n\n if (!isPrimitiveConstType) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": constraint \"const\" is only valid on primitive or enum fields, but field type is \"${label}\"`,\n constraint.provenance\n );\n break;\n }\n\n if (effectiveType.kind === \"primitive\") {\n const valueType =\n constraint.value === null\n ? \"null\"\n : Array.isArray(constraint.value)\n ? \"array\"\n : typeof constraint.value;\n if (valueType !== effectiveType.primitiveKind) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": @const value type \"${valueType}\" is incompatible with field type \"${effectiveType.primitiveKind}\"`,\n constraint.provenance\n );\n }\n break;\n }\n\n const memberValues = effectiveType.members.map((member) => member.value);\n if (!memberValues.some((member) => jsonValueEquals(member, constraint.value))) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": @const value ${JSON.stringify(constraint.value)} is not one of the enum members`,\n constraint.provenance\n );\n }\n break;\n }\n case \"custom\": {\n checkCustomConstraint(ctx, fieldName, effectiveType, constraint);\n break;\n }\n default: {\n const _exhaustive: never = constraint;\n throw new Error(\n `Unhandled constraint kind: ${(_exhaustive as ConstraintNode).constraintKind}`\n );\n }\n }\n}\n\nfunction checkTypeApplicability(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraints: readonly ConstraintNode[]\n): void {\n for (const constraint of constraints) {\n // Path-targeted constraints (e.g., `@Minimum :value 0`) target a sub-field,\n // not the field itself. Resolve the target path and validate against the\n // resolved target type.\n if (constraint.path) {\n const resolution = resolvePathTargetType(ctx, type, constraint.path.segments);\n const targetFieldName = formatPathTargetFieldName(fieldName, constraint.path.segments);\n\n if (resolution.kind === \"missing-property\") {\n addUnknownPathTarget(\n ctx,\n `Field \"${targetFieldName}\": path-targeted constraint \"${constraint.constraintKind}\" references unknown path segment \"${resolution.segment}\"`,\n constraint.provenance\n );\n continue;\n }\n\n if (resolution.kind === \"unresolvable\") {\n addTypeMismatch(\n ctx,\n `Field \"${targetFieldName}\": path-targeted constraint \"${constraint.constraintKind}\" is invalid because type \"${typeLabel(resolution.type)}\" cannot be traversed`,\n constraint.provenance\n );\n continue;\n }\n\n checkConstraintOnType(ctx, targetFieldName, resolution.type, constraint);\n continue;\n }\n\n checkConstraintOnType(ctx, fieldName, type, constraint);\n }\n}\n\n/**\n * Check a custom constraint against the extension registry.\n *\n * When the registry is available:\n * - If the constraint ID is not found, emit UNKNOWN_EXTENSION warning\n * - If found and the registration has `applicableTypes`, verify the field's\n * type kind is in that list (emit TYPE_MISMATCH if not)\n * - If `applicableTypes` is null, the constraint applies to any type\n *\n * When no registry is available, custom constraints are silently skipped.\n */\nfunction checkCustomConstraint(\n ctx: ValidationContext,\n fieldName: string,\n type: TypeNode,\n constraint: ConstraintNode & { readonly constraintKind: \"custom\" }\n): void {\n if (ctx.extensionRegistry === undefined) return;\n\n const registration = ctx.extensionRegistry.findConstraint(constraint.constraintId);\n\n if (registration === undefined) {\n addUnknownExtension(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not registered in the extension registry`,\n constraint.provenance\n );\n return;\n }\n\n const normalizedTagName =\n constraint.provenance.tagName === undefined\n ? undefined\n : normalizeConstraintTagName(constraint.provenance.tagName.replace(/^@/, \"\"));\n if (normalizedTagName !== undefined) {\n const tagRegistration = ctx.extensionRegistry.findConstraintTag(normalizedTagName);\n const extensionId = getExtensionIdFromConstraintId(constraint.constraintId);\n if (\n extensionId !== null &&\n tagRegistration?.extensionId === extensionId &&\n tagRegistration.registration.constraintName === registration.constraintName &&\n tagRegistration.registration.isApplicableToType?.(type) === false\n ) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not applicable to type \"${typeLabel(type)}\"`,\n constraint.provenance\n );\n return;\n }\n }\n\n // If applicableTypes is null, the constraint applies to any type unless a\n // narrower extension predicate rejects the specific resolved type node.\n if (registration.applicableTypes === null) {\n if (registration.isApplicableToType?.(type) === false) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not applicable to type \"${typeLabel(type)}\"`,\n constraint.provenance\n );\n }\n return;\n }\n\n if (\n !registration.applicableTypes.includes(type.kind) ||\n registration.isApplicableToType?.(type) === false\n ) {\n addTypeMismatch(\n ctx,\n `Field \"${fieldName}\": custom constraint \"${constraint.constraintId}\" is not applicable to type \"${typeLabel(type)}\"`,\n constraint.provenance\n );\n }\n}\n\n// =============================================================================\n// FIELD VALIDATION\n// =============================================================================\n\nfunction validateFieldNode(ctx: ValidationContext, field: FieldNode): void {\n validateConstraints(ctx, field.name, field.type, field.constraints);\n\n // Recurse into object type properties\n if (field.type.kind === \"object\") {\n for (const prop of field.type.properties) {\n validateObjectProperty(ctx, field.name, prop);\n }\n }\n}\n\nfunction validateObjectProperty(\n ctx: ValidationContext,\n parentName: string,\n prop: ObjectProperty\n): void {\n const qualifiedName = `${parentName}.${prop.name}`;\n validateConstraints(ctx, qualifiedName, prop.type, prop.constraints);\n\n // Recurse further if this property is also an object\n if (prop.type.kind === \"object\") {\n for (const nestedProp of prop.type.properties) {\n validateObjectProperty(ctx, qualifiedName, nestedProp);\n }\n }\n}\n\nfunction validateConstraints(\n ctx: ValidationContext,\n name: string,\n type: TypeNode,\n constraints: readonly ConstraintNode[]\n): void {\n checkNumericContradictions(ctx, name, constraints);\n checkLengthContradictions(ctx, name, constraints);\n checkAllowedMembersContradiction(ctx, name, constraints);\n checkConstContradictions(ctx, name, constraints);\n checkConstraintBroadening(ctx, name, constraints);\n checkCustomConstraintSemantics(ctx, name, constraints);\n checkTypeApplicability(ctx, name, type, constraints);\n}\n\n// =============================================================================\n// RECURSIVE ELEMENT WALK\n// =============================================================================\n\nfunction validateElement(ctx: ValidationContext, element: FormIRElement): void {\n switch (element.kind) {\n case \"field\":\n validateFieldNode(ctx, element);\n break;\n case \"group\":\n for (const child of element.elements) {\n validateElement(ctx, child);\n }\n break;\n case \"conditional\":\n for (const child of element.elements) {\n validateElement(ctx, child);\n }\n break;\n default: {\n const _exhaustive: never = element;\n throw new Error(`Unhandled element kind: ${(_exhaustive as FormIRElement).kind}`);\n }\n }\n}\n\n// =============================================================================\n// MAIN EXPORT\n// =============================================================================\n\n/**\n * Validate all constraints in a {@link FormIR}.\n *\n * Checks for:\n * - Contradictions between paired constraints (e.g. `minimum > maximum`)\n * - Type applicability violations (e.g. `minLength` on a number field)\n * - Custom constraint type applicability (via extension registry)\n * - Unknown extension constraints (when `extensionRegistry` is provided)\n *\n * @param ir - The form IR to validate.\n * @param options - Optional configuration.\n * @returns A {@link ValidationResult} with diagnostics and a `valid` flag.\n */\nexport function validateIR(ir: FormIR, options?: ValidateIROptions): ValidationResult {\n const ctx: ValidationContext = {\n diagnostics: [],\n extensionRegistry: options?.extensionRegistry,\n typeRegistry: ir.typeRegistry,\n };\n\n for (const element of ir.elements) {\n validateElement(ctx, element);\n }\n\n return {\n diagnostics: ctx.diagnostics,\n valid: ctx.diagnostics.every((d) => d.severity !== \"error\"),\n };\n}\n","/**\n * Extension registry for resolving custom types, constraints, and annotations\n * during JSON Schema generation and IR validation.\n *\n * The registry is created from a list of {@link ExtensionDefinition} objects\n * and provides O(1) lookup by fully-qualified ID (extensionId + \"/\" + name).\n *\n * @packageDocumentation\n */\n\nimport type {\n ExtensionDefinition,\n CustomTypeRegistration,\n CustomConstraintRegistration,\n CustomAnnotationRegistration,\n ConstraintTagRegistration,\n BuiltinConstraintBroadeningRegistration,\n} from \"@formspec/core\";\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * A registry of extensions that provides lookup by fully-qualified ID.\n *\n * Type IDs follow the format: `<extensionId>/<typeName>`\n * Constraint IDs follow the format: `<extensionId>/<constraintName>`\n * Annotation IDs follow the format: `<extensionId>/<annotationName>`\n */\nexport interface ExtensionRegistry {\n /** The extensions registered in this registry (in registration order). */\n readonly extensions: readonly ExtensionDefinition[];\n\n /**\n * Look up a custom type registration by its fully-qualified type ID.\n *\n * @param typeId - The fully-qualified type ID (e.g., \"x-stripe/monetary/Decimal\").\n * @returns The registration if found, otherwise `undefined`.\n */\n findType(typeId: string): CustomTypeRegistration | undefined;\n /**\n * Look up a custom type registration by a TypeScript-facing type name.\n *\n * This is used during TSDoc/class analysis to resolve extension-defined\n * custom types from source-level declarations.\n */\n findTypeByName(\n typeName: string\n ): { readonly extensionId: string; readonly registration: CustomTypeRegistration } | undefined;\n\n /**\n * Look up a custom constraint registration by its fully-qualified constraint ID.\n *\n * @param constraintId - The fully-qualified constraint ID.\n * @returns The registration if found, otherwise `undefined`.\n */\n findConstraint(constraintId: string): CustomConstraintRegistration | undefined;\n /**\n * Look up a TSDoc custom constraint-tag registration by tag name.\n */\n findConstraintTag(tagName: string): {\n readonly extensionId: string;\n readonly registration: ConstraintTagRegistration;\n } | undefined;\n /**\n * Look up built-in tag broadening for a given custom type ID.\n */\n findBuiltinConstraintBroadening(\n typeId: string,\n tagName: string\n ): {\n readonly extensionId: string;\n readonly registration: BuiltinConstraintBroadeningRegistration;\n } | undefined;\n\n /**\n * Look up a custom annotation registration by its fully-qualified annotation ID.\n *\n * @param annotationId - The fully-qualified annotation ID.\n * @returns The registration if found, otherwise `undefined`.\n */\n findAnnotation(annotationId: string): CustomAnnotationRegistration | undefined;\n}\n\n// =============================================================================\n// IMPLEMENTATION\n// =============================================================================\n\n/**\n * Creates an extension registry from a list of extension definitions.\n *\n * The registry indexes all types, constraints, and annotations by their\n * fully-qualified IDs (`<extensionId>/<name>`) for O(1) lookup during\n * generation and validation.\n *\n * @param extensions - The extension definitions to register.\n * @returns An {@link ExtensionRegistry} instance.\n * @throws If duplicate type/constraint/annotation IDs are detected across extensions.\n */\nexport function createExtensionRegistry(\n extensions: readonly ExtensionDefinition[]\n): ExtensionRegistry {\n const typeMap = new Map<string, CustomTypeRegistration>();\n const typeNameMap = new Map<\n string,\n { readonly extensionId: string; readonly registration: CustomTypeRegistration }\n >();\n const constraintMap = new Map<string, CustomConstraintRegistration>();\n const constraintTagMap = new Map<\n string,\n { readonly extensionId: string; readonly registration: ConstraintTagRegistration }\n >();\n const builtinBroadeningMap = new Map<\n string,\n { readonly extensionId: string; readonly registration: BuiltinConstraintBroadeningRegistration }\n >();\n const annotationMap = new Map<string, CustomAnnotationRegistration>();\n\n for (const ext of extensions) {\n if (ext.types !== undefined) {\n for (const type of ext.types) {\n const qualifiedId = `${ext.extensionId}/${type.typeName}`;\n if (typeMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom type ID: \"${qualifiedId}\"`);\n }\n typeMap.set(qualifiedId, type);\n\n for (const sourceTypeName of type.tsTypeNames ?? [type.typeName]) {\n if (typeNameMap.has(sourceTypeName)) {\n throw new Error(`Duplicate custom type source name: \"${sourceTypeName}\"`);\n }\n typeNameMap.set(sourceTypeName, {\n extensionId: ext.extensionId,\n registration: type,\n });\n }\n\n if (type.builtinConstraintBroadenings !== undefined) {\n for (const broadening of type.builtinConstraintBroadenings) {\n const key = `${qualifiedId}:${broadening.tagName}`;\n if (builtinBroadeningMap.has(key)) {\n throw new Error(`Duplicate built-in constraint broadening: \"${key}\"`);\n }\n builtinBroadeningMap.set(key, {\n extensionId: ext.extensionId,\n registration: broadening,\n });\n }\n }\n }\n }\n\n if (ext.constraints !== undefined) {\n for (const constraint of ext.constraints) {\n const qualifiedId = `${ext.extensionId}/${constraint.constraintName}`;\n if (constraintMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom constraint ID: \"${qualifiedId}\"`);\n }\n constraintMap.set(qualifiedId, constraint);\n }\n }\n\n if (ext.constraintTags !== undefined) {\n for (const tag of ext.constraintTags) {\n if (constraintTagMap.has(tag.tagName)) {\n throw new Error(`Duplicate custom constraint tag: \"@${tag.tagName}\"`);\n }\n constraintTagMap.set(tag.tagName, {\n extensionId: ext.extensionId,\n registration: tag,\n });\n }\n }\n\n if (ext.annotations !== undefined) {\n for (const annotation of ext.annotations) {\n const qualifiedId = `${ext.extensionId}/${annotation.annotationName}`;\n if (annotationMap.has(qualifiedId)) {\n throw new Error(`Duplicate custom annotation ID: \"${qualifiedId}\"`);\n }\n annotationMap.set(qualifiedId, annotation);\n }\n }\n }\n\n return {\n extensions,\n findType: (typeId: string) => typeMap.get(typeId),\n findTypeByName: (typeName: string) => typeNameMap.get(typeName),\n findConstraint: (constraintId: string) => constraintMap.get(constraintId),\n findConstraintTag: (tagName: string) => constraintTagMap.get(tagName),\n findBuiltinConstraintBroadening: (typeId: string, tagName: string) =>\n builtinBroadeningMap.get(`${typeId}:${tagName}`),\n findAnnotation: (annotationId: string) => annotationMap.get(annotationId),\n };\n}\n","/**\n * Method schema generator.\n *\n * Generates schemas for method parameters and return types, routing through\n * the canonical IR pipeline (TypeScript type → TypeNode → JSON Schema 2020-12).\n */\n\nimport type * as ts from \"typescript\";\nimport type { MethodInfo, ParameterInfo } from \"../analyzer/class-analyzer.js\";\nimport { resolveTypeNode } from \"../analyzer/class-analyzer.js\";\nimport type { TypeDefinition } from \"@formspec/core\";\nimport { generateJsonSchemaFromIR, type JsonSchema2020 } from \"../json-schema/ir-generator.js\";\nimport { IR_VERSION } from \"@formspec/core\";\n\n/**\n * Runtime-loaded FormSpec schemas, compatible with the CLI's FormSpecSchemas type.\n */\nexport interface LoadedFormSpecSchemas {\n /** The FormSpec export name */\n name: string;\n /** Generated JSON Schema */\n jsonSchema: unknown;\n /** Generated UI Schema (FormSpec/JSON Forms) */\n uiSchema: unknown;\n}\n\n/**\n * Generated schemas for a method.\n */\nexport interface MethodSchemas {\n /** Method name */\n name: string;\n /** Parameter schemas (from FormSpec or static analysis) */\n params: MethodParamsSchemas | null;\n /** Return type schema */\n returnType: JsonSchema2020;\n}\n\n/**\n * Parameter schemas for a method.\n */\nexport interface MethodParamsSchemas {\n /** JSON Schema for parameters */\n jsonSchema: JsonSchema2020;\n /** UI Schema / FormSpec for parameters (if available) */\n uiSchema: object | null;\n /** Name of the FormSpec export used (if any) */\n formSpecExport: string | null;\n}\n\n/**\n * Resolves a TypeScript type to a JSON Schema 2020-12 sub-schema via the IR.\n */\nfunction typeToJsonSchema(type: ts.Type, checker: ts.TypeChecker): JsonSchema2020 {\n const typeRegistry: Record<string, TypeDefinition> = {};\n const visiting = new Set<ts.Type>();\n const typeNode = resolveTypeNode(type, checker, \"\", typeRegistry, visiting);\n\n const fieldProvenance = { surface: \"tsdoc\" as const, file: \"\", line: 0, column: 0 };\n\n // Build a minimal FormIR wrapping a single field to reuse the IR generator.\n const ir = {\n kind: \"form-ir\" as const,\n irVersion: IR_VERSION,\n elements: [\n {\n kind: \"field\" as const,\n name: \"__result\",\n type: typeNode,\n required: true,\n constraints: [],\n annotations: [],\n provenance: fieldProvenance,\n },\n ],\n typeRegistry,\n provenance: fieldProvenance,\n };\n\n const schema = generateJsonSchemaFromIR(ir);\n // Extract the single field's sub-schema from the wrapper.\n const fieldSchema = schema.properties?.[\"__result\"];\n if (fieldSchema) {\n // If there are $defs, attach them to the field schema for completeness.\n if (schema.$defs && Object.keys(schema.$defs).length > 0) {\n return { ...fieldSchema, $defs: schema.$defs };\n }\n return fieldSchema;\n }\n return { type: \"object\" };\n}\n\n/**\n * Generates schemas for a method's parameters and return type.\n *\n * If a parameter references a FormSpec via `InferSchema<typeof X>`,\n * the schemas are taken from the loaded FormSpec at runtime.\n * Otherwise, schemas are generated from static type analysis via the IR.\n *\n * @param method - The method information from static analysis\n * @param checker - TypeScript type checker\n * @param loadedFormSpecs - Map of FormSpec export names to their schemas\n * @returns Generated method schemas\n */\nexport function generateMethodSchemas(\n method: MethodInfo,\n checker: ts.TypeChecker,\n loadedFormSpecs: Map<string, LoadedFormSpecSchemas>\n): MethodSchemas {\n // Generate return type schema via IR\n const returnType = typeToJsonSchema(method.returnType, checker);\n\n // Handle parameters\n const params = generateParamsSchemas(method.parameters, checker, loadedFormSpecs);\n\n return {\n name: method.name,\n params,\n returnType,\n };\n}\n\n/**\n * Generates schemas for method parameters.\n */\nfunction generateParamsSchemas(\n parameters: ParameterInfo[],\n checker: ts.TypeChecker,\n loadedFormSpecs: Map<string, LoadedFormSpecSchemas>\n): MethodParamsSchemas | null {\n if (parameters.length === 0) {\n return null;\n }\n\n // Check if any parameter uses InferSchema<typeof X>\n for (const param of parameters) {\n if (param.formSpecExportName) {\n const formSpec = loadedFormSpecs.get(param.formSpecExportName);\n if (formSpec) {\n return {\n jsonSchema: formSpec.jsonSchema as JsonSchema2020,\n uiSchema: formSpec.uiSchema as object | null,\n formSpecExport: param.formSpecExportName,\n };\n }\n\n // FormSpec not found - fall back to static analysis\n console.warn(\n `Warning: FormSpec export \"${param.formSpecExportName}\" not found, using static analysis`\n );\n }\n }\n\n // Generate from static type analysis via IR\n if (parameters.length === 1 && parameters[0]) {\n const param = parameters[0];\n const jsonSchema = typeToJsonSchema(param.type, checker);\n return {\n jsonSchema,\n uiSchema: null,\n formSpecExport: null,\n };\n }\n\n // Multiple parameters - create object schema\n const properties: Record<string, JsonSchema2020> = {};\n const required: string[] = [];\n\n for (const param of parameters) {\n const paramSchema = typeToJsonSchema(param.type, checker);\n properties[param.name] = paramSchema;\n if (!param.optional) {\n required.push(param.name);\n }\n }\n\n return {\n jsonSchema: {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n },\n uiSchema: null,\n formSpecExport: null,\n };\n}\n\n/**\n * Collects all FormSpec export names referenced by methods.\n *\n * Use this to determine which exports to load at runtime.\n *\n * @param methods - Array of method infos\n * @returns Set of FormSpec export names\n */\nexport function collectFormSpecReferences(methods: MethodInfo[]): Set<string> {\n const references = new Set<string>();\n\n for (const method of methods) {\n for (const param of method.parameters) {\n if (param.formSpecExportName) {\n references.add(param.formSpecExportName);\n }\n }\n }\n\n return references;\n}\n"],"mappings":"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","names":["import_core","ts","ts","ts","import_core","text","provenance","path","parsed","members","isBooleanUnion","import_zod","import_core","path","import_core"]}