@formspec/build 0.1.0-alpha.11 → 0.1.0-alpha.13

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 (135) hide show
  1. package/README.md +51 -15
  2. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts +2 -0
  3. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts.map +1 -0
  4. package/dist/__tests__/constraint-validator.test.d.ts +2 -0
  5. package/dist/__tests__/constraint-validator.test.d.ts.map +1 -0
  6. package/dist/__tests__/extension-api.test.d.ts +2 -0
  7. package/dist/__tests__/extension-api.test.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/example-a-builtins.d.ts +18 -0
  9. package/dist/__tests__/fixtures/example-a-builtins.d.ts.map +1 -1
  10. package/dist/__tests__/guards.test.d.ts +2 -0
  11. package/dist/__tests__/guards.test.d.ts.map +1 -0
  12. package/dist/__tests__/ir-analyzer.test.d.ts +11 -0
  13. package/dist/__tests__/ir-analyzer.test.d.ts.map +1 -0
  14. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts +12 -0
  15. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts.map +1 -0
  16. package/dist/__tests__/ir-json-schema-generator.test.d.ts +11 -0
  17. package/dist/__tests__/ir-json-schema-generator.test.d.ts.map +1 -0
  18. package/dist/__tests__/ir-ui-schema-generator.test.d.ts +2 -0
  19. package/dist/__tests__/ir-ui-schema-generator.test.d.ts.map +1 -0
  20. package/dist/__tests__/jsdoc-constraints.test.d.ts +4 -4
  21. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts +9 -0
  22. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts.map +1 -0
  23. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts +9 -0
  24. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts.map +1 -0
  25. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts +19 -0
  26. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts.map +1 -0
  27. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts +13 -0
  28. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts.map +1 -0
  29. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts +9 -0
  30. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts.map +1 -0
  31. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts +28 -0
  32. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts.map +1 -0
  33. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts +12 -0
  34. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts.map +1 -0
  35. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts +9 -0
  36. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts.map +1 -0
  37. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts +19 -0
  38. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts.map +1 -0
  39. package/dist/__tests__/parity/parity.test.d.ts +14 -0
  40. package/dist/__tests__/parity/parity.test.d.ts.map +1 -0
  41. package/dist/__tests__/parity/utils.d.ts +139 -0
  42. package/dist/__tests__/parity/utils.d.ts.map +1 -0
  43. package/dist/analyzer/class-analyzer.d.ts +54 -99
  44. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  45. package/dist/analyzer/jsdoc-constraints.d.ts +78 -30
  46. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
  47. package/dist/analyzer/tsdoc-parser.d.ts +61 -0
  48. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -0
  49. package/dist/browser.cjs +998 -309
  50. package/dist/browser.cjs.map +1 -1
  51. package/dist/browser.d.ts +10 -6
  52. package/dist/browser.d.ts.map +1 -1
  53. package/dist/browser.js +996 -308
  54. package/dist/browser.js.map +1 -1
  55. package/dist/build.d.ts +65 -150
  56. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts +18 -0
  57. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -0
  58. package/dist/canonicalize/index.d.ts +8 -0
  59. package/dist/canonicalize/index.d.ts.map +1 -0
  60. package/dist/canonicalize/tsdoc-canonicalizer.d.ts +34 -0
  61. package/dist/canonicalize/tsdoc-canonicalizer.d.ts.map +1 -0
  62. package/dist/cli.cjs +1455 -1656
  63. package/dist/cli.cjs.map +1 -1
  64. package/dist/cli.js +1459 -1647
  65. package/dist/cli.js.map +1 -1
  66. package/dist/extensions/index.d.ts +8 -0
  67. package/dist/extensions/index.d.ts.map +1 -0
  68. package/dist/extensions/registry.d.ts +55 -0
  69. package/dist/extensions/registry.d.ts.map +1 -0
  70. package/dist/generators/class-schema.d.ts +23 -38
  71. package/dist/generators/class-schema.d.ts.map +1 -1
  72. package/dist/generators/method-schema.d.ts +6 -8
  73. package/dist/generators/method-schema.d.ts.map +1 -1
  74. package/dist/index.cjs +1391 -1614
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.d.ts +6 -8
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +1403 -1610
  79. package/dist/index.js.map +1 -1
  80. package/dist/internals.cjs +1642 -824
  81. package/dist/internals.cjs.map +1 -1
  82. package/dist/internals.d.ts +12 -3
  83. package/dist/internals.d.ts.map +1 -1
  84. package/dist/internals.js +1645 -820
  85. package/dist/internals.js.map +1 -1
  86. package/dist/json-schema/generator.d.ts +10 -5
  87. package/dist/json-schema/generator.d.ts.map +1 -1
  88. package/dist/json-schema/ir-generator.d.ts +84 -0
  89. package/dist/json-schema/ir-generator.d.ts.map +1 -0
  90. package/dist/json-schema/schema.d.ts +3 -3
  91. package/dist/json-schema/types.d.ts +5 -6
  92. package/dist/json-schema/types.d.ts.map +1 -1
  93. package/dist/ui-schema/generator.d.ts +5 -15
  94. package/dist/ui-schema/generator.d.ts.map +1 -1
  95. package/dist/ui-schema/ir-generator.d.ts +53 -0
  96. package/dist/ui-schema/ir-generator.d.ts.map +1 -0
  97. package/dist/validate/constraint-validator.d.ts +66 -0
  98. package/dist/validate/constraint-validator.d.ts.map +1 -0
  99. package/dist/validate/index.d.ts +9 -0
  100. package/dist/validate/index.d.ts.map +1 -0
  101. package/package.json +5 -4
  102. package/dist/__tests__/analyzer-edge-cases.test.d.ts +0 -13
  103. package/dist/__tests__/analyzer-edge-cases.test.d.ts.map +0 -1
  104. package/dist/__tests__/analyzer.test.d.ts +0 -5
  105. package/dist/__tests__/analyzer.test.d.ts.map +0 -1
  106. package/dist/__tests__/codegen.test.d.ts +0 -5
  107. package/dist/__tests__/codegen.test.d.ts.map +0 -1
  108. package/dist/__tests__/decorator-pipeline.test.d.ts +0 -11
  109. package/dist/__tests__/decorator-pipeline.test.d.ts.map +0 -1
  110. package/dist/__tests__/fixtures/example-b-decorators.d.ts +0 -5
  111. package/dist/__tests__/fixtures/example-b-decorators.d.ts.map +0 -1
  112. package/dist/__tests__/fixtures/example-b-extended.d.ts +0 -5
  113. package/dist/__tests__/fixtures/example-b-extended.d.ts.map +0 -1
  114. package/dist/__tests__/fixtures/example-c-custom.d.ts +0 -5
  115. package/dist/__tests__/fixtures/example-c-custom.d.ts.map +0 -1
  116. package/dist/__tests__/fixtures/example-c-decorators.d.ts +0 -5
  117. package/dist/__tests__/fixtures/example-c-decorators.d.ts.map +0 -1
  118. package/dist/__tests__/fixtures/example-d-mixed-decorators.d.ts +0 -6
  119. package/dist/__tests__/fixtures/example-d-mixed-decorators.d.ts.map +0 -1
  120. package/dist/__tests__/fixtures/example-e-decorators.d.ts +0 -11
  121. package/dist/__tests__/fixtures/example-e-decorators.d.ts.map +0 -1
  122. package/dist/__tests__/fixtures/example-e-no-namespace.d.ts +0 -5
  123. package/dist/__tests__/fixtures/example-e-no-namespace.d.ts.map +0 -1
  124. package/dist/__tests__/fixtures/example-jsdoc-constraints.d.ts +0 -16
  125. package/dist/__tests__/fixtures/example-jsdoc-constraints.d.ts.map +0 -1
  126. package/dist/__tests__/fixtures/example-nested-class.d.ts +0 -45
  127. package/dist/__tests__/fixtures/example-nested-class.d.ts.map +0 -1
  128. package/dist/__tests__/interface-types.test.d.ts +0 -11
  129. package/dist/__tests__/interface-types.test.d.ts.map +0 -1
  130. package/dist/analyzer/decorator-extractor.d.ts +0 -78
  131. package/dist/analyzer/decorator-extractor.d.ts.map +0 -1
  132. package/dist/analyzer/type-converter.d.ts +0 -75
  133. package/dist/analyzer/type-converter.d.ts.map +0 -1
  134. package/dist/codegen/index.d.ts +0 -75
  135. package/dist/codegen/index.d.ts.map +0 -1
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/json-schema/schema.ts","../src/json-schema/generator.ts","../src/ui-schema/schema.ts","../src/ui-schema/generator.ts","../src/json-schema/types.ts","../src/analyzer/decorator-extractor.ts","../src/analyzer/jsdoc-constraints.ts","../src/analyzer/class-analyzer.ts","../src/analyzer/type-converter.ts","../src/analyzer/program.ts","../src/generators/class-schema.ts","../src/codegen/index.ts","../src/index.ts","../src/cli.ts"],"sourcesContent":["/**\n * Zod schemas for JSON Schema draft-07 output validation.\n *\n * These schemas cover the subset of JSON Schema draft-07 that FormSpec generates,\n * plus the FormSpec-specific `x-formspec-*` extension properties.\n *\n * @see https://json-schema.org/draft-07/schema\n */\n\nimport { z } from \"zod\";\nimport type { JSONSchema7 } from \"./types.js\";\n\n// =============================================================================\n// JSON Schema type enum\n// =============================================================================\n\n/**\n * Zod schema for JSON Schema primitive type strings.\n */\nexport const jsonSchemaTypeSchema = z.enum([\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"object\",\n \"array\",\n \"null\",\n]);\n\n// =============================================================================\n// JSON Schema draft-07 schema (recursive)\n// =============================================================================\n\n// We annotate with z.ZodType<JSONSchema7> for the recursive self-reference.\n// The @ts-expect-error is required because exactOptionalPropertyTypes:true causes\n// Zod's inferred output type for optional fields (`T | undefined`) to be\n// incompatible with the JSONSchema7 interface's exact optional fields (`T?`).\n// The runtime behavior is correct: z.optional() will strip `undefined` values\n// during parsing and correctly handle absent keys.\n//\n// @ts-expect-error -- exactOptionalPropertyTypes: Zod optional infers `T | undefined`\n// but JSONSchema7 uses exact optional `?:` which disallows explicit undefined.\nexport const jsonSchema7Schema: z.ZodType<JSONSchema7> = z.lazy(() =>\n z\n .object({\n $schema: z.string().optional(),\n $id: z.string().optional(),\n $ref: z.string().optional(),\n\n // Metadata\n title: z.string().optional(),\n description: z.string().optional(),\n deprecated: z.boolean().optional(),\n\n // Type\n type: z.union([jsonSchemaTypeSchema, z.array(jsonSchemaTypeSchema)]).optional(),\n\n // String validation\n minLength: z.number().optional(),\n maxLength: z.number().optional(),\n pattern: z.string().optional(),\n\n // Number validation\n minimum: z.number().optional(),\n maximum: z.number().optional(),\n exclusiveMinimum: z.number().optional(),\n exclusiveMaximum: z.number().optional(),\n\n // Enum\n enum: z\n .array(z.union([z.string(), z.number(), z.boolean(), z.null()]))\n .readonly()\n .optional(),\n const: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(),\n\n // Object\n properties: z.record(z.string(), jsonSchema7Schema).optional(),\n required: z.array(z.string()).optional(),\n additionalProperties: z.union([z.boolean(), jsonSchema7Schema]).optional(),\n\n // Array\n items: z.union([jsonSchema7Schema, z.array(jsonSchema7Schema)]).optional(),\n minItems: z.number().optional(),\n maxItems: z.number().optional(),\n\n // Composition\n allOf: z.array(jsonSchema7Schema).optional(),\n anyOf: z.array(jsonSchema7Schema).optional(),\n oneOf: z.array(jsonSchema7Schema).optional(),\n not: jsonSchema7Schema.optional(),\n\n // Conditional\n if: jsonSchema7Schema.optional(),\n then: jsonSchema7Schema.optional(),\n else: jsonSchema7Schema.optional(),\n\n // Format\n format: z.string().optional(),\n\n // Default\n default: z.unknown().optional(),\n\n // FormSpec extensions\n \"x-formspec-source\": z.string().optional(),\n \"x-formspec-params\": z.array(z.string()).readonly().optional(),\n \"x-formspec-schemaSource\": z.string().optional(),\n })\n // passthrough preserves arbitrary x-formspec-* extension properties\n // added by custom decorators without causing validation failures\n .passthrough()\n);\n","/**\n * JSON Schema generator for FormSpec forms.\n */\n\nimport type {\n FormElement,\n FormSpec,\n AnyField,\n Group,\n Conditional,\n ArrayField,\n ObjectField,\n} from \"@formspec/core\";\nimport type { JSONSchema7 } from \"./types.js\";\nimport { jsonSchema7Schema } from \"./schema.js\";\nimport { z } from \"zod\";\n\n/**\n * Parses a value through a Zod schema, converting validation errors to a 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 * Generates JSON Schema for nested elements (used for array items and object properties).\n */\nfunction generateNestedSchema(elements: readonly FormElement[]): JSONSchema7 {\n const properties: Record<string, JSONSchema7> = {};\n const required: string[] = [];\n\n collectFields(elements, properties, required);\n\n // Deduplicate required array (can have duplicates when the same field is defined\n // in multiple branches/containers, e.g., repeated in different conditional branches)\n const uniqueRequired = [...new Set(required)];\n\n return {\n type: \"object\",\n properties,\n ...(uniqueRequired.length > 0 && { required: uniqueRequired }),\n };\n}\n\n/**\n * Converts a single field to its JSON Schema representation.\n */\nfunction fieldToJsonSchema(field: AnyField): JSONSchema7 {\n const base: JSONSchema7 = {};\n\n if (field.label !== undefined) {\n base.title = field.label;\n }\n\n switch (field._field) {\n case \"text\":\n return { ...base, type: \"string\" };\n\n case \"number\":\n return {\n ...base,\n type: \"number\",\n ...(field.min !== undefined && { minimum: field.min }),\n ...(field.max !== undefined && { maximum: field.max }),\n };\n\n case \"boolean\":\n return { ...base, type: \"boolean\" };\n\n case \"enum\": {\n const opts = field.options;\n const isObjectOptions =\n opts.length > 0 &&\n opts.every(\n (opt): opt is { id: string; label: string } =>\n typeof opt === \"object\" && \"id\" in opt && \"label\" in opt\n );\n if (isObjectOptions) {\n // Object options with id/label: use oneOf with const/title\n return {\n ...base,\n type: \"string\",\n oneOf: opts.map((o) => ({\n const: o.id,\n title: o.label,\n })),\n };\n }\n return { ...base, type: \"string\", enum: opts as readonly string[] };\n }\n\n case \"dynamic_enum\":\n // Dynamic enums are strings at the schema level\n // The actual options are resolved at runtime\n // x-formspec-source indicates the data source key\n // x-formspec-params indicates dependent field names for fetching options\n return {\n ...base,\n type: \"string\",\n \"x-formspec-source\": field.source,\n ...(field.params !== undefined &&\n field.params.length > 0 && { \"x-formspec-params\": field.params }),\n };\n\n case \"dynamic_schema\":\n // Dynamic schemas are objects with unknown properties\n // x-formspec-schemaSource indicates where to load the schema from\n return {\n ...base,\n type: \"object\",\n additionalProperties: true,\n \"x-formspec-schemaSource\": field.schemaSource,\n };\n\n case \"array\": {\n const arrayField = field as ArrayField<string, readonly FormElement[]>;\n return {\n ...base,\n type: \"array\",\n items: generateNestedSchema(arrayField.items),\n ...(arrayField.minItems !== undefined && { minItems: arrayField.minItems }),\n ...(arrayField.maxItems !== undefined && { maxItems: arrayField.maxItems }),\n };\n }\n\n case \"object\": {\n const objectField = field as ObjectField<string, readonly FormElement[]>;\n const nestedSchema = generateNestedSchema(objectField.properties);\n return {\n ...base,\n ...nestedSchema,\n };\n }\n\n default: {\n // Exhaustiveness check\n const _exhaustive: never = field;\n return _exhaustive;\n }\n }\n}\n\n/**\n * Visits all elements in a form tree, collecting fields and required fields.\n */\nfunction collectFields(\n elements: readonly FormElement[],\n properties: Record<string, JSONSchema7>,\n required: string[]\n): void {\n for (const element of elements) {\n switch (element._type) {\n case \"field\":\n properties[element.name] = fieldToJsonSchema(element);\n if (element.required === true) {\n required.push(element.name);\n }\n break;\n\n case \"group\":\n // Groups don't affect schema structure, just collect their children\n collectFields((element as Group<readonly FormElement[]>).elements, properties, required);\n break;\n\n case \"conditional\":\n // Conditional fields are still part of the schema\n // They're just hidden/shown in the UI\n collectFields(\n (element as Conditional<string, unknown, readonly FormElement[]>).elements,\n properties,\n required\n );\n break;\n }\n }\n}\n\n/**\n * Generates a JSON Schema from a FormSpec.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n *\n * const schema = generateJsonSchema(form);\n * // {\n * // $schema: \"https://json-schema.org/draft-07/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 * @param form - The FormSpec to convert\n * @returns A JSON Schema object\n */\nexport function generateJsonSchema<E extends readonly FormElement[]>(\n form: FormSpec<E>\n): JSONSchema7 {\n const properties: Record<string, JSONSchema7> = {};\n const required: string[] = [];\n\n collectFields(form.elements, properties, required);\n\n // Deduplicate required array (can have duplicates when the same field is defined\n // in multiple branches/containers, e.g., repeated in different conditional branches)\n const uniqueRequired = [...new Set(required)];\n\n const result: JSONSchema7 = {\n $schema: \"https://json-schema.org/draft-07/schema#\",\n type: \"object\",\n properties,\n ...(uniqueRequired.length > 0 && { required: uniqueRequired }),\n };\n\n return parseOrThrow(jsonSchema7Schema, result, \"JSON Schema\");\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 for FormSpec forms.\n */\n\nimport type { FormElement, FormSpec, Group, Conditional } from \"@formspec/core\";\nimport type { UISchemaElement, UISchema, ControlElement, GroupLayout, Rule } from \"./types.js\";\nimport { uiSchema as uiSchemaValidator } from \"./schema.js\";\nimport type { FormSpecField } from \"../analyzer/type-converter.js\";\nimport { z } from \"zod\";\n\n/**\n * Parses a value through a Zod schema, converting validation errors to a 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.\n */\nfunction fieldToScope(fieldName: string): string {\n return `#/properties/${fieldName}`;\n}\n\n/**\n * Creates a rule for conditional visibility.\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 rules into one using allOf.\n *\n * When elements are nested inside multiple conditionals, all conditions\n * must be met for the element to be visible.\n */\nfunction combineRules(parentRule: Rule, childRule: Rule): Rule {\n // Both rules should have the same effect (SHOW)\n // Combine conditions using allOf\n const parentCondition = parentRule.condition;\n const childCondition = childRule.condition;\n\n return {\n effect: \"SHOW\",\n condition: {\n scope: \"#\",\n schema: {\n allOf: [\n {\n properties: {\n [parentCondition.scope.replace(\"#/properties/\", \"\")]: parentCondition.schema,\n },\n },\n {\n properties: {\n [childCondition.scope.replace(\"#/properties/\", \"\")]: childCondition.schema,\n },\n },\n ],\n },\n },\n };\n}\n\n/**\n * Converts form elements to UI Schema elements.\n *\n * @param elements - The form elements to convert\n * @param parentRule - Optional rule inherited from parent conditional\n * @returns Array of UI Schema elements\n */\nfunction elementsToUiSchema(\n elements: readonly FormElement[],\n parentRule?: Rule\n): UISchemaElement[] {\n const result: UISchemaElement[] = [];\n\n for (const element of elements) {\n switch (element._type) {\n case \"field\": {\n const control: ControlElement = {\n type: \"Control\",\n scope: fieldToScope(element.name),\n ...(element.label !== undefined && { label: element.label }),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n result.push(control);\n break;\n }\n\n case \"group\": {\n const groupElement = element as Group<readonly FormElement[]>;\n const group: GroupLayout = {\n type: \"Group\",\n label: groupElement.label,\n elements: elementsToUiSchema(groupElement.elements, parentRule),\n ...(parentRule !== undefined && { rule: parentRule }),\n };\n result.push(group);\n break;\n }\n\n case \"conditional\": {\n const conditionalElement = element as Conditional<string, unknown, readonly FormElement[]>;\n // Create a rule for this conditional\n const newRule = createShowRule(conditionalElement.field, conditionalElement.value);\n // Combine with parent rule if present (for nested conditionals)\n const combinedRule = parentRule !== undefined ? combineRules(parentRule, newRule) : newRule;\n // Apply the combined rule to all children\n const childElements = elementsToUiSchema(conditionalElement.elements, combinedRule);\n result.push(...childElements);\n break;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Converts a single FormSpecField to a ControlElement, resolving showWhen into a rule.\n *\n * @param field - The FormSpecField to convert\n * @param scopePrefix - The JSON Pointer prefix for the field's scope\n * @returns A ControlElement\n */\nfunction formSpecFieldToElement(\n field: FormSpecField,\n scopePrefix = \"#/properties\"\n): ControlElement {\n const control: ControlElement = {\n type: \"Control\",\n scope: `${scopePrefix}/${field.id}`,\n };\n\n if (field.label !== undefined) {\n control.label = field.label;\n }\n\n if (\n field.showWhen !== undefined &&\n typeof field.showWhen === \"object\" &&\n \"field\" in field.showWhen &&\n \"value\" in field.showWhen\n ) {\n const sw = field.showWhen as { field: string; value: unknown };\n control.rule = {\n effect: \"SHOW\",\n condition: {\n scope: `#/properties/${sw.field}`,\n schema: { const: sw.value },\n },\n };\n }\n\n return control;\n}\n\n/**\n * Converts FormSpecField[] (from decorator/interface/type analysis) to a JSON Forms UISchema.\n *\n * Mapping:\n * - Each field → `{ type: \"Control\", scope: \"#/properties/{id}\", label? }`\n * - `showWhen: { field, value }` → rule with SHOW effect\n * - `group` property → Groups fields by group name, preserving insertion order\n * - `fields` (nested object) → single Control pointing to the object property\n * - Root wrapper → `{ type: \"VerticalLayout\", elements }`\n *\n * @param fields - The FormSpecField array to convert\n * @returns A JSON Forms UISchema\n */\nexport function generateUiSchemaFromFields(fields: FormSpecField[]): UISchema {\n // Collect elements, grouping by the `group` property.\n // Map preserves insertion order — first occurrence of a group name determines its position.\n const groupMap = new Map<string, ControlElement[]>();\n const orderedKeys: (string | null)[] = []; // null = ungrouped slot\n const ungrouped: ControlElement[] = [];\n\n for (const field of fields) {\n const element = formSpecFieldToElement(field);\n\n if (field.group !== undefined) {\n if (!groupMap.has(field.group)) {\n groupMap.set(field.group, []);\n orderedKeys.push(field.group);\n }\n // We know the key exists since we just set it above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n groupMap.get(field.group)!.push(element);\n } else {\n // Track position for ungrouped fields relative to grouped fields.\n // Use a sentinel to mark the slot for ungrouped elements inline.\n orderedKeys.push(null);\n ungrouped.push(element);\n }\n }\n\n // Build the flat elements list respecting insertion order.\n const elements: UISchemaElement[] = [];\n let ungroupedIndex = 0;\n\n for (const key of orderedKeys) {\n if (key === null) {\n // Ungrouped field — emit directly.\n const el = ungrouped[ungroupedIndex++];\n if (el !== undefined) {\n elements.push(el);\n }\n } else {\n // Each group key appears in orderedKeys exactly once (guarded by\n // `!groupMap.has()` above), so we emit the Group element directly.\n const groupElements = groupMap.get(key) ?? [];\n const groupLayout: GroupLayout = {\n type: \"Group\",\n label: key,\n elements: groupElements,\n };\n elements.push(groupLayout);\n }\n }\n\n const result: UISchema = {\n type: \"VerticalLayout\",\n elements,\n };\n\n return parseOrThrow(uiSchemaValidator, result, \"UI Schema\");\n}\n\n/**\n * Generates a JSON Forms UI Schema from a FormSpec.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * group(\"Customer\",\n * field.text(\"name\", { label: \"Name\" }),\n * ),\n * when(\"status\", \"draft\",\n * field.text(\"notes\", { label: \"Notes\" }),\n * ),\n * );\n *\n * const uiSchema = generateUiSchema(form);\n * // {\n * // type: \"VerticalLayout\",\n * // elements: [\n * // {\n * // type: \"Group\",\n * // label: \"Customer\",\n * // elements: [\n * // { type: \"Control\", scope: \"#/properties/name\", label: \"Name\" }\n * // ]\n * // },\n * // {\n * // type: \"Control\",\n * // scope: \"#/properties/notes\",\n * // label: \"Notes\",\n * // rule: {\n * // effect: \"SHOW\",\n * // condition: { scope: \"#/properties/status\", schema: { const: \"draft\" } }\n * // }\n * // }\n * // ]\n * // }\n * ```\n *\n * @param form - The FormSpec to convert\n * @returns A JSON Forms UI Schema\n */\nexport function generateUiSchema<E extends readonly FormElement[]>(form: FormSpec<E>): UISchema {\n const result: UISchema = {\n type: \"VerticalLayout\",\n elements: elementsToUiSchema(form.elements),\n };\n\n return parseOrThrow(uiSchemaValidator, result, \"UI Schema\");\n}\n","/**\n * JSON Schema Draft-07 type definitions.\n *\n * These types are a subset of JSON Schema sufficient for form generation.\n */\n\n/**\n * JSON Schema primitive types.\n */\nexport type JSONSchemaType =\n | \"string\"\n | \"number\"\n | \"integer\"\n | \"boolean\"\n | \"object\"\n | \"array\"\n | \"null\";\n\n/**\n * A JSON Schema definition (draft-07 subset).\n */\nexport interface JSONSchema7 {\n $schema?: string;\n $id?: string;\n $ref?: string;\n\n // Metadata\n title?: string;\n description?: string;\n deprecated?: boolean;\n\n // Type\n type?: JSONSchemaType | JSONSchemaType[];\n\n // String validation\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n\n // Number validation\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n\n // Enum\n enum?: readonly (string | number | boolean | null)[];\n const?: string | number | boolean | null;\n\n // Object\n properties?: Record<string, JSONSchema7>;\n required?: string[];\n additionalProperties?: boolean | JSONSchema7;\n\n // Array\n items?: JSONSchema7 | JSONSchema7[];\n minItems?: number;\n maxItems?: number;\n\n // Composition\n allOf?: JSONSchema7[];\n anyOf?: JSONSchema7[];\n oneOf?: JSONSchema7[];\n not?: JSONSchema7;\n\n // Conditional\n if?: JSONSchema7;\n then?: JSONSchema7;\n else?: JSONSchema7;\n\n // Format\n format?: string;\n\n // Default\n default?: unknown;\n\n // =============================================================================\n // FormSpec Extensions (x- prefixed)\n // =============================================================================\n\n /**\n * Data source key for dynamic enum fields.\n * Indicates that options should be fetched from a registered resolver.\n */\n \"x-formspec-source\"?: string;\n\n /**\n * Field names whose values are needed to fetch dynamic enum options.\n * Used for dependent/cascading dropdowns.\n */\n \"x-formspec-params\"?: readonly string[];\n\n /**\n * Schema source identifier for dynamic schema fields.\n * Indicates that the schema should be loaded dynamically at runtime.\n */\n \"x-formspec-schemaSource\"?: string;\n}\n\n/** Extension properties for custom FormSpec decorators. */\nexport type FormSpecSchemaExtensions = Record<`x-formspec-${string}`, unknown>;\n\n/** JSON Schema with FormSpec extension properties for arbitrary x-formspec-* keys. */\nexport type ExtendedJSONSchema7 = JSONSchema7 & FormSpecSchemaExtensions;\n\n/**\n * Sets a FormSpec extension property on a JSON Schema node.\n *\n * Use this to safely add `x-formspec-*` properties to any schema,\n * including nested schemas typed as `JSONSchema7` (which don't carry\n * the extension index signature).\n *\n * @param schema - Any JSON Schema node\n * @param key - Extension key (must start with `x-formspec-`)\n * @param value - Extension value\n */\nexport function setSchemaExtension(\n schema: JSONSchema7,\n key: `x-formspec-${string}`,\n value: unknown\n): void {\n (schema as ExtendedJSONSchema7)[key] = value;\n}\n\n/**\n * Reads a FormSpec extension property from a JSON Schema node.\n *\n * Use this to safely read `x-formspec-*` properties from any schema,\n * including nested schemas typed as `JSONSchema7`.\n *\n * @param schema - Any JSON Schema node\n * @param key - Extension key (must start with `x-formspec-`)\n * @returns The extension value, or `undefined` if not present\n */\nexport function getSchemaExtension(schema: JSONSchema7, key: `x-formspec-${string}`): unknown {\n return (schema as ExtendedJSONSchema7)[key];\n}\n","/**\n * Decorator extractor for parsing decorator AST nodes.\n *\n * Extracts decorator names and arguments from class field decorators,\n * supporting the FormSpec decorator DSL (@Field, @Minimum, @Maximum, etc.).\n *\n * Also supports branded type resolution via the TypeScript type checker\n * to detect custom decorators created with `extendDecorator` and\n * `customDecorator` from `@formspec/decorators`.\n */\n\nimport * as ts from \"typescript\";\nimport { type FormSpecDecoratorName } from \"@formspec/core\";\n\n/**\n * Extracted decorator information.\n */\nexport interface DecoratorInfo {\n /** Decorator name (e.g., \"Field\", \"Minimum\") */\n name: string;\n /** Decorator arguments as literal values */\n args: DecoratorArg[];\n /** Raw AST node for the decorator (undefined for synthetic JSDoc constraint entries) */\n node: ts.Decorator | undefined;\n /** Resolved brand information from the type checker (populated by analyzeField) */\n resolved?: ResolvedDecorator;\n}\n\n/**\n * A decorator argument value.\n * Can be a primitive, array, or object literal.\n */\nexport type DecoratorArg =\n | string\n | number\n | boolean\n | null\n | DecoratorArg[]\n | { [key: string]: DecoratorArg };\n\n/**\n * Result of resolving a decorator via the type checker.\n */\nexport interface ResolvedDecorator {\n /** Decorator name as it appears in source */\n name: string;\n /** If this extends a built-in, the built-in name (e.g., \"Field\") */\n extendsBuiltin?: string;\n /** If this belongs to a CLI extension namespace, the namespace name */\n extensionName?: string;\n /** Whether this is a known FormSpec decorator (built-in or factory-created) */\n isFormSpec: boolean;\n /** Whether this is a marker (zero-arg) decorator */\n isMarker: boolean;\n}\n\n/**\n * Extracts decorators from a class member (property or method).\n *\n * @param member - The class member to extract decorators from\n * @returns Array of extracted decorator info\n */\nexport function extractDecorators(\n member: ts.PropertyDeclaration | ts.MethodDeclaration\n): DecoratorInfo[] {\n const decorators: DecoratorInfo[] = [];\n\n // TC39 decorators are in the modifiers array\n const modifiers = ts.canHaveDecorators(member) ? ts.getDecorators(member) : undefined;\n\n if (!modifiers) return decorators;\n\n for (const decorator of modifiers) {\n const info = parseDecorator(decorator);\n if (info) {\n decorators.push(info);\n }\n }\n\n return decorators;\n}\n\n/**\n * Parses a single decorator node.\n */\nfunction parseDecorator(decorator: ts.Decorator): DecoratorInfo | null {\n const expr = decorator.expression;\n\n // Simple decorator: @Decorator\n if (ts.isIdentifier(expr)) {\n return {\n name: expr.text,\n args: [],\n node: decorator,\n };\n }\n\n // Call expression: @Decorator(args)\n if (ts.isCallExpression(expr)) {\n const callee = expr.expression;\n\n // Get decorator name\n let name: string | null = null;\n if (ts.isIdentifier(callee)) {\n name = callee.text;\n } else if (ts.isPropertyAccessExpression(callee)) {\n // For namespaced decorators like @formspec.Field()\n name = callee.name.text;\n }\n\n if (!name) return null;\n\n // Extract arguments\n const args = expr.arguments.map(extractArgValue);\n\n return {\n name,\n args,\n node: decorator,\n };\n }\n\n return null;\n}\n\n/**\n * Extracts the value from an expression node.\n * Supports literals, arrays, object literals, and RegExp.\n */\nfunction extractArgValue(node: ts.Expression): DecoratorArg {\n // String literal\n if (ts.isStringLiteral(node)) {\n return node.text;\n }\n\n // Numeric literal\n if (ts.isNumericLiteral(node)) {\n return Number(node.text);\n }\n\n // Boolean literals (true/false are identifiers in TS AST)\n if (node.kind === ts.SyntaxKind.TrueKeyword) {\n return true;\n }\n if (node.kind === ts.SyntaxKind.FalseKeyword) {\n return false;\n }\n\n // Null literal\n if (node.kind === ts.SyntaxKind.NullKeyword) {\n return null;\n }\n\n // Prefix unary expression (for negative numbers)\n if (ts.isPrefixUnaryExpression(node)) {\n if (node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) {\n return -Number(node.operand.text);\n }\n if (node.operator === ts.SyntaxKind.PlusToken && ts.isNumericLiteral(node.operand)) {\n return Number(node.operand.text);\n }\n }\n\n // Array literal\n if (ts.isArrayLiteralExpression(node)) {\n return node.elements.map((el) => {\n if (ts.isSpreadElement(el)) {\n // Can't evaluate spread at compile time\n return null;\n }\n return extractArgValue(el);\n });\n }\n\n // Object literal\n if (ts.isObjectLiteralExpression(node)) {\n const obj: Record<string, DecoratorArg> = {};\n for (const prop of node.properties) {\n if (ts.isPropertyAssignment(prop)) {\n const key = getPropertyName(prop.name);\n if (key) {\n obj[key] = extractArgValue(prop.initializer);\n }\n } else if (ts.isShorthandPropertyAssignment(prop)) {\n // { foo } shorthand - we can't resolve the value\n const key = prop.name.text;\n obj[key] = null;\n }\n }\n return obj;\n }\n\n // Template literal (simple case)\n if (ts.isNoSubstitutionTemplateLiteral(node)) {\n return node.text;\n }\n\n // RegExp literal: extract the source pattern string\n if (ts.isRegularExpressionLiteral(node)) {\n const regexText = node.text;\n // RegExp literal format is /pattern/flags\n const lastSlash = regexText.lastIndexOf(\"/\");\n if (lastSlash > 0) {\n return regexText.substring(1, lastSlash);\n }\n return regexText;\n }\n\n // new RegExp(\"pattern\") — extract pattern from constructor call\n if (ts.isNewExpression(node)) {\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === \"RegExp\" &&\n node.arguments &&\n node.arguments.length > 0\n ) {\n const firstArg = node.arguments[0];\n if (firstArg && ts.isStringLiteral(firstArg)) {\n return firstArg.text;\n }\n }\n }\n\n // Identifier - could be an enum member or constant\n // We can't resolve it statically, return null\n if (ts.isIdentifier(node)) {\n return null;\n }\n\n // For other expressions, return null\n return null;\n}\n\n/**\n * Gets the property name from a property name node.\n */\nfunction getPropertyName(name: ts.PropertyName): string | null {\n if (ts.isIdentifier(name)) {\n return name.text;\n }\n if (ts.isStringLiteral(name)) {\n return name.text;\n }\n if (ts.isNumericLiteral(name)) {\n return name.text;\n }\n // Computed property names can't be resolved statically\n return null;\n}\n\n/**\n * Known FormSpec decorators and their expected argument types.\n *\n * This metadata object provides additional information about each decorator's\n * expected argument types. The keys are constrained to match FormSpecDecoratorName.\n */\nexport const FORMSPEC_DECORATORS: Record<FormSpecDecoratorName, { argTypes: readonly string[] }> = {\n // Display metadata\n Field: { argTypes: [\"object\"] },\n\n // Grouping\n Group: { argTypes: [\"string\"] },\n\n // Conditional display\n ShowWhen: { argTypes: [\"object\"] },\n\n // Enum options\n EnumOptions: { argTypes: [\"array\"] },\n\n // Numeric constraints\n Minimum: { argTypes: [\"number\"] },\n Maximum: { argTypes: [\"number\"] },\n ExclusiveMinimum: { argTypes: [\"number\"] },\n ExclusiveMaximum: { argTypes: [\"number\"] },\n\n // String constraints\n MinLength: { argTypes: [\"number\"] },\n MaxLength: { argTypes: [\"number\"] },\n Pattern: { argTypes: [\"string\"] },\n} as const;\n\n/**\n * Checks if a file path belongs to the @formspec/decorators package.\n *\n * Matches both installed node_modules paths and local monorepo paths.\n */\nfunction isFormSpecDecoratorsPath(fileName: string): boolean {\n // Normalize separators for cross-platform matching\n const normalized = fileName.replace(/\\\\/g, \"/\");\n return (\n normalized.includes(\"node_modules/@formspec/decorators\") ||\n normalized.includes(\"/packages/decorators/\")\n );\n}\n\n/**\n * Resolves a decorator via the TypeScript type checker to determine\n * if it is a FormSpec decorator (built-in, extended, or custom).\n *\n * This enables detection of:\n * 1. Direct imports of built-in decorators from `@formspec/decorators`\n * 2. Extended decorators created via `extendDecorator(...).as(...)`\n * 3. Custom decorators created via `customDecorator(...).as(...)` or `.marker(...)`\n *\n * @param decorator - The decorator AST node\n * @param checker - TypeScript type checker\n * @returns Resolved decorator information, or null if not resolvable\n */\nexport function resolveDecorator(\n decorator: ts.Decorator,\n checker: ts.TypeChecker\n): ResolvedDecorator | null {\n const expr = decorator.expression;\n\n // Get the identifier to resolve\n let targetNode: ts.Node;\n let name: string;\n\n if (ts.isIdentifier(expr)) {\n // Simple marker decorator: @Decorator\n targetNode = expr;\n name = expr.text;\n } else if (ts.isCallExpression(expr)) {\n // Parameterized decorator: @Decorator(args)\n if (ts.isIdentifier(expr.expression)) {\n targetNode = expr.expression;\n name = expr.expression.text;\n } else {\n return null;\n }\n } else {\n return null;\n }\n\n // Check if it's a known built-in by name\n if (name in FORMSPEC_DECORATORS) {\n // Verify it actually comes from @formspec/decorators by checking the symbol\n const symbol = checker.getSymbolAtLocation(targetNode);\n if (symbol) {\n const declarations = symbol.declarations;\n if (declarations && declarations.length > 0) {\n const decl = declarations[0];\n if (decl) {\n const sourceFile = decl.getSourceFile();\n const fileName = sourceFile.fileName;\n if (isFormSpecDecoratorsPath(fileName)) {\n return {\n name,\n isFormSpec: true,\n isMarker: !ts.isCallExpression(expr),\n };\n }\n }\n }\n }\n }\n\n // Try to resolve branded types for custom/extended decorators\n const resolvedSymbol = checker.getSymbolAtLocation(targetNode);\n if (!resolvedSymbol) return null;\n\n const type = checker.getTypeOfSymbol(resolvedSymbol);\n const props = type.getProperties();\n\n let extendsBuiltin: string | undefined;\n let extensionName: string | undefined;\n let isMarker = false;\n\n for (const prop of props) {\n // __String is a branded string type; cast is safe for read-only string operations\n const escapedName = prop.getEscapedName() as string;\n\n // TypeScript represents unique symbol properties as __@<name>@<uniqueId>\n // in escaped names. The <name> portion may be either the Symbol description\n // (e.g., \"formspec.extends\") or the const variable name (e.g., \"FORMSPEC_EXTENDS\"),\n // depending on how the symbol is declared and resolved by the type checker.\n // We check for both patterns to handle all cases.\n if (\n escapedName.startsWith(\"__@\") &&\n (escapedName.includes(\"formspec.extends\") || escapedName.includes(\"FORMSPEC_EXTENDS\"))\n ) {\n const propType = checker.getTypeOfSymbol(prop);\n if (propType.isStringLiteral()) {\n extendsBuiltin = propType.value;\n }\n }\n\n if (\n escapedName.startsWith(\"__@\") &&\n (escapedName.includes(\"formspec.extension\") || escapedName.includes(\"FORMSPEC_EXTENSION\"))\n ) {\n const propType = checker.getTypeOfSymbol(prop);\n if (propType.isStringLiteral()) {\n extensionName = propType.value;\n }\n }\n\n if (\n escapedName.startsWith(\"__@\") &&\n (escapedName.includes(\"formspec.marker\") || escapedName.includes(\"FORMSPEC_MARKER\"))\n ) {\n isMarker = true;\n }\n }\n\n if (extendsBuiltin) {\n return {\n name,\n extendsBuiltin,\n isFormSpec: true,\n isMarker: false,\n };\n }\n\n if (extensionName) {\n return {\n name,\n extensionName,\n isFormSpec: true,\n isMarker,\n };\n }\n\n if (isMarker) {\n return {\n name,\n isFormSpec: true,\n isMarker: true,\n };\n }\n\n return null;\n}\n","/**\n * JSDoc constraint tag extractor.\n *\n * Extracts constraint tags from JSDoc comments on class fields and returns\n * synthetic {@link DecoratorInfo} objects that integrate seamlessly with\n * the existing decorator-based constraint pipeline.\n *\n * Supported tags correspond to keys in {@link CONSTRAINT_TAG_DEFINITIONS}\n * from `@formspec/core` (e.g., `@Minimum`, `@Maximum`, `@Pattern`).\n */\n\nimport * as ts from \"typescript\";\nimport { CONSTRAINT_TAG_DEFINITIONS, type ConstraintTagName } from \"@formspec/core\";\nimport type { DecoratorArg, DecoratorInfo } from \"./decorator-extractor.js\";\n\n/**\n * Extracts JSDoc constraint tags from a TypeScript AST node and returns\n * synthetic {@link DecoratorInfo} objects.\n *\n * For each recognised tag (case-sensitive PascalCase match against\n * {@link CONSTRAINT_TAG_DEFINITIONS}), the comment text is parsed\n * according to the tag's declared value type:\n * - `\"number\"` tags: parsed via `Number()` — skipped when NaN\n * - `\"string\"` tags (`Pattern`): used as-is (trimmed)\n *\n * @param node - The AST node to inspect for JSDoc tags\n * @returns Synthetic decorator info objects for each valid constraint tag\n */\nexport function extractJSDocConstraints(node: ts.Node): DecoratorInfo[] {\n const results: DecoratorInfo[] = [];\n const jsDocTags = ts.getJSDocTags(node);\n\n for (const tag of jsDocTags) {\n const tagName = tag.tagName.text;\n\n // Case-sensitive check against known constraint tags\n if (!(tagName in CONSTRAINT_TAG_DEFINITIONS)) {\n continue;\n }\n\n const constraintName = tagName as ConstraintTagName;\n const expectedType = CONSTRAINT_TAG_DEFINITIONS[constraintName];\n\n // Extract comment text — can be string, NodeArray<JSDocComment>, or undefined\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText === \"\") {\n continue;\n }\n\n const trimmed = commentText.trim();\n if (trimmed === \"\") {\n continue;\n }\n\n if (expectedType === \"number\") {\n const value = Number(trimmed);\n if (Number.isNaN(value)) {\n continue;\n }\n results.push(createSyntheticDecorator(constraintName, value));\n } else if (expectedType === \"json\") {\n // JSON type (EnumOptions) — parse inline JSON array only.\n // Downstream UI schema generation expects an array of options.\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (!Array.isArray(parsed)) {\n continue;\n }\n results.push(createSyntheticDecorator(constraintName, parsed as DecoratorArg));\n } catch {\n // Skip malformed JSON\n continue;\n }\n } else {\n // \"string\" type (Pattern)\n results.push(createSyntheticDecorator(constraintName, trimmed));\n }\n }\n\n return results;\n}\n\n/**\n * Extracts `@Field_displayName` and `@Field_description` TSDoc tags from\n * a node and returns a synthetic `Field` {@link DecoratorInfo} if either\n * is present.\n *\n * This enables interface properties to carry display metadata via TSDoc\n * tags instead of the `@Field` decorator (which requires a class):\n *\n * ```typescript\n * interface Config {\n * // @Field_displayName Program Name\n * // @Field_description Internal identifier\n * programName: string;\n * }\n * ```\n *\n * @param node - The AST node to inspect for display metadata tags\n * @returns A synthetic `Field` decorator info, or null if no tags found\n */\nexport function extractJSDocFieldMetadata(node: ts.Node): DecoratorInfo | null {\n const jsDocTags = ts.getJSDocTags(node);\n\n let displayName: string | undefined;\n let description: string | undefined;\n\n for (const tag of jsDocTags) {\n const tagName = tag.tagName.text;\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText.trim() === \"\") {\n continue;\n }\n\n const trimmed = commentText.trim();\n\n if (tagName === \"Field_displayName\") {\n displayName = trimmed;\n } else if (tagName === \"Field_description\") {\n description = trimmed;\n }\n }\n\n if (displayName === undefined && description === undefined) {\n return null;\n }\n\n // Build the FieldOptions-shaped arg object\n const fieldOpts: Record<string, DecoratorArg> = {\n ...(displayName !== undefined ? { displayName } : {}),\n ...(description !== undefined ? { description } : {}),\n };\n\n return createSyntheticDecorator(\"Field\", fieldOpts);\n}\n\n/**\n * Extracts the text content from a JSDoc tag's comment.\n *\n * The `tag.comment` property can be a plain string, an array of\n * `JSDocComment` nodes, or undefined. This helper normalises all\n * three cases to a single `string | undefined`.\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 // NodeArray<JSDocComment> — concatenate text spans\n return ts.getTextOfJSDocComment(tag.comment);\n}\n\n/**\n * Creates a synthetic {@link DecoratorInfo} for a JSDoc constraint tag.\n *\n * The `node` field is `undefined` because JSDoc constraints have no\n * decorator AST node. Downstream constraint processing only uses\n * the `name` and `args` fields.\n */\nfunction createSyntheticDecorator(name: string, value: DecoratorArg): DecoratorInfo {\n return {\n name,\n args: [value],\n node: undefined,\n };\n}\n","/**\n * Class analyzer for extracting fields, types, and decorators.\n *\n * Analyzes a TypeScript class declaration to extract:\n * - Field names and TypeScript types\n * - Decorator metadata (Field, Minimum, Maximum, etc.)\n * - Field optionality\n * - TSDoc @deprecated tags\n * - Default values from property initializers\n */\n\nimport * as ts from \"typescript\";\nimport { extractDecorators, resolveDecorator, type DecoratorInfo } from \"./decorator-extractor.js\";\nimport { extractJSDocConstraints, extractJSDocFieldMetadata } from \"./jsdoc-constraints.js\";\n\n/**\n * Analyzed field information from a class.\n */\nexport interface FieldInfo {\n /** Field name */\n name: string;\n /** TypeScript type node for the field */\n typeNode: ts.TypeNode | undefined;\n /** Resolved type from the type checker */\n type: ts.Type;\n /** Whether the field is optional (has ? modifier) */\n optional: boolean;\n /** Decorators applied to the field */\n decorators: DecoratorInfo[];\n /** Whether the field has a TSDoc @deprecated tag */\n deprecated: boolean;\n /** Default value extracted from the property initializer (literal values only) */\n defaultValue: unknown;\n}\n\n/**\n * Result of analyzing a class declaration.\n */\nexport interface ClassAnalysis {\n /** Class name */\n name: string;\n /** Analyzed fields */\n fields: FieldInfo[];\n /** Instance methods */\n instanceMethods: MethodInfo[];\n /** Static methods */\n staticMethods: MethodInfo[];\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 * Analyzes a class declaration to extract fields and methods.\n *\n * @param classDecl - The class declaration to analyze\n * @param checker - TypeScript type checker\n * @returns Analysis result with fields and methods\n */\nexport function analyzeClass(\n classDecl: ts.ClassDeclaration,\n checker: ts.TypeChecker\n): ClassAnalysis {\n const name = classDecl.name?.text ?? \"AnonymousClass\";\n const fields: FieldInfo[] = [];\n const instanceMethods: MethodInfo[] = [];\n const staticMethods: MethodInfo[] = [];\n\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member)) {\n const fieldInfo = analyzeField(member, checker);\n if (fieldInfo) {\n fields.push(fieldInfo);\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 instanceMethods,\n staticMethods,\n };\n}\n\n/**\n * Analyzes a property declaration to extract field info.\n */\nexport function analyzeField(\n prop: ts.PropertyDeclaration,\n checker: ts.TypeChecker\n): FieldInfo | null {\n // Skip computed property names\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const typeNode = prop.type;\n const type = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n const decorators = extractDecorators(prop);\n\n // Resolve each decorator via the type checker to detect extended/custom decorators\n for (const dec of decorators) {\n if (dec.node) {\n const resolved = resolveDecorator(dec.node, checker);\n if (resolved) {\n dec.resolved = resolved;\n }\n }\n }\n\n // Inherit constraints from type alias declarations first (as defaults).\n // Field-level decorators and JSDoc are applied after, so they take precedence.\n if (prop.type) {\n const aliasConstraints = extractTypeAliasConstraints(prop.type, checker);\n decorators.push(...aliasConstraints);\n }\n\n // Merge JSDoc constraint tags (e.g., /** @Minimum 0 @Maximum 100 */)\n const jsdocConstraints = extractJSDocConstraints(prop);\n decorators.push(...jsdocConstraints);\n\n const deprecated = hasDeprecatedTag(prop);\n const defaultValue = extractDefaultValue(prop.initializer);\n\n return {\n name,\n typeNode,\n type,\n optional,\n decorators,\n deprecated,\n defaultValue,\n };\n}\n\n/**\n * Given a type node, checks if it references a type alias and extracts\n * JSDoc constraint tags from the alias declaration.\n *\n * Only constraint tags (`@Minimum`, `@Maximum`, `@Pattern`, etc.) are\n * propagated — display metadata (`@Field_displayName`, `@Field_description`)\n * is intentionally excluded because display metadata is a field-level\n * concern, not a type-level one.\n *\n * This makes `type Percent = number` with `@Minimum 0 @Maximum 100`\n * propagate constraints to any field typed as `Percent`.\n */\nfunction extractTypeAliasConstraints(\n typeNode: ts.TypeNode,\n checker: ts.TypeChecker\n): DecoratorInfo[] {\n // Only handle type references (e.g., `Percent`, not `number` directly)\n if (!ts.isTypeReferenceNode(typeNode)) return [];\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 — those are handled by\n // the nested object analysis pipeline in type-converter.ts\n if (ts.isTypeLiteralNode(aliasDecl.type)) return [];\n\n // Only propagate constraint tags, not display metadata (@Field_displayName,\n // @Field_description). Display metadata on the alias shouldn't override the\n // field's own title/description — those are field-level concerns.\n return extractJSDocConstraints(aliasDecl);\n}\n\n/**\n * Checks if a node has a TSDoc `@deprecated` tag.\n */\nfunction hasDeprecatedTag(node: ts.Node): boolean {\n const jsDocTags = ts.getJSDocTags(node);\n return jsDocTags.some((tag) => tag.tagName.text === \"deprecated\");\n}\n\n/**\n * Extracts a default value from a property initializer.\n *\n * Only extracts literal values (strings, numbers, booleans, null).\n * Non-literal initializers (function calls, expressions, etc.) return undefined.\n */\nfunction extractDefaultValue(initializer: ts.Expression | undefined): unknown {\n if (!initializer) return undefined;\n\n // String literal\n if (ts.isStringLiteral(initializer)) {\n return initializer.text;\n }\n\n // Numeric literal\n if (ts.isNumericLiteral(initializer)) {\n return Number(initializer.text);\n }\n\n // Boolean literals\n if (initializer.kind === ts.SyntaxKind.TrueKeyword) {\n return true;\n }\n if (initializer.kind === ts.SyntaxKind.FalseKeyword) {\n return false;\n }\n\n // Null literal\n if (initializer.kind === ts.SyntaxKind.NullKeyword) {\n return null;\n }\n\n // Negative number\n if (ts.isPrefixUnaryExpression(initializer)) {\n if (\n initializer.operator === ts.SyntaxKind.MinusToken &&\n ts.isNumericLiteral(initializer.operand)\n ) {\n return -Number(initializer.operand.text);\n }\n }\n\n // Non-literal initializer — can't extract statically\n return undefined;\n}\n\n/**\n * Analyzes a method declaration to extract method info.\n */\nfunction analyzeMethod(method: ts.MethodDeclaration, checker: ts.TypeChecker): MethodInfo | null {\n // Skip computed method names\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 {\n name,\n parameters,\n returnTypeNode,\n returnType,\n };\n}\n\n/**\n * Analyzes a parameter declaration.\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 // Parameter is optional if it has a question token or a default value\n const optional = param.questionToken !== undefined || param.initializer !== undefined;\n\n return {\n name,\n typeNode,\n type,\n formSpecExportName,\n optional,\n };\n}\n\n/**\n * Detects if a type node is InferSchema<typeof X> or InferFormSchema<typeof X> and extracts X.\n *\n * @param typeNode - The type node to check\n * @returns The export name X, or null if not a FormSpec inference pattern\n */\nfunction detectFormSpecReference(typeNode: ts.TypeNode | undefined): string | null {\n if (!typeNode) return null;\n\n // Looking for: InferSchema<typeof X> or InferFormSchema<typeof X>\n if (!ts.isTypeReferenceNode(typeNode)) return null;\n\n // Get the type name - could be Identifier or QualifiedName\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 // Support both InferSchema (for elements) and InferFormSchema (for FormSpec)\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 // typeArg.exprName is the identifier (e.g., \"ActivateParams\")\n if (ts.isIdentifier(typeArg.exprName)) {\n return typeArg.exprName.text;\n }\n\n // Could be qualified name like Namespace.ActivateParams\n if (ts.isQualifiedName(typeArg.exprName)) {\n return typeArg.exprName.right.text;\n }\n\n return null;\n}\n\n/**\n * Analyzes an interface declaration to extract field information.\n *\n * Similar to {@link analyzeClass} but for interface declarations.\n * Extracts JSDoc constraint tags (`@Minimum`, `@MaxLength`, etc.) and\n * display metadata (`@Field_displayName`, `@Field_description`) from\n * property signatures, producing the same {@link ClassAnalysis}\n * structure for downstream schema generation.\n *\n * @param interfaceDecl - The interface declaration to analyze\n * @param checker - TypeScript type checker\n * @returns Analysis result with fields (no methods — interfaces have no implementations)\n */\nexport function analyzeInterface(\n interfaceDecl: ts.InterfaceDeclaration,\n checker: ts.TypeChecker\n): ClassAnalysis {\n const name = interfaceDecl.name.text;\n const fields: FieldInfo[] = [];\n\n for (const member of interfaceDecl.members) {\n if (ts.isPropertySignature(member)) {\n const fieldInfo = analyzeInterfaceProperty(member, checker);\n if (fieldInfo) {\n fields.push(fieldInfo);\n }\n }\n }\n\n return {\n name,\n fields,\n instanceMethods: [],\n staticMethods: [],\n };\n}\n\n/**\n * Result of analyzing a type alias — either a successful analysis or\n * an error describing why the alias can't be analyzed.\n */\nexport type AnalyzeTypeAliasResult =\n | { ok: true; analysis: ClassAnalysis }\n | { ok: false; error: string };\n\n/**\n * Analyzes a type alias declaration to extract field information.\n *\n * Supports type aliases whose body is a type literal (object type):\n *\n * ```typescript\n * type Config = {\n * // @Field_displayName Name @Minimum 1\n * name: string;\n * };\n * ```\n *\n * Returns an error result (not an exception) for non-object-literal aliases,\n * allowing callers to accumulate diagnostics across multiple types.\n *\n * @param typeAlias - The type alias declaration to analyze\n * @param checker - TypeScript type checker\n * @returns Success with analysis, or error with a diagnostic message including line number\n */\nexport function analyzeTypeAlias(\n typeAlias: ts.TypeAliasDeclaration,\n checker: ts.TypeChecker\n): AnalyzeTypeAliasResult {\n // Only handle type literals: type X = { ... }\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: FieldInfo[] = [];\n\n for (const member of typeAlias.type.members) {\n if (ts.isPropertySignature(member)) {\n const fieldInfo = analyzeInterfaceProperty(member, checker);\n if (fieldInfo) {\n fields.push(fieldInfo);\n }\n }\n }\n\n return {\n ok: true,\n analysis: {\n name,\n fields,\n instanceMethods: [],\n staticMethods: [],\n },\n };\n}\n\n/**\n * Analyzes an interface property signature to extract field info.\n *\n * Extracts JSDoc constraint tags (`@Minimum`, `@MaxLength`, etc.) and\n * display metadata (`@DisplayName`, `@Description`) from the property's\n * TSDoc comments. Also used by the type converter for nested interface/type\n * alias constraint propagation.\n */\nexport function analyzeInterfaceProperty(\n prop: ts.PropertySignature,\n checker: ts.TypeChecker\n): FieldInfo | null {\n if (!ts.isIdentifier(prop.name)) {\n return null;\n }\n\n const name = prop.name.text;\n const typeNode = prop.type;\n const type = checker.getTypeAtLocation(prop);\n const optional = prop.questionToken !== undefined;\n\n // Interface properties have no decorators — only JSDoc tags\n const decorators: DecoratorInfo[] = [];\n\n // Inherit constraints from type alias declarations first (as defaults).\n // Field-level tags are applied after, so they take precedence.\n if (typeNode) {\n const aliasConstraints = extractTypeAliasConstraints(typeNode, checker);\n decorators.push(...aliasConstraints);\n }\n\n // Extract display metadata (@Field_displayName, @Field_description) as synthetic Field decorator\n const fieldMetadata = extractJSDocFieldMetadata(prop);\n if (fieldMetadata) {\n decorators.push(fieldMetadata);\n }\n\n // Extract constraint tags (@Minimum, @MaxLength, @Pattern, etc.)\n const jsdocConstraints = extractJSDocConstraints(prop);\n decorators.push(...jsdocConstraints);\n\n const deprecated = hasDeprecatedTag(prop);\n\n return {\n name,\n typeNode,\n type,\n optional,\n decorators,\n deprecated,\n defaultValue: undefined,\n };\n}\n","/**\n * Type converter for transforming TypeScript types to JSON Schema and FormSpec.\n *\n * Converts TypeScript types (extracted via type checker) to:\n * - JSON Schema definitions\n * - FormSpec field definitions\n */\n\nimport * as ts from \"typescript\";\nimport type { DecoratorInfo } from \"./decorator-extractor.js\";\nimport { analyzeField, analyzeInterfaceProperty, type FieldInfo } from \"./class-analyzer.js\";\nimport { setSchemaExtension, type ExtendedJSONSchema7 } from \"../json-schema/types.js\";\n\n/**\n * FormSpec field definition (simplified for output).\n */\nexport interface FormSpecField {\n _field: string;\n id: string;\n label?: string;\n placeholder?: string;\n description?: string;\n required?: boolean;\n min?: number;\n max?: number;\n step?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n maxItems?: number;\n pattern?: string;\n options?: (string | { id: string; label: string })[];\n showWhen?: object;\n group?: string;\n fields?: FormSpecField[]; // Nested fields for object types\n}\n\n/**\n * Result of converting a TypeScript type.\n */\nexport interface TypeConversionResult {\n /** JSON Schema representation */\n jsonSchema: ExtendedJSONSchema7;\n /** FormSpec field type */\n formSpecFieldType: string;\n}\n\n/**\n * Given a ts.Type for a named type (class, interface, or type alias with\n * a type literal body), navigates to its declaration and returns a Map\n * from property name to its fully analyzed FieldInfo.\n *\n * - **Classes**: uses `analyzeField` to extract decorators + JSDoc constraints\n * - **Interfaces**: extracts `@Field_displayName`, `@Field_description`, and constraint tags\n * - **Type aliases** (object literals): same as interfaces\n *\n * Returns null for unnamed types (inline objects, mapped types, etc.),\n * preserving existing structural-only behavior for those cases.\n */\nfunction getNamedTypeFieldInfoMap(\n type: ts.Type,\n checker: ts.TypeChecker\n): Map<string, FieldInfo> | null {\n // Check both direct symbol and alias symbol — type aliases resolve to\n // an anonymous __type symbol, with the original alias on type.aliasSymbol.\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, FieldInfo>();\n for (const member of classDecl.members) {\n if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name)) {\n const fieldInfo = analyzeField(member, checker);\n if (fieldInfo) map.set(fieldInfo.name, fieldInfo);\n }\n }\n return map;\n }\n\n // Try interface declaration\n const interfaceDecl = declarations.find(ts.isInterfaceDeclaration);\n if (interfaceDecl) {\n return buildFieldInfoMapFromSignatures(interfaceDecl.members, checker);\n }\n\n // Try type alias with type literal body: type X = { ... }\n const typeAliasDecl = declarations.find(ts.isTypeAliasDeclaration);\n if (typeAliasDecl && ts.isTypeLiteralNode(typeAliasDecl.type)) {\n return buildFieldInfoMapFromSignatures(typeAliasDecl.type.members, checker);\n }\n }\n\n return null;\n}\n\n/**\n * Builds a FieldInfo map from interface/type-literal property signatures,\n * delegating to {@link analyzeInterfaceProperty} for JSDoc extraction.\n */\nfunction buildFieldInfoMapFromSignatures(\n members: ts.NodeArray<ts.TypeElement>,\n checker: ts.TypeChecker\n): Map<string, FieldInfo> {\n const map = new Map<string, FieldInfo>();\n for (const member of members) {\n if (ts.isPropertySignature(member)) {\n const fieldInfo = analyzeInterfaceProperty(member, checker);\n if (fieldInfo) {\n map.set(fieldInfo.name, fieldInfo);\n }\n }\n }\n return map;\n}\n\n/**\n * Resolved information about a single property of an object type.\n *\n * Computed once by `getObjectPropertyInfos` and consumed by both the\n * JSON Schema path (`convertObjectType`) and the UI Schema path\n * (`createFormSpecField`), eliminating duplicated iteration logic.\n */\ninterface ObjectPropertyInfo {\n /** Property name */\n name: string;\n /** Resolved TypeScript type for the property */\n type: ts.Type;\n /** Whether the property is optional */\n optional: boolean;\n /** FieldInfo from the class declaration, if this is a class-typed object */\n fieldInfo: FieldInfo | undefined;\n}\n\n/**\n * Iterates the properties of an object type and resolves each property's\n * type, optionality, and class-level field info (decorators/JSDoc).\n *\n * This is the single source of truth for nested property analysis, used\n * by both the JSON Schema and FormSpec field generation paths.\n */\nfunction getObjectPropertyInfos(\n type: ts.ObjectType,\n checker: ts.TypeChecker\n): ObjectPropertyInfo[] {\n const fieldInfoMap = getNamedTypeFieldInfoMap(type, checker);\n const result: ObjectPropertyInfo[] = [];\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 fieldInfo = fieldInfoMap?.get(prop.name) ?? undefined;\n\n result.push({ name: prop.name, type: propType, optional, fieldInfo });\n }\n\n return result;\n}\n\n/**\n * Converts a TypeScript type to JSON Schema and FormSpec field type.\n *\n * @param type - The TypeScript type to convert\n * @param checker - TypeScript type checker\n * @returns Conversion result with JSON Schema and FormSpec type\n */\nexport function convertType(type: ts.Type, checker: ts.TypeChecker): TypeConversionResult {\n return convertTypeInternal(type, checker, new Set());\n}\n\nfunction convertTypeInternal(\n type: ts.Type,\n checker: ts.TypeChecker,\n visiting: Set<ts.Type>\n): TypeConversionResult {\n // Handle primitive types\n if (type.flags & ts.TypeFlags.String) {\n return { jsonSchema: { type: \"string\" }, formSpecFieldType: \"text\" };\n }\n\n if (type.flags & ts.TypeFlags.Number) {\n return { jsonSchema: { type: \"number\" }, formSpecFieldType: \"number\" };\n }\n\n if (type.flags & ts.TypeFlags.Boolean) {\n return { jsonSchema: { type: \"boolean\" }, formSpecFieldType: \"boolean\" };\n }\n\n if (type.flags & ts.TypeFlags.Null) {\n return { jsonSchema: { type: \"null\" }, formSpecFieldType: \"null\" };\n }\n\n if (type.flags & ts.TypeFlags.Undefined) {\n return { jsonSchema: {}, formSpecFieldType: \"undefined\" };\n }\n\n // Handle literal types\n if (type.isStringLiteral()) {\n return {\n jsonSchema: { const: type.value },\n formSpecFieldType: \"enum\",\n };\n }\n\n if (type.isNumberLiteral()) {\n return {\n jsonSchema: { const: type.value },\n formSpecFieldType: \"number\",\n };\n }\n\n // Handle union types (including string literal unions for enums)\n if (type.isUnion()) {\n return convertUnionType(type, checker, visiting);\n }\n\n // Handle array types\n if (checker.isArrayType(type)) {\n return convertArrayType(type, checker, visiting);\n }\n\n // Handle object types\n if (type.flags & ts.TypeFlags.Object) {\n return convertObjectType(type as ts.ObjectType, checker, visiting);\n }\n\n // Fallback\n return { jsonSchema: {}, formSpecFieldType: \"unknown\" };\n}\n\n/**\n * Converts a union type to JSON Schema.\n */\nfunction convertUnionType(\n type: ts.UnionType,\n checker: ts.TypeChecker,\n visiting: Set<ts.Type>\n): TypeConversionResult {\n const types = type.types;\n\n // Filter out null and undefined for analysis\n // Note: undefined is filtered out since JSON Schema doesn't have an undefined type\n // Optional fields are handled via the 'required' array, not the type\n const nonNullTypes = types.filter(\n (t) => !(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))\n );\n const hasNull = types.some((t) => t.flags & ts.TypeFlags.Null);\n\n // Check if this is a boolean type (true | false in TypeScript)\n // TypeScript represents `boolean` as a union of `true | false` literal types\n const isBooleanUnion =\n nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts.TypeFlags.BooleanLiteral);\n\n if (isBooleanUnion) {\n const result: TypeConversionResult = {\n jsonSchema: { type: \"boolean\" },\n formSpecFieldType: \"boolean\",\n };\n if (hasNull) {\n result.jsonSchema = { oneOf: [{ type: \"boolean\" }, { type: \"null\" }] };\n }\n return result;\n }\n\n // Check if all types are string literals (enum pattern)\n const allStringLiterals = nonNullTypes.every((t) => t.isStringLiteral());\n if (allStringLiterals && nonNullTypes.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- TypeScript doesn't narrow array types from `every` predicate\n const enumValues = nonNullTypes.map((t) => (t as ts.StringLiteralType).value);\n const result: TypeConversionResult = {\n jsonSchema: { enum: enumValues },\n formSpecFieldType: \"enum\",\n };\n if (hasNull) {\n result.jsonSchema = { oneOf: [{ enum: enumValues }, { type: \"null\" }] };\n }\n return result;\n }\n\n // Check if all types are number literals\n const allNumberLiterals = nonNullTypes.every((t) => t.isNumberLiteral());\n if (allNumberLiterals && nonNullTypes.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- TypeScript doesn't narrow array types from `every` predicate\n const enumValues = nonNullTypes.map((t) => (t as ts.NumberLiteralType).value);\n const result: TypeConversionResult = {\n jsonSchema: { enum: enumValues },\n formSpecFieldType: \"enum\",\n };\n if (hasNull) {\n result.jsonSchema = { oneOf: [{ enum: enumValues }, { type: \"null\" }] };\n }\n return result;\n }\n\n // Handle nullable types (T | null or T | undefined) with single non-null type\n if (nonNullTypes.length === 1 && nonNullTypes[0]) {\n const result = convertTypeInternal(nonNullTypes[0], checker, visiting);\n // Make it nullable in JSON Schema\n if (hasNull) {\n result.jsonSchema = { oneOf: [result.jsonSchema, { type: \"null\" }] };\n }\n return result;\n }\n\n // General union - use oneOf (filter out undefined which isn't valid in JSON Schema)\n const schemas = nonNullTypes.map((t) => convertTypeInternal(t, checker, visiting).jsonSchema);\n if (hasNull) {\n schemas.push({ type: \"null\" });\n }\n return {\n jsonSchema: { oneOf: schemas },\n formSpecFieldType: \"union\",\n };\n}\n\n/**\n * Converts an array type to JSON Schema.\n */\nfunction convertArrayType(\n type: ts.Type,\n checker: ts.TypeChecker,\n visiting: Set<ts.Type>\n): TypeConversionResult {\n const typeArgs = (type as ts.TypeReference).typeArguments;\n const elementType = typeArgs?.[0];\n\n const itemSchema = elementType\n ? convertTypeInternal(elementType, checker, visiting).jsonSchema\n : {};\n\n return {\n jsonSchema: {\n type: \"array\",\n items: itemSchema,\n },\n formSpecFieldType: \"array\",\n };\n}\n\n/**\n * Converts an object type to JSON Schema.\n */\nfunction convertObjectType(\n type: ts.ObjectType,\n checker: ts.TypeChecker,\n visiting: Set<ts.Type>\n): TypeConversionResult {\n // Circular reference guard\n if (visiting.has(type)) {\n return { jsonSchema: { type: \"object\" }, formSpecFieldType: \"object\" };\n }\n visiting.add(type);\n\n const properties: Record<string, ExtendedJSONSchema7> = {};\n const required: string[] = [];\n\n for (const propInfo of getObjectPropertyInfos(type, checker)) {\n const propSchema = convertTypeInternal(propInfo.type, checker, visiting).jsonSchema;\n\n // Apply decorator/JSDoc constraints from the class declaration if available\n properties[propInfo.name] = propInfo.fieldInfo\n ? applyDecoratorsToSchema(propSchema, propInfo.fieldInfo.decorators, propInfo.fieldInfo)\n : propSchema;\n\n if (!propInfo.optional) {\n required.push(propInfo.name);\n }\n }\n\n visiting.delete(type);\n\n return {\n jsonSchema: {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n },\n formSpecFieldType: \"object\",\n };\n}\n\n/**\n * Creates a FormSpec field definition from a field's type and decorators.\n *\n * @param fieldName - The field name\n * @param type - The TypeScript type\n * @param decorators - Decorators applied to the field\n * @param optional - Whether the field is optional\n * @param checker - TypeScript type checker\n * @returns FormSpec field definition\n */\nexport function createFormSpecField(\n fieldName: string,\n type: ts.Type,\n decorators: DecoratorInfo[],\n optional: boolean,\n checker: ts.TypeChecker,\n visitedTypes = new Set<ts.Type>()\n): FormSpecField {\n const { formSpecFieldType } = convertType(type, checker);\n\n const field: FormSpecField = {\n _field: formSpecFieldType,\n id: fieldName,\n };\n\n // Apply optionality\n if (!optional) {\n field.required = true;\n }\n\n // For object types, recursively add nested fields.\n // Note: visitedTypes guards against circular references independently from\n // the `visiting` set in convertTypeInternal — they protect different recursion\n // paths (FormSpec field generation vs JSON Schema generation).\n if (formSpecFieldType === \"object\" && type.flags & ts.TypeFlags.Object) {\n if (!visitedTypes.has(type)) {\n visitedTypes.add(type);\n\n const nestedFields: FormSpecField[] = [];\n for (const propInfo of getObjectPropertyInfos(type as ts.ObjectType, checker)) {\n nestedFields.push(\n createFormSpecField(\n propInfo.name,\n propInfo.type,\n propInfo.fieldInfo?.decorators ?? [],\n propInfo.optional,\n checker,\n visitedTypes\n )\n );\n }\n\n visitedTypes.delete(type);\n\n if (nestedFields.length > 0) {\n field.fields = nestedFields;\n }\n }\n }\n\n // Apply decorator values\n for (const dec of decorators) {\n applyDecoratorToField(field, dec);\n }\n\n return field;\n}\n\n/**\n * Applies a decorator's values to a FormSpec field.\n *\n * Note: Custom decorator extensions (x-formspec-*) are only emitted in JSON Schema\n * via `applyDecoratorsToSchema`, not here. The FormSpecField interface does not\n * carry extension data — extensions are a schema-level concern.\n *\n * @param field - The FormSpec field to modify\n * @param decorator - The decorator information to apply\n */\nfunction applyDecoratorToField(field: FormSpecField, decorator: DecoratorInfo): void {\n const { args } = decorator;\n const resolved = decorator.resolved;\n\n // If this is an extended decorator, map it to the built-in it extends\n const effectiveName = resolved?.extendsBuiltin ?? decorator.name;\n\n switch (effectiveName) {\n case \"Field\": {\n // Field takes an object with displayName, description, placeholder\n const opts = args[0];\n if (typeof opts === \"object\" && opts !== null && !Array.isArray(opts)) {\n if (typeof opts[\"displayName\"] === \"string\") {\n field.label = opts[\"displayName\"];\n }\n if (typeof opts[\"description\"] === \"string\") {\n field.description = opts[\"description\"];\n }\n if (typeof opts[\"placeholder\"] === \"string\") {\n field.placeholder = opts[\"placeholder\"];\n }\n }\n break;\n }\n\n case \"Minimum\":\n if (typeof args[0] === \"number\") {\n field.min = args[0];\n }\n break;\n\n case \"Maximum\":\n if (typeof args[0] === \"number\") {\n field.max = args[0];\n }\n break;\n\n case \"MinLength\":\n if (typeof args[0] === \"number\") {\n field.minLength = args[0];\n }\n break;\n\n case \"MaxLength\":\n if (typeof args[0] === \"number\") {\n field.maxLength = args[0];\n }\n break;\n\n case \"Pattern\":\n if (typeof args[0] === \"string\") {\n field.pattern = args[0];\n }\n break;\n\n case \"EnumOptions\":\n if (Array.isArray(args[0])) {\n field.options = args[0] as (string | { id: string; label: string })[];\n }\n break;\n\n case \"ShowWhen\":\n if (typeof args[0] === \"object\" && args[0] !== null) {\n field.showWhen = args[0] as object;\n }\n break;\n\n case \"Group\":\n if (typeof args[0] === \"string\") {\n field.group = args[0];\n }\n break;\n }\n}\n\n/**\n * Applies decorator constraints to a JSON Schema.\n *\n * @param schema - The base JSON Schema\n * @param decorators - Decorators to apply\n * @param fieldInfo - Optional field info for deprecated/default values\n * @returns Modified JSON Schema with constraints\n */\nexport function applyDecoratorsToSchema(\n schema: ExtendedJSONSchema7,\n decorators: DecoratorInfo[],\n fieldInfo?: FieldInfo\n): ExtendedJSONSchema7 {\n const result = { ...schema };\n\n for (const dec of decorators) {\n const { args } = dec;\n const resolved = dec.resolved;\n\n // If this is an extended decorator, map it to the built-in it extends\n const effectiveName = resolved?.extendsBuiltin ?? dec.name;\n\n switch (effectiveName) {\n case \"Field\": {\n // Field takes an object: { displayName, description?, placeholder? }\n const opts = args[0];\n if (typeof opts === \"object\" && opts !== null && !Array.isArray(opts)) {\n if (typeof opts[\"displayName\"] === \"string\") {\n result.title = opts[\"displayName\"];\n }\n if (typeof opts[\"description\"] === \"string\") {\n result.description = opts[\"description\"];\n }\n }\n break;\n }\n\n case \"Minimum\":\n if (typeof args[0] === \"number\") {\n result.minimum = args[0];\n }\n break;\n\n case \"Maximum\":\n if (typeof args[0] === \"number\") {\n result.maximum = args[0];\n }\n break;\n\n case \"ExclusiveMinimum\":\n if (typeof args[0] === \"number\") {\n result.exclusiveMinimum = args[0];\n }\n break;\n\n case \"ExclusiveMaximum\":\n if (typeof args[0] === \"number\") {\n result.exclusiveMaximum = args[0];\n }\n break;\n\n case \"MinLength\":\n if (typeof args[0] === \"number\") {\n result.minLength = args[0];\n }\n break;\n\n case \"MaxLength\":\n if (typeof args[0] === \"number\") {\n result.maxLength = args[0];\n }\n break;\n\n case \"Pattern\":\n if (typeof args[0] === \"string\") {\n result.pattern = args[0];\n }\n break;\n }\n\n // Emit x-formspec-* for custom decorators with a valid extensionName.\n // Extension names must be lowercase alphanumeric with hyphens (e.g., \"title-field\", \"priority\").\n if (resolved?.extensionName && /^[a-z][a-z0-9-]*$/.test(resolved.extensionName)) {\n const key = `x-formspec-${resolved.extensionName}` as const;\n if (resolved.isMarker) {\n setSchemaExtension(result, key, true);\n } else {\n // Parameterized: use first argument as value\n setSchemaExtension(result, key, args[0] ?? true);\n }\n }\n }\n\n // Apply deprecated and default from FieldInfo\n if (fieldInfo) {\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- `deprecated` is a FieldInfo flag tracking @deprecated JSDoc, not itself deprecated\n if (fieldInfo.deprecated) {\n result.deprecated = true;\n }\n if (fieldInfo.defaultValue !== undefined) {\n result.default = fieldInfo.defaultValue;\n }\n }\n\n return result;\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 schema generator.\n *\n * Generates JSON Schema and FormSpec/UI Schema from statically analyzed\n * class fields and decorators.\n */\n\nimport type * as ts from \"typescript\";\nimport type { ClassAnalysis, FieldInfo } from \"../analyzer/class-analyzer.js\";\nimport {\n convertType,\n applyDecoratorsToSchema,\n createFormSpecField,\n type FormSpecField,\n} from \"../analyzer/type-converter.js\";\nimport type { ExtendedJSONSchema7 } from \"../json-schema/types.js\";\nimport type { UISchema } from \"../ui-schema/types.js\";\nimport { generateUiSchemaFromFields } from \"../ui-schema/generator.js\";\nimport {\n createProgramContext,\n findClassByName,\n findInterfaceByName,\n findTypeAliasByName,\n} from \"../analyzer/program.js\";\nimport { analyzeClass, analyzeInterface, analyzeTypeAlias } from \"../analyzer/class-analyzer.js\";\n\n/**\n * Generated schemas for a class.\n */\nexport interface ClassSchemas {\n /** JSON Schema for validation */\n jsonSchema: ExtendedJSONSchema7;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema and FormSpec from a class analysis.\n *\n * Uses static type information and decorator metadata to build\n * complete schema definitions for a class's fields.\n *\n * @param analysis - The class analysis result\n * @param checker - TypeScript type checker\n * @returns Generated JSON Schema and FormSpec\n */\nexport function generateClassSchemas(\n analysis: ClassAnalysis,\n checker: ts.TypeChecker\n): ClassSchemas {\n const properties: Record<string, ExtendedJSONSchema7> = {};\n const required: string[] = [];\n const uiElements: FormSpecField[] = [];\n\n for (const field of analysis.fields) {\n // Generate JSON Schema for field\n const { jsonSchema: baseSchema } = convertType(field.type, checker);\n const fieldSchema = applyDecoratorsToSchema(baseSchema, field.decorators, field);\n properties[field.name] = fieldSchema;\n\n // Track required fields\n if (!field.optional) {\n required.push(field.name);\n }\n\n // Generate FormSpec field\n const formSpecField = createFormSpecField(\n field.name,\n field.type,\n field.decorators,\n field.optional,\n checker\n );\n uiElements.push(formSpecField);\n }\n\n // Build complete JSON Schema\n const jsonSchema: ExtendedJSONSchema7 = {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n\n // Convert FormSpecField[] to JSON Forms UISchema\n const uiSchema = generateUiSchemaFromFields(uiElements);\n\n return { jsonSchema, uiSchema };\n}\n\n/**\n * Generates JSON Schema for a single field.\n *\n * Useful for generating schemas for method return types\n * or individual field extraction.\n *\n * @param field - The field information\n * @param checker - TypeScript type checker\n * @returns JSON Schema for the field's type\n */\nexport function generateFieldSchema(\n field: FieldInfo,\n checker: ts.TypeChecker\n): ExtendedJSONSchema7 {\n const { jsonSchema: baseSchema } = convertType(field.type, checker);\n return applyDecoratorsToSchema(baseSchema, field.decorators, field);\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 for validation */\n jsonSchema: ExtendedJSONSchema7;\n /** JSON Forms UI Schema for rendering */\n uiSchema: UISchema;\n}\n\n/**\n * Generates JSON Schema and FormSpec/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,\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 FormSpec/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 = analyzeClass(classDecl, ctx.checker);\n return generateClassSchemas(analysis, ctx.checker);\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 FormSpec/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 analysis pipeline:\n *\n * - **Classes**: extracts decorators and JSDoc constraints\n * - **Interfaces**: extracts TSDoc tags (`@Field_displayName`, `@Minimum`, etc.)\n * - **Type aliases**: object literal bodies analyzed like interfaces\n *\n * @example\n * ```typescript\n * // Works with both classes and interfaces — caller doesn't need to know\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 FormSpec/UI Schema\n */\nexport function generateSchemas(options: GenerateSchemasOptions): GenerateFromClassResult {\n const ctx = createProgramContext(options.filePath);\n\n // Try class first\n const classDecl = findClassByName(ctx.sourceFile, options.typeName);\n if (classDecl) {\n const analysis = analyzeClass(classDecl, ctx.checker);\n return generateClassSchemas(analysis, ctx.checker);\n }\n\n // Try interface\n const interfaceDecl = findInterfaceByName(ctx.sourceFile, options.typeName);\n if (interfaceDecl) {\n const analysis = analyzeInterface(interfaceDecl, ctx.checker);\n return generateClassSchemas(analysis, ctx.checker);\n }\n\n // Try type alias\n const typeAlias = findTypeAliasByName(ctx.sourceFile, options.typeName);\n if (typeAlias) {\n const result = analyzeTypeAlias(typeAlias, ctx.checker);\n if (result.ok) {\n return generateClassSchemas(result.analysis, ctx.checker);\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 * Code generation for FormSpec type metadata.\n *\n * Generates a TypeScript file that patches decorated classes with\n * their extracted type metadata, enabling runtime schema generation\n * as an alternative to a TypeScript transformer.\n *\n * Usage:\n * formspec codegen ./src/forms.ts -o ./src/__formspec_types__.ts\n *\n * Then in your code:\n * import './__formspec_types__'; // Patches all decorated classes\n * import { UserFormSchema, getUserFormFormSpec } from './__formspec_types__';\n * const spec = getUserFormFormSpec();\n */\n\nimport * as ts from \"typescript\";\nimport * as path from \"node:path\";\nimport * as fs from \"node:fs\";\n\n/**\n * Type metadata format used by `@formspec/decorators`.\n *\n * Represents the runtime type information for a field that TypeScript\n * normally erases at compile time.\n */\nexport interface TypeMetadata {\n /** Base type: \"string\", \"number\", \"boolean\", \"enum\", \"array\", \"object\", \"unknown\" */\n type: string;\n /** For enum types, the possible literal values */\n values?: unknown[];\n /** For array types, metadata about the array element type */\n itemType?: TypeMetadata;\n /** For object types, metadata about each property */\n properties?: Record<string, TypeMetadata>;\n /** Whether the field accepts null */\n nullable?: boolean;\n /** Whether the field is optional (T | undefined or ?: modifier) */\n optional?: boolean;\n}\n\n/**\n * Information about a decorated class found during codegen analysis.\n *\n * Used to track which classes need type metadata patches and where\n * they are located in the source tree.\n */\nexport interface DecoratedClassInfo {\n /** Class name as it appears in the source file */\n name: string;\n /** Import path to the source file (relative to output, without extension) */\n sourcePath: string;\n /** Type metadata for all decorated properties in the class */\n typeMetadata: Record<string, TypeMetadata>;\n /** Whether the class is exported from its source file */\n isExported: boolean;\n}\n\n/**\n * Options for code generation.\n */\nexport interface CodegenOptions {\n /** Source files to analyze (glob patterns supported) */\n files: string[];\n /** Output file path */\n output: string;\n /** Base directory for relative imports */\n baseDir?: string;\n}\n\n/**\n * Finds all decorated classes in the given source files.\n */\nexport function findDecoratedClasses(files: string[], baseDir: string): DecoratedClassInfo[] {\n const program = ts.createProgram(files, {\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n // TC39 Stage 3 decorators — do not use experimentalDecorators\n strict: true,\n });\n\n const checker = program.getTypeChecker();\n const results: DecoratedClassInfo[] = [];\n\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n if (!files.some((f) => path.resolve(f) === sourceFile.fileName)) continue;\n\n ts.forEachChild(sourceFile, (node) => {\n if (ts.isClassDeclaration(node) && hasDecoratedProperties(node)) {\n const className = node.name?.text;\n if (!className) return;\n\n const typeMetadata = extractTypeMetadata(node, checker);\n const relativePath = path.relative(baseDir, sourceFile.fileName);\n const exported = isClassExported(node, sourceFile);\n\n results.push({\n name: className,\n sourcePath: relativePath.replace(/\\.tsx?$/, \"\"),\n typeMetadata,\n isExported: exported,\n });\n }\n });\n }\n\n return results;\n}\n\n/**\n * Checks if a class has any decorated properties.\n */\nfunction hasDecoratedProperties(node: ts.ClassDeclaration): boolean {\n return node.members.some((member) => {\n if (!ts.isPropertyDeclaration(member)) return false;\n const decorators = ts.getDecorators(member);\n return decorators !== undefined && decorators.length > 0;\n });\n}\n\n/**\n * Checks if a class is exported from its source file.\n *\n * A class is considered exported if:\n * 1. It has the 'export' modifier directly (export class Foo {})\n * 2. It has 'export default' modifiers (export default class Foo {})\n * 3. It's referenced in a named export declaration (export { Foo })\n */\nfunction isClassExported(classNode: ts.ClassDeclaration, sourceFile: ts.SourceFile): boolean {\n const className = classNode.name?.text;\n if (!className) return false;\n\n // Check for direct export modifier (export class Foo or export default class Foo)\n const modifiers = ts.getModifiers(classNode);\n if (modifiers) {\n const hasExport = modifiers.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword);\n if (hasExport) return true;\n }\n\n // Check for named exports (export { Foo } or export { Foo as Bar })\n for (const statement of sourceFile.statements) {\n if (ts.isExportDeclaration(statement) && statement.exportClause) {\n if (ts.isNamedExports(statement.exportClause)) {\n for (const element of statement.exportClause.elements) {\n // Check if this export refers to our class\n // element.name is the exported name, element.propertyName is the local name (if renamed)\n const localName = element.propertyName?.text ?? element.name.text;\n if (localName === className) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Extracts type metadata for all properties in a class.\n */\nfunction extractTypeMetadata(\n classNode: ts.ClassDeclaration,\n checker: ts.TypeChecker\n): Record<string, TypeMetadata> {\n const metadata: Record<string, TypeMetadata> = {};\n\n for (const member of classNode.members) {\n if (!ts.isPropertyDeclaration(member)) continue;\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Both checks needed: name can be undefined OR not an identifier\n if (!member.name || !ts.isIdentifier(member.name)) continue;\n\n const symbol = checker.getSymbolAtLocation(member.name);\n // Skip properties without symbols - they don't have resolvable types\n if (!symbol) continue;\n\n const type = checker.getTypeOfSymbolAtLocation(symbol, member);\n const fieldName = member.name.text;\n const isOptional = !!(symbol.flags & ts.SymbolFlags.Optional);\n\n const typeInfo = convertTypeToMetadata(type, checker);\n if (isOptional) {\n typeInfo.optional = true;\n }\n metadata[fieldName] = typeInfo;\n }\n\n return metadata;\n}\n\n/**\n * Converts a TypeScript type to serializable metadata.\n */\nfunction convertTypeToMetadata(\n type: ts.Type,\n checker: ts.TypeChecker,\n visited = new Set<ts.Type>()\n): TypeMetadata {\n // Cycle detection for object types only\n const isObjectType = (type.flags & ts.TypeFlags.Object) !== 0;\n if (isObjectType) {\n if (visited.has(type)) {\n return { type: \"unknown\" };\n }\n visited.add(type);\n }\n\n // Handle union types\n if (type.isUnion()) {\n const types = type.types;\n const nonNullTypes = types.filter(\n (t) => !(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))\n );\n const hasNull = types.some((t) => t.flags & ts.TypeFlags.Null);\n\n // Boolean union (true | false)\n const isBooleanUnion =\n nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts.TypeFlags.BooleanLiteral);\n\n if (isBooleanUnion) {\n const result: TypeMetadata = { type: \"boolean\" };\n if (hasNull) result.nullable = true;\n return result;\n }\n\n // String literal union = enum\n const allStringLiterals = nonNullTypes.every((t) => t.isStringLiteral());\n if (allStringLiterals && nonNullTypes.length > 0) {\n const result: TypeMetadata = {\n type: \"enum\",\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- TypeScript doesn't narrow array types from `every` predicate\n values: nonNullTypes.map((t) => (t as ts.StringLiteralType).value),\n };\n if (hasNull) result.nullable = true;\n return result;\n }\n\n // Number literal union = enum\n const allNumberLiterals = nonNullTypes.every((t) => t.isNumberLiteral());\n if (allNumberLiterals && nonNullTypes.length > 0) {\n const result: TypeMetadata = {\n type: \"enum\",\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- TypeScript doesn't narrow array types from `every` predicate\n values: nonNullTypes.map((t) => (t as ts.NumberLiteralType).value),\n };\n if (hasNull) result.nullable = true;\n return result;\n }\n\n // Nullable single type\n // Explicit undefined check needed for array element access\n if (nonNullTypes.length === 1) {\n const singleType = nonNullTypes[0];\n if (!singleType) return { type: \"unknown\" };\n const result = convertTypeToMetadata(singleType, checker, visited);\n if (hasNull) result.nullable = true;\n return result;\n }\n\n return { type: \"unknown\" };\n }\n\n // Primitives\n if (type.flags & ts.TypeFlags.String) return { type: \"string\" };\n if (type.flags & ts.TypeFlags.Number) return { type: \"number\" };\n if (type.flags & ts.TypeFlags.Boolean) return { type: \"boolean\" };\n\n // String literal\n if (type.isStringLiteral()) {\n return { type: \"enum\", values: [type.value] };\n }\n\n // Number literal\n if (type.isNumberLiteral()) {\n return { type: \"enum\", values: [type.value] };\n }\n\n // Arrays\n if (checker.isArrayType(type)) {\n const typeArgs = (type as ts.TypeReference).typeArguments;\n return {\n type: \"array\",\n itemType: typeArgs?.[0]\n ? convertTypeToMetadata(typeArgs[0], checker, visited)\n : { type: \"unknown\" },\n };\n }\n\n // Objects\n if (type.flags & ts.TypeFlags.Object) {\n const properties: Record<string, TypeMetadata> = {};\n for (const prop of type.getProperties()) {\n // Skip properties without declarations - undefined check needed because declarations array can be empty\n const declaration = prop.valueDeclaration ?? prop.declarations?.[0];\n if (!declaration) continue;\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);\n const propOptional = !!(prop.flags & ts.SymbolFlags.Optional);\n const propMeta = convertTypeToMetadata(propType, checker, visited);\n if (propOptional) propMeta.optional = true;\n properties[prop.name] = propMeta;\n }\n\n if (Object.keys(properties).length > 0) {\n return { type: \"object\", properties };\n }\n return { type: \"object\" };\n }\n\n return { type: \"unknown\" };\n}\n\n/**\n * Generates the codegen output file content.\n */\nexport function generateCodegenOutput(\n classes: DecoratedClassInfo[],\n outputPath: string,\n baseDir: string\n): string {\n const outputDir = path.dirname(path.resolve(outputPath));\n const lines: string[] = [\n \"/**\",\n \" * Auto-generated by FormSpec CLI.\",\n \" * DO NOT EDIT - changes will be overwritten.\",\n \" *\",\n \" * This file provides:\",\n \" * - Type metadata patches for runtime schema generation\",\n \" * - Inferred schema types (e.g., UserFormSchema)\",\n \" * - Type-safe FormSpec accessors (e.g., getUserFormFormSpec())\",\n \" *\",\n \" * Usage:\",\n \" * import { UserFormSchema, getUserFormFormSpec } from './__formspec_types__';\",\n \" *\",\n \" * const data: UserFormSchema = { name: 'Alice', country: 'us' };\",\n \" * const spec = getUserFormFormSpec();\",\n \" */\",\n \"\",\n \"/* eslint-disable @typescript-eslint/no-explicit-any */\",\n \"\",\n ];\n\n // Generate imports\n for (const cls of classes) {\n // Compute absolute source path, then relative from output dir\n const absoluteSourcePath = path.resolve(baseDir, cls.sourcePath);\n const importPath = getRelativeImportPath(outputDir, absoluteSourcePath);\n lines.push(`import { ${cls.name} } from \"${importPath}\";`);\n }\n\n lines.push(\"\");\n lines.push(\"// =============================================================================\");\n lines.push(\"// Type Metadata Patches\");\n lines.push(\"// =============================================================================\");\n lines.push(\"\");\n\n // Generate patches\n for (const cls of classes) {\n const metadataJson = JSON.stringify(cls.typeMetadata, null, 2)\n .split(\"\\n\")\n .map((line, i) => (i === 0 ? line : \" \" + line))\n .join(\"\\n\");\n\n lines.push(`(${cls.name} as any).__formspec_types__ = ${metadataJson};`);\n lines.push(\"\");\n }\n\n lines.push(\"// =============================================================================\");\n lines.push(\"// Inferred Schema Types\");\n lines.push(\"// =============================================================================\");\n lines.push(\"\");\n\n // Generate schema types\n for (const cls of classes) {\n lines.push(generateSchemaType(cls));\n lines.push(\"\");\n }\n\n lines.push(\"// =============================================================================\");\n lines.push(\"// Type-Safe FormSpec Accessors\");\n lines.push(\"// =============================================================================\");\n lines.push(\"\");\n\n // Generate typed accessors\n for (const cls of classes) {\n lines.push(generateTypedAccessor(cls));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Converts TypeMetadata to a TypeScript type string.\n */\nfunction metadataToTypeString(metadata: TypeMetadata): string {\n const baseType = metadataToBaseTypeString(metadata);\n\n // Handle nullable and optional modifiers\n if (metadata.nullable && metadata.optional) {\n return `${baseType} | null | undefined`;\n }\n if (metadata.nullable) {\n return `${baseType} | null`;\n }\n if (metadata.optional) {\n return `${baseType} | undefined`;\n }\n return baseType;\n}\n\n/**\n * Checks if a property key needs to be quoted in TypeScript object types.\n *\n * Property keys need quoting if they:\n * - Contain characters invalid in JavaScript identifiers (spaces, hyphens, etc.)\n * - Are reserved JavaScript/TypeScript keywords (class, function, etc.)\n *\n * @param key - The property name to check\n * @returns true if the key requires quotes, false otherwise\n */\n// Valid JS identifier: starts with letter/underscore/$, followed by alphanumeric/_/$\nconst VALID_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;\n\n// Reserved words that need quoting (comprehensive list including ES6+)\nconst RESERVED_WORDS = new Set([\n // Keywords\n \"break\",\n \"case\",\n \"catch\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"in\",\n \"instanceof\",\n \"new\",\n \"return\",\n \"switch\",\n \"this\",\n \"throw\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"class\",\n \"const\",\n \"enum\",\n \"export\",\n \"extends\",\n \"import\",\n \"super\",\n \"implements\",\n \"interface\",\n \"let\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"static\",\n \"yield\",\n // ES6+ keywords\n \"async\",\n \"await\",\n // Literal values (not technically keywords but best to quote)\n \"null\",\n \"true\",\n \"false\",\n // Accessor keywords\n \"get\",\n \"set\",\n // Strict mode reserved\n \"arguments\",\n \"eval\",\n]);\n\nfunction needsPropertyQuoting(key: string): boolean {\n if (!VALID_IDENTIFIER.test(key)) {\n return true;\n }\n return RESERVED_WORDS.has(key);\n}\n\n/**\n * Escapes a property key for safe use in TypeScript type definitions.\n *\n * Wraps keys in double quotes if they need quoting, using JSON.stringify\n * for robust escaping of special characters.\n *\n * @param key - The property name to escape\n * @returns The escaped key, quoted if necessary\n */\nfunction escapePropertyKey(key: string): string {\n if (needsPropertyQuoting(key)) {\n return JSON.stringify(key);\n }\n return key;\n}\n\n/**\n * Converts TypeMetadata to base type string (without null/optional modifiers).\n */\nfunction metadataToBaseTypeString(metadata: TypeMetadata): string {\n switch (metadata.type) {\n case \"string\":\n return \"string\";\n case \"number\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"enum\":\n if (metadata.values && metadata.values.length > 0) {\n return metadata.values\n .map((v) => (typeof v === \"string\" ? JSON.stringify(v) : String(v)))\n .join(\" | \");\n }\n return \"string\";\n case \"array\":\n if (metadata.itemType) {\n const itemType = metadataToTypeString(metadata.itemType);\n // Wrap union types in parentheses for array\n if (itemType.includes(\"|\")) {\n return `(${itemType})[]`;\n }\n return `${itemType}[]`;\n }\n return \"unknown[]\";\n case \"object\":\n if (metadata.properties && Object.keys(metadata.properties).length > 0) {\n const props = Object.entries(metadata.properties)\n .map(([key, propMeta]) => {\n const optional = propMeta.optional ? \"?\" : \"\";\n return `${escapePropertyKey(key)}${optional}: ${metadataToTypeString(propMeta)}`;\n })\n .join(\"; \");\n return `{ ${props} }`;\n }\n return \"Record<string, unknown>\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Generates a TypeScript schema type for a class.\n */\nfunction generateSchemaType(cls: DecoratedClassInfo): string {\n const props = Object.entries(cls.typeMetadata)\n .map(([fieldName, metadata]) => {\n const optional = metadata.optional ? \"?\" : \"\";\n const typeStr = metadataToTypeString(metadata);\n return ` ${escapePropertyKey(fieldName)}${optional}: ${typeStr};`;\n })\n .join(\"\\n\");\n\n return `export type ${cls.name}Schema = {\\n${props}\\n};`;\n}\n\n/**\n * Maps TypeMetadata type strings to FormSpec field type strings.\n *\n * TypeMetadata uses generic type names (string, number), while FormSpec\n * uses more specific field type names (text, number, enum).\n *\n * @param type - The TypeMetadata type string\n * @returns The corresponding FormSpec field type\n */\nfunction metadataTypeToFieldType(type: string): string {\n switch (type) {\n case \"string\":\n return \"text\";\n case \"number\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"enum\":\n return \"enum\";\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n default:\n return \"text\";\n }\n}\n\n/**\n * Generates typed FormSpec accessor for a class.\n *\n * Creates three exports:\n * 1. Element tuple type (e.g., UserFormElements) - Exact readonly array type\n * representing each field with its literal types preserved\n * 2. FormSpec result type (e.g., UserFormFormSpec) - Type alias wrapping the elements\n * 3. Accessor function (e.g., getUserFormFormSpec()) - Returns FormSpec with full\n * type information for autocomplete and type checking\n *\n * These types enable the same level of type inference as the Chain DSL.\n *\n * @param cls - The decorated class information\n * @returns TypeScript code defining the accessor function and types\n */\nfunction generateTypedAccessor(cls: DecoratedClassInfo): string {\n const lines: string[] = [];\n\n // Generate the element type as a tuple\n const elementTypes = Object.entries(cls.typeMetadata).map(([fieldName, metadata]) => {\n const fieldType = metadataTypeToFieldType(metadata.type);\n const required = !metadata.optional;\n\n let elementType = `{ readonly _field: \"${fieldType}\"; readonly id: \"${fieldName}\"; readonly required: ${String(required)}`;\n\n // Add options for enum types\n if (metadata.type === \"enum\" && metadata.values) {\n const optionValues = metadata.values\n .map((v) => (typeof v === \"string\" ? JSON.stringify(v) : String(v)))\n .join(\", \");\n elementType += `; readonly options: readonly [${optionValues}]`;\n }\n\n elementType += \" }\";\n return elementType;\n });\n\n // Export element tuple type\n lines.push(`export type ${cls.name}Elements = readonly [\\n ${elementTypes.join(\",\\n \")}\\n];`);\n lines.push(\"\");\n\n // Export typed FormSpec result type\n lines.push(`export type ${cls.name}FormSpec = { readonly elements: ${cls.name}Elements };`);\n lines.push(\"\");\n\n // Export typed accessor function\n lines.push(`/**`);\n lines.push(` * Type-safe FormSpec accessor for ${cls.name}.`);\n lines.push(` * Reads the patched type metadata from the class.`);\n lines.push(` */`);\n lines.push(`export function get${cls.name}FormSpec(): ${cls.name}FormSpec {`);\n lines.push(\n ` const types = (${cls.name} as any).__formspec_types__ as Record<string, unknown>[];`\n );\n lines.push(` return { elements: types } as unknown as ${cls.name}FormSpec;`);\n lines.push(`}`);\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Gets a relative import path from output to source.\n */\nfunction getRelativeImportPath(outputDir: string, sourcePath: string): string {\n // sourcePath is already relative to baseDir\n let relativePath = path.relative(outputDir, sourcePath);\n\n // Ensure it starts with ./ or ../\n if (!relativePath.startsWith(\".\")) {\n relativePath = \"./\" + relativePath;\n }\n\n // Use forward slashes for imports\n relativePath = relativePath.replace(/\\\\/g, \"/\");\n\n // Add .js extension for ESM compatibility\n return relativePath + \".js\";\n}\n\n/**\n * Runs the code generation.\n */\nexport function runCodegen(options: CodegenOptions): void {\n const baseDir = options.baseDir ?? path.dirname(options.output);\n const absoluteFiles = options.files.map((f) => path.resolve(f));\n\n console.log(`Scanning ${String(absoluteFiles.length)} file(s) for decorated classes...`);\n\n const classes = findDecoratedClasses(absoluteFiles, baseDir);\n\n if (classes.length === 0) {\n console.log(\"No decorated classes found.\");\n return;\n }\n\n console.log(`Found ${String(classes.length)} decorated class(es):`);\n for (const cls of classes) {\n const fieldCount = Object.keys(cls.typeMetadata).length;\n console.log(` - ${cls.name} (${String(fieldCount)} field(s))`);\n }\n\n // Check for unexported classes and warn\n const unexported = classes.filter((cls) => !cls.isExported);\n if (unexported.length > 0) {\n console.warn(\n `\\n⚠️ Warning: The following decorated classes are not exported from their source files:`\n );\n for (const cls of unexported) {\n console.warn(` - ${cls.name} (${cls.sourcePath})`);\n }\n console.warn(\n `\\n The generated code will fail to compile because it cannot import these classes.`\n );\n console.warn(` To fix this, add 'export' to the class declaration, for example:`);\n console.warn(` export class YourClassName { ... }\\n`);\n }\n\n const output = generateCodegenOutput(classes, options.output, baseDir);\n\n // Ensure output directory exists\n const outputDir = path.dirname(options.output);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(options.output, output);\n console.log(`\\nGenerated: ${options.output}`);\n}\n","/**\n * `@formspec/build` - Build tools for FormSpec\n *\n * This package provides generators to compile FormSpec forms into:\n * - JSON Schema (for validation)\n * - JSON Forms UI Schema (for rendering)\n *\n * @example\n * ```typescript\n * import { buildFormSchemas } from \"@formspec/build\";\n * import { formspec, field, group } from \"@formspec/dsl\";\n *\n * const form = formspec(\n * group(\"Customer\",\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.text(\"email\", { label: \"Email\" }),\n * ),\n * );\n *\n * const { jsonSchema, uiSchema } = buildFormSchemas(form);\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { FormElement, FormSpec } from \"@formspec/core\";\nimport { generateJsonSchema } from \"./json-schema/generator.js\";\nimport { generateUiSchema } from \"./ui-schema/generator.js\";\nimport type { JSONSchema7 } from \"./json-schema/types.js\";\nimport type { UISchema } from \"./ui-schema/types.js\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// =============================================================================\n// Type Exports\n// =============================================================================\n\nexport type {\n JSONSchema7,\n JSONSchemaType,\n ExtendedJSONSchema7,\n FormSpecSchemaExtensions,\n} from \"./json-schema/types.js\";\n\nexport { setSchemaExtension, getSchemaExtension } from \"./json-schema/types.js\";\n\nexport type {\n UISchema,\n UISchemaElement,\n UISchemaElementBase,\n UISchemaElementType,\n ControlElement,\n VerticalLayout,\n HorizontalLayout,\n GroupLayout,\n Categorization,\n Category,\n LabelElement,\n Rule,\n RuleEffect,\n RuleConditionSchema,\n SchemaBasedCondition,\n} from \"./ui-schema/types.js\";\n\nexport type { FormSpecField } from \"./analyzer/type-converter.js\";\n\nexport type {\n ClassSchemas,\n GenerateFromClassOptions,\n GenerateFromClassResult,\n GenerateSchemasOptions,\n} from \"./generators/class-schema.js\";\n\nexport type { TypeMetadata, DecoratedClassInfo, CodegenOptions } from \"./codegen/index.js\";\n\n// =============================================================================\n// Zod Validation Schemas\n// =============================================================================\n\nexport {\n ruleEffectSchema,\n uiSchemaElementTypeSchema,\n ruleConditionSchema,\n schemaBasedConditionSchema,\n ruleSchema,\n controlSchema,\n verticalLayoutSchema,\n horizontalLayoutSchema,\n groupLayoutSchema,\n categorizationSchema,\n categorySchema,\n labelElementSchema,\n uiSchemaElementSchema,\n uiSchema as uiSchemaSchema,\n} from \"./ui-schema/schema.js\";\n\nexport { jsonSchemaTypeSchema, jsonSchema7Schema } from \"./json-schema/schema.js\";\n\n// =============================================================================\n// Chain DSL Generators\n// =============================================================================\n\nexport { generateJsonSchema } from \"./json-schema/generator.js\";\nexport { generateUiSchema, generateUiSchemaFromFields } from \"./ui-schema/generator.js\";\n\n// =============================================================================\n// Decorator DSL: High-Level Entry Points\n// =============================================================================\n\nexport { generateSchemasFromClass, generateSchemas } from \"./generators/class-schema.js\";\n\n// generateSchemas is the recommended entry point — it auto-detects class/interface/type alias.\n// generateSchemasFromClass is retained for backwards compatibility.\n\nexport { findDecoratedClasses, generateCodegenOutput, runCodegen } from \"./codegen/index.js\";\n\n/**\n * Result of building form schemas.\n */\nexport interface BuildResult {\n /** JSON Schema for validation */\n readonly jsonSchema: JSONSchema7;\n /** JSON Forms UI Schema for rendering */\n readonly uiSchema: UISchema;\n}\n\n/**\n * Builds both JSON Schema and UI Schema from a FormSpec.\n *\n * This is a convenience function that combines `generateJsonSchema`\n * and `generateUiSchema`.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * field.text(\"name\", { required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n *\n * const { jsonSchema, uiSchema } = buildFormSchemas(form);\n *\n * // Use with JSON Forms renderer\n * <JsonForms\n * schema={jsonSchema}\n * uischema={uiSchema}\n * data={formData}\n * renderers={materialRenderers}\n * />\n * ```\n *\n * @param form - The FormSpec to build schemas from\n * @returns Object containing both jsonSchema and uiSchema\n */\nexport function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>): BuildResult {\n return {\n jsonSchema: generateJsonSchema(form),\n uiSchema: generateUiSchema(form),\n };\n}\n\n/**\n * Options for writing schemas to disk.\n */\nexport interface WriteSchemasOptions {\n /** Output directory for the schema files */\n readonly outDir: string;\n /** Base name for the output files (without extension). Defaults to \"schema\" */\n readonly name?: string;\n /** Number of spaces for JSON indentation. Defaults to 2 */\n readonly indent?: number;\n}\n\n/**\n * Result of writing schemas to disk.\n */\nexport interface WriteSchemasResult {\n /** Path to the generated JSON Schema file */\n readonly jsonSchemaPath: string;\n /** Path to the generated UI Schema file */\n readonly uiSchemaPath: string;\n}\n\n/**\n * Builds and writes both JSON Schema and UI Schema files to disk.\n *\n * This is a convenience function for build-time schema generation.\n * It creates the output directory if it doesn't exist.\n *\n * @example\n * ```typescript\n * import { formspec, field } from \"formspec\";\n * import { writeSchemas } from \"@formspec/build\";\n *\n * const ProductForm = formspec(\n * field.text(\"name\", { required: true }),\n * field.enum(\"status\", [\"draft\", \"active\"]),\n * );\n *\n * // Write schemas to ./generated/product-schema.json and ./generated/product-uischema.json\n * const { jsonSchemaPath, uiSchemaPath } = writeSchemas(ProductForm, {\n * outDir: \"./generated\",\n * name: \"product\",\n * });\n *\n * console.log(`Generated: ${jsonSchemaPath}, ${uiSchemaPath}`);\n * ```\n *\n * @param form - The FormSpec to build schemas from\n * @param options - Output options (directory, file name, indentation)\n * @returns Object containing paths to the generated files\n */\nexport function writeSchemas<E extends readonly FormElement[]>(\n form: FormSpec<E>,\n options: WriteSchemasOptions\n): WriteSchemasResult {\n const { outDir, name = \"schema\", indent = 2 } = options;\n\n // Build schemas\n const { jsonSchema, uiSchema } = buildFormSchemas(form);\n\n // Ensure output directory exists\n if (!fs.existsSync(outDir)) {\n fs.mkdirSync(outDir, { recursive: true });\n }\n\n // Write files\n const jsonSchemaPath = path.join(outDir, `${name}-schema.json`);\n const uiSchemaPath = path.join(outDir, `${name}-uischema.json`);\n\n fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));\n fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema, null, indent));\n\n return { jsonSchemaPath, uiSchemaPath };\n}\n","#!/usr/bin/env node\n/**\n * FormSpec CLI - Generate JSON Schema and UI Schema from form definitions\n *\n * Usage:\n * formspec-build <input-file> [options]\n *\n * Options:\n * -o, --out-dir <dir> Output directory (default: ./generated)\n * -n, --name <name> Base name for output files (default: derived from input)\n * -h, --help Show help\n *\n * Example:\n * formspec-build src/forms/product.ts -o ./schemas -n product\n */\n\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\ninterface CliOptions {\n inputFile: string;\n outDir: string;\n name: string;\n}\n\nfunction printHelp(): void {\n console.log(`\nFormSpec Build CLI - Generate JSON Schema and UI Schema\n\nUsage:\n formspec-build <input-file> [options]\n\nOptions:\n -o, --out-dir <dir> Output directory (default: ./generated)\n -n, --name <name> Base name for output files (default: derived from input)\n -h, --help Show this help message\n\nExample:\n formspec-build src/forms/product.ts -o ./schemas -n product\n\nThe input file should export a FormSpec as its default export or as 'form':\n // product-form.ts\n import { formspec, field } from \"formspec\";\n export default formspec(field.text(\"name\"));\n // or: export const form = formspec(field.text(\"name\"));\n`);\n}\n\nfunction parseArgs(args: string[]): CliOptions | null {\n const positional: string[] = [];\n let outDir = \"./generated\";\n let name = \"\";\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n\n if (arg === \"-h\" || arg === \"--help\") {\n printHelp();\n process.exit(0);\n }\n\n if (arg === \"-o\" || arg === \"--out-dir\") {\n const nextArg = args[i + 1];\n if (!nextArg) {\n console.error(\"Error: --out-dir requires a value\");\n return null;\n }\n outDir = nextArg;\n i++;\n continue;\n }\n\n if (arg === \"-n\" || arg === \"--name\") {\n const nextArg = args[i + 1];\n if (!nextArg) {\n console.error(\"Error: --name requires a value\");\n return null;\n }\n name = nextArg;\n i++;\n continue;\n }\n\n if (arg.startsWith(\"-\")) {\n console.error(`Error: Unknown option: ${arg}`);\n return null;\n }\n\n positional.push(arg);\n }\n\n if (positional.length === 0) {\n console.error(\"Error: No input file specified\");\n printHelp();\n return null;\n }\n\n const inputFile = positional[0];\n if (!inputFile) {\n console.error(\"Error: No input file specified\");\n return null;\n }\n\n // Default name from input file\n if (!name) {\n name = path.basename(inputFile, path.extname(inputFile));\n }\n\n return { inputFile, outDir, name };\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const options = parseArgs(args);\n\n if (!options) {\n process.exit(1);\n }\n\n const { inputFile, outDir, name } = options;\n\n // Resolve input file path\n const absoluteInput = path.resolve(process.cwd(), inputFile);\n\n try {\n // Dynamically import the input file\n // Use file URL for cross-platform compatibility (Windows paths need file:// URLs)\n const fileUrl = pathToFileURL(absoluteInput).href;\n const module = (await import(fileUrl)) as Record<string, unknown>;\n\n // Look for the form export\n const form = module[\"default\"] ?? module[\"form\"];\n\n if (!form || typeof form !== \"object\" || !(\"elements\" in form)) {\n console.error(\"Error: Input file must export a FormSpec as default export or as 'form'\");\n console.error(\"Example:\");\n console.error(' export default formspec(field.text(\"name\"));');\n console.error(\" // or\");\n console.error(' export const form = formspec(field.text(\"name\"));');\n process.exit(1);\n }\n\n // Import writeSchemas dynamically to avoid circular deps\n const { writeSchemas } = await import(\"./index.js\");\n\n const { jsonSchemaPath, uiSchemaPath } = writeSchemas(\n form as Parameters<typeof writeSchemas>[0],\n { outDir, name }\n );\n\n console.log(\"Generated:\");\n console.log(` ${jsonSchemaPath}`);\n console.log(` ${uiSchemaPath}`);\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n } else {\n console.error(\"Error:\", error);\n }\n process.exit(1);\n }\n}\n\nvoid main();\n"],"mappings":"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","names":["z","z","init_schema","z","parseOrThrow","init_generator","init_schema","ts","ts","ts","ts","uiSchema","init_generator","ts","path","fs","path","uiSchema","init_generator","init_schema","path","writeSchemas"]}
1
+ {"version":3,"sources":["../src/canonicalize/chain-dsl-canonicalizer.ts","../src/canonicalize/tsdoc-canonicalizer.ts","../src/canonicalize/index.ts","../src/json-schema/ir-generator.ts","../src/json-schema/generator.ts","../src/ui-schema/schema.ts","../src/ui-schema/ir-generator.ts","../src/ui-schema/generator.ts","../src/json-schema/types.ts","../src/json-schema/schema.ts","../src/analyzer/program.ts","../src/analyzer/tsdoc-parser.ts","../src/analyzer/jsdoc-constraints.ts","../src/analyzer/class-analyzer.ts","../src/generators/class-schema.ts","../src/index.ts","../src/cli.ts"],"sourcesContent":["/**\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: false,\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: false,\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 * decorators.\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` decorators are grouped into `GroupLayoutNode` elements.\n * Fields with `@ShowWhen` decorators 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 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 * Canonicalization layer — converts authoring surface output to canonical IR.\n *\n * @packageDocumentation\n */\n\nexport { canonicalizeChainDSL } from \"./chain-dsl-canonicalizer.js\";\nexport { canonicalizeTSDoc, type TSDocSource } from \"./tsdoc-canonicalizer.js\";\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 UnionTypeNode,\n ReferenceTypeNode,\n DynamicTypeNode,\n CustomTypeNode,\n ConstraintNode,\n AnnotationNode,\n ObjectProperty,\n} from \"@formspec/core\";\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;\n enum?: readonly (string | number)[];\n const?: string | number | boolean | null;\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 // 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}\n\nfunction makeContext(): GeneratorContext {\n return { defs: {} };\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 * @param ir - The canonical FormIR produced by a canonicalizer\n * @returns A plain JSON-serializable JSON Schema 2020-12 object\n */\nexport function generateJsonSchemaFromIR(ir: FormIR): JsonSchema2020 {\n const ctx = makeContext();\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 }\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 (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\n // Apply constraints. multipleOf:1 on a number type is a special case: it\n // promotes the type to \"integer\" and removes the multipleOf keyword.\n applyConstraints(schema, field.constraints);\n\n // Apply annotations (title, description, default, deprecated, etc.).\n applyAnnotations(schema, field.annotations);\n\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 \"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);\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 only emitted when the IR explicitly disallows extra\n * properties. The default per the JSON Schema vocabulary spec §2.5 is to omit it (allow policy).\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 // IR default is false (closed objects). Emit explicitly when disallowed.\n schema.additionalProperties = false;\n }\n\n return schema;\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);\n applyAnnotations(schema, prop.annotations);\n return schema;\n}\n\n/**\n * Generates JSON Schema for a union type.\n *\n * Union handling strategy:\n * - Boolean shorthand: `true | false` → `{ type: \"boolean\" }` (not anyOf)\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 // Default: anyOf for all non-boolean unions.\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 * 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 * CustomTypeNode is a placeholder for Phase 8 extensions.\n * Emits a minimal passthrough object type until the extension API is implemented.\n */\nfunction generateCustomType(_type: CustomTypeNode): JsonSchema2020 {\n return { type: \"object\" };\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 (e.g., `@minimum :value 0`) are emitted at the field\n * level here; full sub-field targeting via allOf composition is a Phase 4 concern.\n */\nfunction applyConstraints(schema: JsonSchema2020, constraints: readonly ConstraintNode[]): 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 \"allowedMembers\":\n // EnumMemberConstraintNode — not yet emitted to JSON Schema (Phase 6 validation).\n break;\n\n case \"custom\":\n // CustomConstraintNode — handled by Phase 8 extensions.\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 *\n * UI-only annotations (`placeholder`, `formatHint`) are silently ignored here —\n * they belong in the UI Schema, not the data schema.\n */\nfunction applyAnnotations(schema: JsonSchema2020, annotations: readonly AnnotationNode[]): 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 \"deprecated\":\n schema.deprecated = true;\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 // CustomAnnotationNode — handled by Phase 8 extensions.\n break;\n\n default: {\n // TypeScript exhaustiveness guard.\n const _exhaustive: never = annotation;\n void _exhaustive;\n }\n }\n }\n}\n","/**\n * JSON Schema generator for FormSpec forms.\n *\n * Routes through the canonical IR pipeline: Chain DSL → FormIR → JSON Schema 2020-12.\n */\n\nimport type { FormElement, FormSpec } from \"@formspec/core\";\nimport { canonicalizeChainDSL } from \"../canonicalize/index.js\";\nimport { generateJsonSchemaFromIR, type JsonSchema2020 } from \"./ir-generator.js\";\n\n/**\n * Generates a JSON Schema 2020-12 from a FormSpec.\n *\n * All generation routes through the canonical IR. The chain DSL is first\n * canonicalized to a FormIR, then the IR-based generator produces the schema.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n *\n * const schema = generateJsonSchema(form);\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 * @param form - The FormSpec to convert\n * @returns A JSON Schema 2020-12 object\n */\nexport function generateJsonSchema<E extends readonly FormElement[]>(\n form: FormSpec<E>\n): JsonSchema2020 {\n const ir = canonicalizeChainDSL(form);\n return generateJsonSchemaFromIR(ir);\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 { UISchema, UISchemaElement, ControlElement, GroupLayout, Rule } 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 merges the two\n * conditions into a single rule using allOf so that JSON Forms evaluates\n * both predicates simultaneously.\n */\nfunction combineRules(parentRule: Rule, childRule: Rule): Rule {\n const parentCondition = parentRule.condition;\n const childCondition = childRule.condition;\n\n return {\n effect: \"SHOW\",\n condition: {\n scope: \"#\",\n schema: {\n allOf: [\n {\n properties: {\n [parentCondition.scope.replace(\"#/properties/\", \"\")]: parentCondition.schema,\n },\n },\n {\n properties: {\n [childCondition.scope.replace(\"#/properties/\", \"\")]: childCondition.schema,\n },\n },\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\n const control: ControlElement = {\n type: \"Control\",\n scope: fieldToScope(field.name),\n ...(displayNameAnnotation !== undefined && { label: displayNameAnnotation.value }),\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 * JSON Forms UI Schema generator for FormSpec forms.\n *\n * Routes through the canonical IR pipeline: Chain DSL → FormIR → UI Schema.\n */\n\nimport type { FormElement, FormSpec } from \"@formspec/core\";\nimport { canonicalizeChainDSL } from \"../canonicalize/index.js\";\nimport { generateUiSchemaFromIR } from \"./ir-generator.js\";\nimport type { UISchema } from \"./types.js\";\n\n/**\n * Generates a JSON Forms UI Schema from a FormSpec.\n *\n * All generation routes through the canonical IR. The chain DSL is first\n * canonicalized to a FormIR, then the IR-based generator produces the schema.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * group(\"Customer\",\n * field.text(\"name\", { label: \"Name\" }),\n * ),\n * when(\"status\", \"draft\",\n * field.text(\"notes\", { label: \"Notes\" }),\n * ),\n * );\n *\n * const uiSchema = generateUiSchema(form);\n * // {\n * // type: \"VerticalLayout\",\n * // elements: [\n * // {\n * // type: \"Group\",\n * // label: \"Customer\",\n * // elements: [\n * // { type: \"Control\", scope: \"#/properties/name\", label: \"Name\" }\n * // ]\n * // },\n * // {\n * // type: \"Control\",\n * // scope: \"#/properties/notes\",\n * // label: \"Notes\",\n * // rule: {\n * // effect: \"SHOW\",\n * // condition: { scope: \"#/properties/status\", schema: { const: \"draft\" } }\n * // }\n * // }\n * // ]\n * // }\n * ```\n *\n * @param form - The FormSpec to convert\n * @returns A JSON Forms UI Schema\n */\nexport function generateUiSchema<E extends readonly FormElement[]>(form: FormSpec<E>): UISchema {\n const ir = canonicalizeChainDSL(form);\n return generateUiSchemaFromIR(ir);\n}\n","/**\n * JSON Schema type definitions.\n *\n * These types are a subset of JSON Schema sufficient for form generation.\n */\n\n/**\n * JSON Schema primitive types.\n */\nexport type JSONSchemaType =\n | \"string\"\n | \"number\"\n | \"integer\"\n | \"boolean\"\n | \"object\"\n | \"array\"\n | \"null\";\n\n/**\n * A JSON Schema definition (legacy subset used by Zod validator and types.ts).\n */\nexport interface JSONSchema7 {\n $schema?: string;\n $id?: string;\n $ref?: string;\n\n // Metadata\n title?: string;\n description?: string;\n deprecated?: boolean;\n\n // Type\n type?: JSONSchemaType | JSONSchemaType[];\n\n // String validation\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n\n // Number validation\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n\n // Enum\n enum?: readonly (string | number | boolean | null)[];\n const?: string | number | boolean | null;\n\n // Object\n properties?: Record<string, JSONSchema7>;\n required?: string[];\n additionalProperties?: boolean | JSONSchema7;\n\n // Array\n items?: JSONSchema7 | JSONSchema7[];\n minItems?: number;\n maxItems?: number;\n\n // Composition\n allOf?: JSONSchema7[];\n anyOf?: JSONSchema7[];\n oneOf?: JSONSchema7[];\n not?: JSONSchema7;\n\n // Conditional\n if?: JSONSchema7;\n then?: JSONSchema7;\n else?: JSONSchema7;\n\n // Format\n format?: string;\n\n // Default\n default?: unknown;\n\n // =============================================================================\n // FormSpec Extensions (x- prefixed)\n // =============================================================================\n\n /**\n * Data source key for dynamic enum fields.\n * Indicates that options should be fetched from a registered resolver.\n */\n \"x-formspec-source\"?: string;\n\n /**\n * Field names whose values are needed to fetch dynamic enum options.\n * Used for dependent/cascading dropdowns.\n */\n \"x-formspec-params\"?: readonly string[];\n\n /**\n * Schema source identifier for dynamic schema fields.\n * Indicates that the schema should be loaded dynamically at runtime.\n */\n \"x-formspec-schemaSource\"?: string;\n}\n\n/** Extension properties for custom FormSpec decorators. */\nexport type FormSpecSchemaExtensions = Record<`x-formspec-${string}`, unknown>;\n\n/** JSON Schema with FormSpec extension properties for arbitrary x-formspec-* keys. */\nexport type ExtendedJSONSchema7 = JSONSchema7 & FormSpecSchemaExtensions;\n\n/**\n * Sets a FormSpec extension property on a JSON Schema node.\n *\n * Use this to safely add `x-formspec-*` properties to any schema,\n * including nested schemas typed as `JSONSchema7` (which don't carry\n * the extension index signature).\n *\n * @param schema - Any JSON Schema node\n * @param key - Extension key (must start with `x-formspec-`)\n * @param value - Extension value\n */\nexport function setSchemaExtension(\n schema: object,\n key: `x-formspec-${string}`,\n value: unknown\n): void {\n (schema as Record<string, unknown>)[key] = value;\n}\n\n/**\n * Reads a FormSpec extension property from a JSON Schema node.\n *\n * Accepts any schema object — `JSONSchema7`, `JsonSchema2020`, `ExtendedJSONSchema7`, etc.\n *\n * @param schema - Any JSON Schema node\n * @param key - Extension key (must start with `x-formspec-`)\n * @returns The extension value, or `undefined` if not present\n */\nexport function getSchemaExtension(schema: object, key: `x-formspec-${string}`): unknown {\n return (schema as Record<string, unknown>)[key];\n}\n","/**\n * Zod schemas for JSON Schema output validation.\n *\n * These schemas cover the subset of JSON Schema that FormSpec generates,\n * plus the FormSpec-specific `x-formspec-*` extension properties.\n *\n * @see https://json-schema.org/draft/2020-12/schema\n */\n\nimport { z } from \"zod\";\nimport type { JSONSchema7 } from \"./types.js\";\n\n// =============================================================================\n// JSON Schema type enum\n// =============================================================================\n\n/**\n * Zod schema for JSON Schema primitive type strings.\n */\nexport const jsonSchemaTypeSchema = z.enum([\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"object\",\n \"array\",\n \"null\",\n]);\n\n// =============================================================================\n// JSON Schema validator schema (recursive)\n// =============================================================================\n\n// We annotate with z.ZodType<JSONSchema7> for the recursive self-reference.\n// The @ts-expect-error is required because exactOptionalPropertyTypes:true causes\n// Zod's inferred output type for optional fields (`T | undefined`) to be\n// incompatible with the JSONSchema7 interface's exact optional fields (`T?`).\n// The runtime behavior is correct: z.optional() will strip `undefined` values\n// during parsing and correctly handle absent keys.\n//\n// @ts-expect-error -- exactOptionalPropertyTypes: Zod optional infers `T | undefined`\n// but JSONSchema7 uses exact optional `?:` which disallows explicit undefined.\nexport const jsonSchema7Schema: z.ZodType<JSONSchema7> = z.lazy(() =>\n z\n .object({\n $schema: z.string().optional(),\n $id: z.string().optional(),\n $ref: z.string().optional(),\n\n // Metadata\n title: z.string().optional(),\n description: z.string().optional(),\n deprecated: z.boolean().optional(),\n\n // Type\n type: z.union([jsonSchemaTypeSchema, z.array(jsonSchemaTypeSchema)]).optional(),\n\n // String validation\n minLength: z.number().optional(),\n maxLength: z.number().optional(),\n pattern: z.string().optional(),\n\n // Number validation\n minimum: z.number().optional(),\n maximum: z.number().optional(),\n exclusiveMinimum: z.number().optional(),\n exclusiveMaximum: z.number().optional(),\n\n // Enum\n enum: z\n .array(z.union([z.string(), z.number(), z.boolean(), z.null()]))\n .readonly()\n .optional(),\n const: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(),\n\n // Object\n properties: z.record(z.string(), jsonSchema7Schema).optional(),\n required: z.array(z.string()).optional(),\n additionalProperties: z.union([z.boolean(), jsonSchema7Schema]).optional(),\n\n // Array\n items: z.union([jsonSchema7Schema, z.array(jsonSchema7Schema)]).optional(),\n minItems: z.number().optional(),\n maxItems: z.number().optional(),\n\n // Composition\n allOf: z.array(jsonSchema7Schema).optional(),\n anyOf: z.array(jsonSchema7Schema).optional(),\n oneOf: z.array(jsonSchema7Schema).optional(),\n not: jsonSchema7Schema.optional(),\n\n // Conditional\n if: jsonSchema7Schema.optional(),\n then: jsonSchema7Schema.optional(),\n else: jsonSchema7Schema.optional(),\n\n // Format\n format: z.string().optional(),\n\n // Default\n default: z.unknown().optional(),\n\n // FormSpec extensions\n \"x-formspec-source\": z.string().optional(),\n \"x-formspec-params\": z.array(z.string()).readonly().optional(),\n \"x-formspec-schemaSource\": z.string().optional(),\n })\n // passthrough preserves arbitrary x-formspec-* extension properties\n // added by custom decorators without causing validation failures\n .passthrough()\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 * 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 * `@MinLength`, `@MaxLength`, `@Pattern`, `@EnumOptions`\n * — Parsed via TSDocParser as custom block tags.\n *\n * 2. **Annotation tags** (`@Field_displayName`, `@Field_description`):\n * These contain underscores which are not valid in TSDoc tag names.\n * They are extracted via the TypeScript compiler's `ts.getJSDocTags()`\n * until a future migration to underscore-free tag names.\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 type BuiltinConstraintName,\n type ConstraintNode,\n type AnnotationNode,\n type Provenance,\n type NumericConstraintNode,\n type LengthConstraintNode,\n} from \"@formspec/core\";\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/**\n * Constraint tag name → constraint kind mapping for numeric constraints.\n */\nconst NUMERIC_CONSTRAINT_MAP: Record<string, NumericConstraintNode[\"constraintKind\"]> = {\n Minimum: \"minimum\",\n Maximum: \"maximum\",\n ExclusiveMinimum: \"exclusiveMinimum\",\n ExclusiveMaximum: \"exclusiveMaximum\",\n};\n\n/**\n * Constraint tag name → constraint kind mapping for length constraints.\n */\nconst LENGTH_CONSTRAINT_MAP: Record<string, LengthConstraintNode[\"constraintKind\"]> = {\n MinLength: \"minLength\",\n MaxLength: \"maxLength\",\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 */\nconst TAGS_REQUIRING_RAW_TEXT = new Set([\"Pattern\", \"EnumOptions\"]);\n\n/**\n * Type guard that checks whether a tag name is a known BuiltinConstraintName.\n */\nfunction isBuiltinConstraintName(tagName: string): tagName is BuiltinConstraintName {\n return tagName in BUILTIN_CONSTRAINT_DEFINITIONS;\n}\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 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 modifier/block tags and TS JSDoc API. */\n readonly annotations: readonly AnnotationNode[];\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. For annotation tags that contain\n * underscores (`@Field_displayName`, `@Field_description`), the TypeScript\n * compiler JSDoc API is used as a fallback.\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\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 = block.blockTag.tagName.substring(1); // Remove leading @\n if (TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;\n\n const text = extractBlockText(block).trim();\n if (text === \"\") 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 annotations.push({\n kind: \"annotation\",\n annotationKind: \"deprecated\",\n provenance: provenanceForComment(range, sourceFile, file, \"deprecated\"),\n });\n }\n }\n }\n\n // ----- Phase 1b: TS compiler API for tags with TSDoc-incompatible content -----\n // @Pattern and @EnumOptions content can contain `@` and `{}` characters\n // which the TSDoc parser treats as structural markers. We extract these\n // via the TS compiler API which preserves content verbatim.\n const jsDocTagsAll = ts.getJSDocTags(node);\n for (const tag of jsDocTagsAll) {\n const tagName = 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 const constraintNode = parseConstraintValue(tagName, text, provenance);\n if (constraintNode) {\n constraints.push(constraintNode);\n }\n }\n\n // ----- Phase 2: TS compiler JSDoc API for underscore-containing annotation tags -----\n // @Field_displayName and @Field_description contain underscores which\n // are invalid in TSDoc tag names. We extract them via the TS compiler API.\n let displayName: string | undefined;\n let description: string | undefined;\n let displayNameTag: ts.JSDocTag | undefined;\n let descriptionTag: ts.JSDocTag | undefined;\n\n for (const tag of jsDocTagsAll) {\n const tagName = tag.tagName.text;\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText.trim() === \"\") {\n continue;\n }\n\n const trimmed = commentText.trim();\n\n if (tagName === \"Field_displayName\") {\n displayName = trimmed;\n displayNameTag = tag;\n } else if (tagName === \"Field_description\") {\n description = trimmed;\n descriptionTag = tag;\n }\n }\n\n if (displayName !== undefined && displayNameTag) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"displayName\",\n value: displayName,\n provenance: provenanceForJSDocTag(displayNameTag, file),\n });\n }\n\n if (description !== undefined && descriptionTag) {\n annotations.push({\n kind: \"annotation\",\n annotationKind: \"description\",\n value: description,\n provenance: provenanceForJSDocTag(descriptionTag, file),\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// 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 */\nfunction parseConstraintValue(\n tagName: string,\n text: string,\n provenance: Provenance\n): ConstraintNode | null {\n if (!isBuiltinConstraintName(tagName)) {\n return null;\n }\n\n const expectedType = BUILTIN_CONSTRAINT_DEFINITIONS[tagName];\n\n if (expectedType === \"number\") {\n const value = Number(text);\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 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 provenance,\n };\n }\n\n return null;\n }\n\n if (expectedType === \"json\") {\n try {\n const parsed: unknown = JSON.parse(text);\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 provenance,\n };\n } catch {\n return null;\n }\n }\n\n // expectedType === \"string\" — only remaining case after number and json\n return {\n kind: \"constraint\",\n constraintKind: \"pattern\",\n pattern: text,\n provenance,\n };\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 * 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 (@Field_displayName, etc.)\n *\n * The IR extraction path uses the official `@microsoft/tsdoc` parser for\n * constraints (all TSDoc-compliant alphanumeric names) and the TypeScript\n * compiler JSDoc API for annotation tags (which contain underscores, e.g.\n * `@Field_displayName`).\n *\n * Supported constraints correspond to keys in {@link BUILTIN_CONSTRAINT_DEFINITIONS}\n * from `@formspec/core` (e.g., `@Minimum`, `@Maximum`, `@Pattern`).\n */\n\nimport * as ts from \"typescript\";\nimport {\n BUILTIN_CONSTRAINT_DEFINITIONS,\n type BuiltinConstraintName,\n type ConstraintNode,\n type AnnotationNode,\n type JsonValue,\n} from \"@formspec/core\";\nimport { parseTSDocTags, hasDeprecatedTagTSDoc } from \"./tsdoc-parser.js\";\n\n// =============================================================================\n// Legacy types — previously in decorator-extractor.ts, now owned here\n// =============================================================================\n\n/**\n * A constraint argument value.\n */\nexport type ConstraintArg =\n | string\n | number\n | boolean\n | null\n | ConstraintArg[]\n | { [key: string]: ConstraintArg };\n\n/**\n * Extracted constraint information from a JSDoc tag.\n * @deprecated Use {@link ConstraintNode} from the IR path instead.\n */\nexport interface ConstraintInfo {\n /** Constraint name (e.g., \"Minimum\", \"Pattern\", \"Field\") */\n name: string;\n /** Constraint arguments as literal values */\n args: ConstraintArg[];\n /** Raw AST node (undefined for synthetic JSDoc constraint entries) */\n node: ts.Decorator | undefined;\n}\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 `@Field_displayName`, `@Field_description`, and `@deprecated`\n * TSDoc tags from a node and returns canonical {@link AnnotationNode} objects.\n *\n * Uses a hybrid approach:\n * - `@deprecated` is extracted via the TSDoc parser (standard tag).\n * - `@Field_displayName` and `@Field_description` are extracted via the\n * TypeScript compiler JSDoc API because they contain underscores which\n * are invalid in TSDoc tag names.\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// =============================================================================\n// LEGACY API — backward compatibility for decorator-based pipeline\n// =============================================================================\n\n/**\n * Extracts JSDoc constraint tags and returns synthetic {@link ConstraintInfo}\n * objects for backward compatibility with the decorator-based pipeline.\n *\n * Uses the TypeScript compiler JSDoc API (not TSDoc parser) to maintain\n * identical behavior with the legacy pipeline.\n *\n * @deprecated Use {@link extractJSDocConstraintNodes} for IR output.\n */\nexport function extractJSDocConstraints(node: ts.Node): ConstraintInfo[] {\n const results: ConstraintInfo[] = [];\n const jsDocTags = ts.getJSDocTags(node);\n\n for (const tag of jsDocTags) {\n const tagName = tag.tagName.text;\n\n if (!(tagName in BUILTIN_CONSTRAINT_DEFINITIONS)) {\n continue;\n }\n\n const constraintName = tagName as BuiltinConstraintName;\n const expectedType = BUILTIN_CONSTRAINT_DEFINITIONS[constraintName];\n\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText === \"\") {\n continue;\n }\n\n const trimmed = commentText.trim();\n if (trimmed === \"\") {\n continue;\n }\n\n if (expectedType === \"number\") {\n const value = Number(trimmed);\n if (Number.isNaN(value)) {\n continue;\n }\n results.push(createSyntheticDecorator(constraintName, value));\n } else if (expectedType === \"json\") {\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (!Array.isArray(parsed)) {\n continue;\n }\n results.push(createSyntheticDecorator(constraintName, parsed as ConstraintArg));\n } catch {\n continue;\n }\n } else {\n results.push(createSyntheticDecorator(constraintName, trimmed));\n }\n }\n\n return results;\n}\n\n/**\n * Extracts `@Field_displayName` and `@Field_description` TSDoc tags\n * and returns a synthetic `Field` {@link ConstraintInfo} for backward\n * compatibility with the decorator-based pipeline.\n *\n * @deprecated Use {@link extractJSDocAnnotationNodes} for IR output.\n */\nexport function extractJSDocFieldMetadata(node: ts.Node): ConstraintInfo | null {\n const jsDocTags = ts.getJSDocTags(node);\n\n let displayName: string | undefined;\n let description: string | undefined;\n\n for (const tag of jsDocTags) {\n const tagName = tag.tagName.text;\n const commentText = getTagCommentText(tag);\n if (commentText === undefined || commentText.trim() === \"\") {\n continue;\n }\n\n const trimmed = commentText.trim();\n\n if (tagName === \"Field_displayName\") {\n displayName = trimmed;\n } else if (tagName === \"Field_description\") {\n description = trimmed;\n }\n }\n\n if (displayName === undefined && description === undefined) {\n return null;\n }\n\n const fieldOpts: Record<string, ConstraintArg> = {\n ...(displayName !== undefined ? { displayName } : {}),\n ...(description !== undefined ? { description } : {}),\n };\n\n return createSyntheticDecorator(\"Field\", fieldOpts);\n}\n\n// =============================================================================\n// PRIVATE HELPERS\n// =============================================================================\n\n/**\n * Extracts the text content from a JSDoc tag's comment.\n *\n * The `tag.comment` property can be a plain string, an array of\n * `JSDocComment` nodes, or undefined. This helper normalises all\n * three cases to a single `string | undefined`.\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 // NodeArray<JSDocComment> — concatenate text spans\n return ts.getTextOfJSDocComment(tag.comment);\n}\n\n/**\n * Creates a synthetic {@link ConstraintInfo} for backward compatibility.\n */\nfunction createSyntheticDecorator(name: string, value: ConstraintArg): ConstraintInfo {\n return {\n name,\n args: [value],\n node: undefined,\n };\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 ConstraintNode,\n AnnotationNode,\n Provenance,\n ObjectProperty,\n TypeDefinition,\n JsonValue,\n} from \"@formspec/core\";\nimport {\n extractJSDocConstraintNodes,\n extractJSDocAnnotationNodes,\n extractDefaultValueAnnotation,\n} from \"./jsdoc-constraints.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// IR OUTPUT TYPES\n// =============================================================================\n\n/**\n * Layout metadata extracted from `@Group` and `@ShowWhen` decorators.\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 /** 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 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 { name, fields, fieldLayouts, typeRegistry, instanceMethods, staticMethods };\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 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 { name, fields, fieldLayouts, typeRegistry, instanceMethods: [], staticMethods: [] };\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 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 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 const type = resolveTypeNode(tsType, checker, file, typeRegistry, visiting);\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 const annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@Field_displayName, @Field_description, @deprecated)\n annotations.push(...extractJSDocAnnotationNodes(prop, file));\n\n // Default value annotation\n const defaultAnnotation = extractDefaultValueAnnotation(prop.initializer, file);\n if (defaultAnnotation) {\n annotations.push(defaultAnnotation);\n }\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 const type = resolveTypeNode(tsType, checker, file, typeRegistry, visiting);\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 const annotations: AnnotationNode[] = [];\n\n // JSDoc annotations (@Field_displayName, @Field_description, @deprecated)\n annotations.push(...extractJSDocAnnotationNodes(prop, file));\n\n return {\n kind: \"field\",\n name,\n type,\n required: !optional,\n constraints,\n annotations,\n provenance,\n };\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): 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);\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): TypeNode {\n const allTypes = type.types;\n\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\n // Boolean union: true | false → boolean primitive\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 if (hasNull) {\n return {\n kind: \"union\",\n members: [boolNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n };\n }\n return boolNode;\n }\n\n // All string literals → EnumTypeNode\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: stringTypes.map((t) => ({ value: t.value })),\n };\n if (hasNull) {\n return {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n };\n }\n return enumNode;\n }\n\n // All number literals → EnumTypeNode\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: numberTypes.map((t) => ({ value: t.value })),\n };\n if (hasNull) {\n return {\n kind: \"union\",\n members: [enumNode, { kind: \"primitive\", primitiveKind: \"null\" }],\n };\n }\n return enumNode;\n }\n\n // Nullable wrapper: T | null with single non-null type\n if (nonNullTypes.length === 1 && nonNullTypes[0]) {\n const inner = resolveTypeNode(nonNullTypes[0], checker, file, typeRegistry, visiting);\n if (hasNull) {\n return {\n kind: \"union\",\n members: [inner, { kind: \"primitive\", primitiveKind: \"null\" }],\n };\n }\n return inner;\n }\n\n // General union\n const members = nonNullTypes.map((t) =>\n resolveTypeNode(t, checker, file, typeRegistry, visiting)\n );\n if (hasNull) {\n members.push({ kind: \"primitive\", primitiveKind: \"null\" });\n }\n return { 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\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 // Circular reference guard\n if (visiting.has(type)) {\n return { kind: \"object\", properties: [], additionalProperties: false };\n }\n visiting.add(type);\n\n // Check if this is a named type already in the registry\n const typeName = getNamedTypeName(type);\n if (typeName && typeName in typeRegistry) {\n visiting.delete(type);\n return { kind: \"reference\", name: typeName, typeArguments: [] };\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(propType, checker, file, typeRegistry, visiting);\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: false,\n };\n\n // Register named types\n if (typeName) {\n typeRegistry[typeName] = {\n name: typeName,\n type: objectNode,\n provenance: provenanceForFile(file),\n };\n return { kind: \"reference\", name: typeName, 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/**\n * Given a type node referencing a type alias, extracts IR ConstraintNodes\n * from the alias declaration's JSDoc tags.\n */\nfunction extractTypeAliasConstraintNodes(\n typeNode: ts.TypeNode,\n checker: ts.TypeChecker,\n file: string\n): ConstraintNode[] {\n if (!ts.isTypeReferenceNode(typeNode)) return [];\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 return extractJSDocConstraintNodes(aliasDecl, file);\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\n// =============================================================================\n// NAMED TYPE HELPERS\n// =============================================================================\n\n/**\n * Extracts a stable type name from a ts.ObjectType when it originates from\n * a named declaration (class, interface, or type alias).\n */\nfunction getNamedTypeName(type: ts.ObjectType): 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// 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 * 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 * `@formspec/build` - Build tools for FormSpec\n *\n * This package provides generators to compile FormSpec forms into:\n * - JSON Schema 2020-12 (for validation)\n * - JSON Forms UI Schema (for rendering)\n *\n * @example\n * ```typescript\n * import { buildFormSchemas } from \"@formspec/build\";\n * import { formspec, field, group } from \"@formspec/dsl\";\n *\n * const form = formspec(\n * group(\"Customer\",\n * field.text(\"name\", { label: \"Name\", required: true }),\n * field.text(\"email\", { label: \"Email\" }),\n * ),\n * );\n *\n * const { jsonSchema, uiSchema } = buildFormSchemas(form);\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { FormElement, FormSpec } from \"@formspec/core\";\nimport { generateJsonSchema } from \"./json-schema/generator.js\";\nimport { generateUiSchema } from \"./ui-schema/generator.js\";\nimport type { JsonSchema2020 } from \"./json-schema/ir-generator.js\";\nimport type { UISchema } from \"./ui-schema/types.js\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// =============================================================================\n// Type Exports\n// =============================================================================\n\nexport type { JsonSchema2020 } from \"./json-schema/ir-generator.js\";\n\nexport type {\n JSONSchema7,\n JSONSchemaType,\n ExtendedJSONSchema7,\n FormSpecSchemaExtensions,\n} from \"./json-schema/types.js\";\n\nexport { setSchemaExtension, getSchemaExtension } from \"./json-schema/types.js\";\n\nexport type {\n UISchema,\n UISchemaElement,\n UISchemaElementBase,\n UISchemaElementType,\n ControlElement,\n VerticalLayout,\n HorizontalLayout,\n GroupLayout,\n Categorization,\n Category,\n LabelElement,\n Rule,\n RuleEffect,\n RuleConditionSchema,\n SchemaBasedCondition,\n} from \"./ui-schema/types.js\";\n\nexport type {\n ClassSchemas,\n GenerateFromClassOptions,\n GenerateFromClassResult,\n GenerateSchemasOptions,\n} from \"./generators/class-schema.js\";\n\n// =============================================================================\n// Zod Validation Schemas\n// =============================================================================\n\nexport {\n ruleEffectSchema,\n uiSchemaElementTypeSchema,\n ruleConditionSchema,\n schemaBasedConditionSchema,\n ruleSchema,\n controlSchema,\n verticalLayoutSchema,\n horizontalLayoutSchema,\n groupLayoutSchema,\n categorizationSchema,\n categorySchema,\n labelElementSchema,\n uiSchemaElementSchema,\n uiSchema as uiSchemaSchema,\n} from \"./ui-schema/schema.js\";\n\nexport { jsonSchemaTypeSchema, jsonSchema7Schema } from \"./json-schema/schema.js\";\n\n// =============================================================================\n// Chain DSL Generators\n// =============================================================================\n\nexport { generateJsonSchema } from \"./json-schema/generator.js\";\nexport { generateUiSchema } from \"./ui-schema/generator.js\";\n\n// =============================================================================\n// Class/Interface Analysis: High-Level Entry Points\n// =============================================================================\n\nexport { generateSchemasFromClass, generateSchemas } from \"./generators/class-schema.js\";\n\n// generateSchemas is the recommended entry point — it auto-detects class/interface/type alias.\n// generateSchemasFromClass is retained for backwards compatibility.\n\n/**\n * Result of building form schemas.\n */\nexport interface BuildResult {\n /** JSON Schema 2020-12 for validation */\n readonly jsonSchema: JsonSchema2020;\n /** JSON Forms UI Schema for rendering */\n readonly uiSchema: UISchema;\n}\n\n/**\n * Builds both JSON Schema and UI Schema from a FormSpec.\n *\n * This is a convenience function that combines `generateJsonSchema`\n * and `generateUiSchema`.\n *\n * @example\n * ```typescript\n * const form = formspec(\n * field.text(\"name\", { required: true }),\n * field.number(\"age\", { min: 0 }),\n * );\n *\n * const { jsonSchema, uiSchema } = buildFormSchemas(form);\n *\n * // Use with JSON Forms renderer\n * <JsonForms\n * schema={jsonSchema}\n * uischema={uiSchema}\n * data={formData}\n * renderers={materialRenderers}\n * />\n * ```\n *\n * @param form - The FormSpec to build schemas from\n * @returns Object containing both jsonSchema and uiSchema\n */\nexport function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>): BuildResult {\n return {\n jsonSchema: generateJsonSchema(form),\n uiSchema: generateUiSchema(form),\n };\n}\n\n/**\n * Options for writing schemas to disk.\n */\nexport interface WriteSchemasOptions {\n /** Output directory for the schema files */\n readonly outDir: string;\n /** Base name for the output files (without extension). Defaults to \"schema\" */\n readonly name?: string;\n /** Number of spaces for JSON indentation. Defaults to 2 */\n readonly indent?: number;\n}\n\n/**\n * Result of writing schemas to disk.\n */\nexport interface WriteSchemasResult {\n /** Path to the generated JSON Schema file */\n readonly jsonSchemaPath: string;\n /** Path to the generated UI Schema file */\n readonly uiSchemaPath: string;\n}\n\n/**\n * Builds and writes both JSON Schema and UI Schema files to disk.\n *\n * This is a convenience function for build-time schema generation.\n * It creates the output directory if it doesn't exist.\n *\n * @example\n * ```typescript\n * import { formspec, field } from \"formspec\";\n * import { writeSchemas } from \"@formspec/build\";\n *\n * const ProductForm = formspec(\n * field.text(\"name\", { required: true }),\n * field.enum(\"status\", [\"draft\", \"active\"]),\n * );\n *\n * // Write schemas to ./generated/product-schema.json and ./generated/product-uischema.json\n * const { jsonSchemaPath, uiSchemaPath } = writeSchemas(ProductForm, {\n * outDir: \"./generated\",\n * name: \"product\",\n * });\n *\n * console.log(`Generated: ${jsonSchemaPath}, ${uiSchemaPath}`);\n * ```\n *\n * @param form - The FormSpec to build schemas from\n * @param options - Output options (directory, file name, indentation)\n * @returns Object containing paths to the generated files\n */\nexport function writeSchemas<E extends readonly FormElement[]>(\n form: FormSpec<E>,\n options: WriteSchemasOptions\n): WriteSchemasResult {\n const { outDir, name = \"schema\", indent = 2 } = options;\n\n // Build schemas\n const { jsonSchema, uiSchema } = buildFormSchemas(form);\n\n // Ensure output directory exists\n if (!fs.existsSync(outDir)) {\n fs.mkdirSync(outDir, { recursive: true });\n }\n\n // Write files\n const jsonSchemaPath = path.join(outDir, `${name}-schema.json`);\n const uiSchemaPath = path.join(outDir, `${name}-uischema.json`);\n\n fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));\n fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema, null, indent));\n\n return { jsonSchemaPath, uiSchemaPath };\n}\n","#!/usr/bin/env node\n/**\n * FormSpec CLI - Generate JSON Schema and UI Schema from form definitions\n *\n * Usage:\n * formspec-build <input-file> [options]\n *\n * Options:\n * -o, --out-dir <dir> Output directory (default: ./generated)\n * -n, --name <name> Base name for output files (default: derived from input)\n * -h, --help Show help\n *\n * Example:\n * formspec-build src/forms/product.ts -o ./schemas -n product\n */\n\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\ninterface CliOptions {\n inputFile: string;\n outDir: string;\n name: string;\n}\n\nfunction printHelp(): void {\n console.log(`\nFormSpec Build CLI - Generate JSON Schema and UI Schema\n\nUsage:\n formspec-build <input-file> [options]\n\nOptions:\n -o, --out-dir <dir> Output directory (default: ./generated)\n -n, --name <name> Base name for output files (default: derived from input)\n -h, --help Show this help message\n\nExample:\n formspec-build src/forms/product.ts -o ./schemas -n product\n\nThe input file should export a FormSpec as its default export or as 'form':\n // product-form.ts\n import { formspec, field } from \"formspec\";\n export default formspec(field.text(\"name\"));\n // or: export const form = formspec(field.text(\"name\"));\n`);\n}\n\nfunction parseArgs(args: string[]): CliOptions | null {\n const positional: string[] = [];\n let outDir = \"./generated\";\n let name = \"\";\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n\n if (arg === \"-h\" || arg === \"--help\") {\n printHelp();\n process.exit(0);\n }\n\n if (arg === \"-o\" || arg === \"--out-dir\") {\n const nextArg = args[i + 1];\n if (!nextArg) {\n console.error(\"Error: --out-dir requires a value\");\n return null;\n }\n outDir = nextArg;\n i++;\n continue;\n }\n\n if (arg === \"-n\" || arg === \"--name\") {\n const nextArg = args[i + 1];\n if (!nextArg) {\n console.error(\"Error: --name requires a value\");\n return null;\n }\n name = nextArg;\n i++;\n continue;\n }\n\n if (arg.startsWith(\"-\")) {\n console.error(`Error: Unknown option: ${arg}`);\n return null;\n }\n\n positional.push(arg);\n }\n\n if (positional.length === 0) {\n console.error(\"Error: No input file specified\");\n printHelp();\n return null;\n }\n\n const inputFile = positional[0];\n if (!inputFile) {\n console.error(\"Error: No input file specified\");\n return null;\n }\n\n // Default name from input file\n if (!name) {\n name = path.basename(inputFile, path.extname(inputFile));\n }\n\n return { inputFile, outDir, name };\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const options = parseArgs(args);\n\n if (!options) {\n process.exit(1);\n }\n\n const { inputFile, outDir, name } = options;\n\n // Resolve input file path\n const absoluteInput = path.resolve(process.cwd(), inputFile);\n\n try {\n // Dynamically import the input file\n // Use file URL for cross-platform compatibility (Windows paths need file:// URLs)\n const fileUrl = pathToFileURL(absoluteInput).href;\n const module = (await import(fileUrl)) as Record<string, unknown>;\n\n // Look for the form export\n const form = module[\"default\"] ?? module[\"form\"];\n\n if (!form || typeof form !== \"object\" || !(\"elements\" in form)) {\n console.error(\"Error: Input file must export a FormSpec as default export or as 'form'\");\n console.error(\"Example:\");\n console.error(' export default formspec(field.text(\"name\"));');\n console.error(\" // or\");\n console.error(' export const form = formspec(field.text(\"name\"));');\n process.exit(1);\n }\n\n // Import writeSchemas dynamically to avoid circular deps\n const { writeSchemas } = await import(\"./index.js\");\n\n const { jsonSchemaPath, uiSchemaPath } = writeSchemas(\n form as Parameters<typeof writeSchemas>[0],\n { outDir, name }\n );\n\n console.log(\"Generated:\");\n console.log(` ${jsonSchemaPath}`);\n console.log(` ${uiSchemaPath}`);\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n } else {\n console.error(\"Error:\", error);\n }\n process.exit(1);\n }\n}\n\nvoid main();\n"],"mappings":"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","names":["IR_VERSION","z","init_ir_generator","init_generator","init_ir_generator","z","init_schema","ts","ts","BUILTIN_CONSTRAINT_DEFINITIONS","ts","isBooleanUnion","init_ir_generator","path","uiSchema","init_generator","init_schema","path","writeSchemas"]}