@formspec/core 0.1.0-alpha.23 → 0.1.0-alpha.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/field-state.ts","../src/types/constraint-definitions.ts","../src/types/ir.ts","../src/extensions/index.ts","../src/guards.ts"],"sourcesContent":["import type { Validity } from \"./validity.js\";\n\n/**\n * Represents the runtime state of a single form field.\n *\n * @typeParam T - The value type of the field\n *\n * @public\n */\nexport interface FieldState<T> {\n /** Current value of the field */\n readonly value: T;\n\n /** Whether the field has been modified by the user */\n readonly dirty: boolean;\n\n /** Whether the field has been focused and blurred */\n readonly touched: boolean;\n\n /** Current validity state */\n readonly validity: Validity;\n\n /** Validation error messages, if any */\n readonly errors: readonly string[];\n}\n\n/**\n * Creates initial field state with default values.\n *\n * @typeParam T - The value type of the field\n * @param value - The initial value for the field\n * @returns Initial field state\n *\n * @public\n */\nexport function createInitialFieldState<T>(value: T): FieldState<T> {\n return {\n value,\n dirty: false,\n touched: false,\n validity: \"unknown\",\n errors: [],\n };\n}\n","/**\n * Built-in constraint definitions for FormSpec constraint validation.\n *\n * This is the single source of truth for which constraints FormSpec\n * recognizes. Both `@formspec/build` (schema generation)\n * and `@formspec/eslint-plugin` (lint-time validation) import from here.\n */\n\n/**\n * Built-in constraint names mapped to their expected value type for parsing.\n * Constraints are surface-agnostic — they manifest as both TSDoc tags\n * (e.g., `@minimum 0`) and chain DSL options (e.g., `{ minimum: 0 }`).\n *\n * Keys use camelCase matching JSON Schema property names.\n *\n * @internal\n */\nexport const _BUILTIN_CONSTRAINT_DEFINITIONS = {\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 uniqueItems: \"boolean\",\n pattern: \"string\",\n const: \"json\",\n enumOptions: \"json\",\n} as const;\n\n/**\n * Type of a built-in constraint name.\n *\n * @public\n */\nexport type BuiltinConstraintName =\n | \"minimum\"\n | \"maximum\"\n | \"exclusiveMinimum\"\n | \"exclusiveMaximum\"\n | \"multipleOf\"\n | \"minLength\"\n | \"maxLength\"\n | \"minItems\"\n | \"maxItems\"\n | \"uniqueItems\"\n | \"pattern\"\n | \"const\"\n | \"enumOptions\";\n\n/**\n * Normalizes a constraint tag name from PascalCase to camelCase.\n *\n * Lowercases the first character so that e.g. `\"Minimum\"` becomes `\"minimum\"`.\n * Callers must strip the `@` prefix before calling this function.\n *\n * @example\n * normalizeConstraintTagName(\"Minimum\") // \"minimum\"\n * normalizeConstraintTagName(\"MinLength\") // \"minLength\"\n * normalizeConstraintTagName(\"minimum\") // \"minimum\" (idempotent)\n *\n * @internal\n */\nexport function _normalizeConstraintTagName(tagName: string): string {\n return tagName.charAt(0).toLowerCase() + tagName.slice(1);\n}\n\n/**\n * Type guard: checks whether a tag name is a known built-in constraint.\n *\n * Uses `Object.hasOwn()` rather than `in` to prevent prototype-chain\n * matches on names like `\"toString\"` or `\"constructor\"`.\n *\n * Callers should normalize with {@link _normalizeConstraintTagName} first\n * if the input may be PascalCase.\n *\n * @internal\n */\nexport function _isBuiltinConstraintName(tagName: string): tagName is BuiltinConstraintName {\n return Object.hasOwn(_BUILTIN_CONSTRAINT_DEFINITIONS, tagName);\n}\n","/**\n * Canonical Intermediate Representation (IR) types for FormSpec.\n *\n * The IR is the shared intermediate structure that both authoring surfaces\n * (chain DSL and TSDoc-annotated types) compile to. All downstream operations\n * — JSON Schema generation, UI Schema generation, constraint validation,\n * diagnostics — consume the IR exclusively.\n *\n * All types are plain, serializable objects (no live compiler references).\n *\n * @see {@link https://github.com/stripe/formspec-workspace/blob/main/scratch/design/001-canonical-ir.md}\n */\n\n// =============================================================================\n// IR VERSION\n// =============================================================================\n\n/**\n * The current IR format version. Centralized here so all canonicalizers\n * and consumers reference a single source of truth.\n *\n * @beta\n */\nexport const IR_VERSION = \"0.1.0\" as const;\n\n// =============================================================================\n// UTILITY TYPES\n// =============================================================================\n\n/**\n * A JSON-serializable value. All IR nodes must be representable as JSON.\n *\n * @beta\n */\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | readonly JsonValue[]\n | { readonly [key: string]: JsonValue };\n\n// =============================================================================\n// PROVENANCE\n// =============================================================================\n\n/**\n * Describes the origin of an IR node.\n * Enables diagnostics that point to the source of a contradiction or error.\n *\n * @beta\n */\nexport interface Provenance {\n /** The authoring surface that produced this node. */\n readonly surface: \"tsdoc\" | \"chain-dsl\" | \"extension\" | \"inferred\";\n /** Absolute path to the source file. */\n readonly file: string;\n /** 1-based line number in the source file. */\n readonly line: number;\n /** 0-based column number in the source file. */\n readonly column: number;\n /** Length of the source span in characters (for IDE underline ranges). */\n readonly length?: number;\n /**\n * The specific tag, call, or construct that produced this node.\n * Examples: `@minimum`, `field.number({ min: 0 })`, `optional`\n */\n readonly tagName?: string;\n}\n\n// =============================================================================\n// PATH TARGET\n// =============================================================================\n\n/**\n * A path targeting a sub-field within a complex type.\n * Used by constraints and annotations to target nested properties.\n *\n * @beta\n */\nexport interface PathTarget {\n /**\n * Sequence of property names forming a path from the annotated field's type\n * to the target sub-field.\n * e.g., `[\"value\"]` or `[\"address\", \"zip\"]`\n */\n readonly segments: readonly string[];\n}\n\n// =============================================================================\n// TYPE NODES\n// =============================================================================\n\n/**\n * Discriminated union of all type representations in the IR.\n *\n * @beta\n */\nexport type TypeNode =\n | PrimitiveTypeNode\n | EnumTypeNode\n | ArrayTypeNode\n | ObjectTypeNode\n | RecordTypeNode\n | UnionTypeNode\n | ReferenceTypeNode\n | DynamicTypeNode\n | CustomTypeNode;\n\n/**\n * Primitive types mapping directly to JSON Schema primitives.\n *\n * Note: integer is NOT a primitive kind — integer semantics are expressed\n * via a `multipleOf: 1` constraint on a number type.\n *\n * @beta\n */\nexport interface PrimitiveTypeNode {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n}\n\n/**\n * A member of a static enum type.\n *\n * @beta\n */\nexport interface EnumMember {\n /** The serialized value stored in data. */\n readonly value: string | number;\n /** Optional per-member display name. */\n readonly displayName?: string;\n}\n\n/**\n * Static enum type with members known at build time.\n *\n * @beta\n */\nexport interface EnumTypeNode {\n readonly kind: \"enum\";\n readonly members: readonly EnumMember[];\n}\n\n/**\n * Array type with a single items type.\n *\n * @beta\n */\nexport interface ArrayTypeNode {\n readonly kind: \"array\";\n readonly items: TypeNode;\n}\n\n/**\n * A named property within an object type.\n *\n * @beta\n */\nexport interface ObjectProperty {\n readonly name: string;\n readonly type: TypeNode;\n readonly optional: boolean;\n /**\n * Use-site constraints on this property.\n * Distinct from constraints on the property's type — these are\n * use-site constraints (e.g., `@minimum :amount 0` targets the\n * `amount` property of a `MonetaryAmount` field).\n */\n readonly constraints: readonly ConstraintNode[];\n /** Use-site annotations on this property. */\n readonly annotations: readonly AnnotationNode[];\n readonly provenance: Provenance;\n}\n\n/**\n * Object type with named properties.\n *\n * @beta\n */\nexport interface ObjectTypeNode {\n readonly kind: \"object\";\n /**\n * Named properties of this object. Order is preserved from the source\n * declaration for deterministic output.\n */\n readonly properties: readonly ObjectProperty[];\n /**\n * Whether additional properties beyond those listed are permitted.\n * Ordinary static object types default to true under the current spec.\n * Explicitly closed-object modes may still set this to false.\n */\n readonly additionalProperties: boolean;\n}\n\n/**\n * Record (dictionary) type — an object with a string index signature and no\n * named properties. Corresponds to `Record<string, T>` or `{ [k: string]: T }`.\n *\n * Emitted as `{ \"type\": \"object\", \"additionalProperties\": <value schema> }` in\n * JSON Schema per spec 003 §2.5.\n *\n * @beta\n */\nexport interface RecordTypeNode {\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/**\n * Union type for non-enum unions. Nullable types are represented as `T | null`.\n *\n * @beta\n */\nexport interface UnionTypeNode {\n readonly kind: \"union\";\n readonly members: readonly TypeNode[];\n}\n\n/**\n * Named type reference preserved for `$defs` and `$ref` emission.\n *\n * @beta\n */\nexport interface ReferenceTypeNode {\n readonly kind: \"reference\";\n /**\n * The fully-qualified name of the referenced type.\n * For TypeScript interfaces/type aliases: `\"<module>#<TypeName>\"`.\n * For built-in types: the primitive kind string.\n */\n readonly name: string;\n /**\n * Type arguments if this is a generic instantiation.\n * e.g., `Array<string>` → `{ name: \"Array\", typeArguments: [PrimitiveTypeNode(\"string\")] }`\n */\n readonly typeArguments: readonly TypeNode[];\n}\n\n/**\n * Dynamic type whose schema is resolved at runtime from a named data source.\n *\n * @beta\n */\nexport interface DynamicTypeNode {\n readonly kind: \"dynamic\";\n readonly dynamicKind: \"enum\" | \"schema\";\n /** Key identifying the runtime data source or schema provider. */\n readonly sourceKey: string;\n /**\n * For dynamic enums: field names whose current values are passed as\n * parameters to the data source resolver.\n */\n readonly parameterFields: readonly string[];\n}\n\n/**\n * Custom type registered by an extension.\n *\n * @beta\n */\nexport interface CustomTypeNode {\n readonly kind: \"custom\";\n /**\n * The extension-qualified type identifier.\n * Format: `\"<vendor-prefix>/<extension-name>/<type-name>\"`\n * e.g., `\"x-stripe/monetary/MonetaryAmount\"`\n */\n readonly typeId: string;\n /**\n * Opaque payload serialized by the extension that registered this type.\n * Must be JSON-serializable.\n */\n readonly payload: JsonValue;\n}\n\n// =============================================================================\n// CONSTRAINT NODES\n// =============================================================================\n\n/**\n * Discriminated union of all constraint types.\n * Constraints are set-influencing: they narrow the set of valid values.\n *\n * @beta\n */\nexport type ConstraintNode =\n | NumericConstraintNode\n | LengthConstraintNode\n | PatternConstraintNode\n | ArrayCardinalityConstraintNode\n | EnumMemberConstraintNode\n | ConstConstraintNode\n | CustomConstraintNode;\n\n/**\n * Numeric constraints: bounds and multipleOf.\n *\n * `minimum` and `maximum` are inclusive; `exclusiveMinimum` and\n * `exclusiveMaximum` are exclusive bounds (matching JSON Schema 2020-12\n * semantics).\n *\n * Type applicability: may only attach to fields with `PrimitiveTypeNode(\"number\")`\n * or a `ReferenceTypeNode` that resolves to one.\n *\n * @beta\n */\nexport interface NumericConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind:\n | \"minimum\"\n | \"maximum\"\n | \"exclusiveMinimum\"\n | \"exclusiveMaximum\"\n | \"multipleOf\";\n readonly value: number;\n /** If present, targets a nested sub-field rather than the field itself. */\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * String length and array item count constraints.\n *\n * `minLength`/`maxLength` apply to strings; `minItems`/`maxItems` apply to\n * arrays. They share the same node shape because the composition rules are\n * identical.\n *\n * Type applicability: `minLength`/`maxLength` require `PrimitiveTypeNode(\"string\")`;\n * `minItems`/`maxItems` require `ArrayTypeNode`.\n *\n * @beta\n */\nexport interface LengthConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"minLength\" | \"maxLength\" | \"minItems\" | \"maxItems\";\n readonly value: number;\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * String pattern constraint (ECMA-262 regex without delimiters).\n *\n * Multiple `pattern` constraints on the same field compose via intersection:\n * all patterns must match simultaneously.\n *\n * Type applicability: requires `PrimitiveTypeNode(\"string\")`.\n *\n * @beta\n */\nexport interface PatternConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"pattern\";\n /** ECMA-262 regular expression, without delimiters. */\n readonly pattern: string;\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * Array uniqueness constraint.\n *\n * @beta\n */\nexport interface ArrayCardinalityConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"uniqueItems\";\n readonly value: true;\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * Enum member subset constraint that only narrows the allowed member set.\n *\n * @beta\n */\nexport interface EnumMemberConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"allowedMembers\";\n readonly members: readonly (string | number)[];\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * Literal-value equality constraint.\n *\n * @beta\n */\nexport interface ConstConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"const\";\n readonly value: JsonValue;\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n/**\n * Extension-registered custom constraint.\n *\n * @beta\n */\nexport interface CustomConstraintNode {\n readonly kind: \"constraint\";\n readonly constraintKind: \"custom\";\n /** Extension-qualified ID: `\"<vendor-prefix>/<extension-name>/<constraint-name>\"` */\n readonly constraintId: string;\n /** JSON-serializable payload defined by the extension. */\n readonly payload: JsonValue;\n /** How this constraint composes with others of the same `constraintId`. */\n readonly compositionRule: \"intersect\" | \"override\";\n readonly path?: PathTarget;\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// ANNOTATION NODES\n// =============================================================================\n\n/**\n * Discriminated union of all annotation types.\n * Annotations are value-influencing: they describe or present a field\n * but do not affect which values are valid.\n *\n * @beta\n */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | RemarksAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\n/**\n * Display-name annotation.\n *\n * @beta\n */\nexport interface DisplayNameAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"displayName\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Description annotation.\n *\n * @beta\n */\nexport interface DescriptionAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"description\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Remarks annotation — programmatic-persona documentation carried via\n * the `x-<vendor>-remarks` JSON Schema extension keyword.\n *\n * Populated from `@remarks` TSDoc tag content. SDK codegen can include\n * this in doc comments; API Documenter renders the source `@remarks`\n * natively in a dedicated Remarks section.\n *\n * @beta\n */\nexport interface RemarksAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"remarks\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Schema format annotation, for example `email`, `date`, or `uri`.\n *\n * @beta\n */\nexport interface FormatAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"format\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Placeholder annotation.\n *\n * @beta\n */\nexport interface PlaceholderAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"placeholder\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Default-value annotation.\n *\n * @beta\n */\nexport interface DefaultValueAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"defaultValue\";\n /** Must be JSON-serializable and type-compatible (verified during Validate phase). */\n readonly value: JsonValue;\n readonly provenance: Provenance;\n}\n\n/**\n * Deprecated annotation.\n *\n * @beta\n */\nexport interface DeprecatedAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"deprecated\";\n /** Optional deprecation message. */\n readonly message?: string;\n readonly provenance: Provenance;\n}\n\n/**\n * UI rendering hint — does not affect schema validation.\n * Unlike FormatAnnotationNode, this never emits a JSON Schema `format`.\n *\n * @beta\n */\nexport interface FormatHintAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"formatHint\";\n /** Renderer-specific format identifier: \"textarea\", \"radio\", \"date\", \"color\", etc. */\n readonly format: string;\n readonly provenance: Provenance;\n}\n\n/**\n * Extension-registered custom annotation.\n *\n * @beta\n */\nexport interface CustomAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"custom\";\n /** Extension-qualified ID: `\"<vendor-prefix>/<extension-name>/<annotation-name>\"` */\n readonly annotationId: string;\n readonly value: JsonValue;\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// FIELD NODE\n// =============================================================================\n\n/**\n * A single form field after canonicalization.\n *\n * @beta\n */\nexport interface FieldNode {\n readonly kind: \"field\";\n /** The field's key in the data schema. */\n readonly name: string;\n /** The resolved type of this field. */\n readonly type: TypeNode;\n /** Whether this field is required in the data schema. */\n readonly required: boolean;\n /** Set-influencing constraints, after merging. */\n readonly constraints: readonly ConstraintNode[];\n /** Value-influencing annotations, after merging. */\n readonly annotations: readonly AnnotationNode[];\n /** Where this field was declared. */\n readonly provenance: Provenance;\n /**\n * Debug only — ordered list of constraint/annotation nodes that participated\n * in merging, including dominated ones.\n */\n readonly mergeHistory?: readonly {\n readonly node: ConstraintNode | AnnotationNode;\n readonly dominated: boolean;\n }[];\n}\n\n// =============================================================================\n// LAYOUT NODES\n// =============================================================================\n\n/**\n * Union of layout node types.\n *\n * @beta\n */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/**\n * A visual grouping of form elements.\n *\n * @beta\n */\nexport interface GroupLayoutNode {\n readonly kind: \"group\";\n readonly label: string;\n /** Elements contained in this group — may be fields or nested groups. */\n readonly elements: readonly FormIRElement[];\n readonly provenance: Provenance;\n}\n\n/**\n * Conditional visibility based on another field's value.\n *\n * @beta\n */\nexport interface ConditionalLayoutNode {\n readonly kind: \"conditional\";\n /** The field whose value triggers visibility. */\n readonly fieldName: string;\n /** The value that makes the condition true (SHOW). */\n readonly value: JsonValue;\n /** Elements shown when the condition is met. */\n readonly elements: readonly FormIRElement[];\n readonly provenance: Provenance;\n}\n\n/**\n * Union of all IR element types.\n *\n * @beta\n */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/**\n * A named type definition stored in the type registry.\n *\n * @beta\n */\nexport interface TypeDefinition {\n /** The fully-qualified reference name (key in the registry). */\n readonly name: string;\n /** The resolved type node. */\n readonly type: TypeNode;\n /** Constraints declared on the named type itself. */\n readonly constraints?: readonly ConstraintNode[];\n /** Root-level value metadata for a named type definition. */\n readonly annotations?: readonly AnnotationNode[];\n /** Where this type was declared. */\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// FORM IR (TOP-LEVEL)\n// =============================================================================\n\n/**\n * The complete Canonical Intermediate Representation for a form.\n *\n * Output of the Canonicalize phase; input to Validate, Generate (JSON Schema),\n * and Generate (UI Schema) phases.\n *\n * Serializable to JSON — no live compiler objects.\n *\n * @beta\n */\nexport interface FormIR {\n readonly kind: \"form-ir\";\n /**\n * Schema version for the IR format itself.\n * Should equal `IR_VERSION`.\n */\n readonly irVersion: string;\n /** Top-level elements of the form: fields and layout nodes. */\n readonly elements: readonly FormIRElement[];\n /** Root-level annotations derived from the source declaration itself. */\n readonly rootAnnotations?: readonly AnnotationNode[];\n /**\n * Registry of named types referenced by fields in this form.\n * Keys are fully-qualified type names matching `ReferenceTypeNode.name`.\n */\n readonly typeRegistry: Readonly<Record<string, TypeDefinition>>;\n /** Root-level metadata for the form itself. */\n readonly annotations?: readonly AnnotationNode[];\n /** Provenance of the form definition itself. */\n readonly provenance: Provenance;\n}\n","/**\n * Extension API for registering custom types, constraints, annotations,\n * and vocabulary keywords with FormSpec.\n *\n * Extensions allow third-party packages (e.g., \"Decimal\", \"DateOnly\") to\n * plug into the FormSpec pipeline. The types and factory functions defined\n * here are consumed by the FormSpec build pipeline.\n *\n * @packageDocumentation\n */\n\nimport type { BuiltinConstraintName } from \"../types/constraint-definitions.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * A JSON-serializable payload value used by extension registration hooks.\n *\n * @public\n */\nexport type ExtensionPayloadValue =\n | null\n | boolean\n | number\n | string\n | readonly ExtensionPayloadValue[]\n | { readonly [key: string]: ExtensionPayloadValue };\n\n/**\n * Top-level type kinds that extension applicability hooks may inspect.\n *\n * @public\n */\nexport type ExtensionTypeKind =\n | \"primitive\"\n | \"enum\"\n | \"array\"\n | \"object\"\n | \"record\"\n | \"union\"\n | \"reference\"\n | \"dynamic\"\n | \"custom\";\n\n/**\n * A curated type shape exposed to extension applicability hooks.\n *\n * This intentionally exposes only the fields needed to determine tag/type\n * applicability without committing the entire canonical IR as public API.\n *\n * @public\n */\nexport type ExtensionApplicableType =\n | {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n }\n | {\n readonly kind: \"custom\";\n readonly typeId: string;\n readonly payload: ExtensionPayloadValue;\n }\n | { readonly kind: Exclude<ExtensionTypeKind, \"primitive\" | \"custom\"> };\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced by FormSpec's internal custom-type IR nodes and\n * resolved to JSON Schema via `toJsonSchema` during generation.\n *\n * @public\n */\nexport interface CustomTypeRegistration {\n /** The type name, unique within the extension. */\n readonly typeName: string;\n /**\n * Optional TypeScript surface names that should resolve to this custom type\n * during TSDoc/class analysis. Defaults to `typeName` when omitted.\n */\n readonly tsTypeNames?: readonly string[];\n /**\n * Converts the custom type's payload into a JSON Schema fragment.\n *\n * @param payload - The opaque JSON payload stored on the custom type node.\n * @param vendorPrefix - The vendor prefix for extension keywords (e.g., \"x-stripe\").\n * @returns A JSON Schema fragment representing this type.\n */\n readonly toJsonSchema: (\n payload: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n /**\n * Optional broadening of built-in constraint tags so they can apply to this\n * custom type without modifying the core built-in constraint tables.\n */\n readonly builtinConstraintBroadenings?: readonly BuiltinConstraintBroadeningRegistration[];\n}\n\n/**\n * Registration for a custom constraint that maps to JSON Schema keywords.\n *\n * Custom constraints are referenced by FormSpec's internal custom-constraint nodes.\n *\n * @public\n */\nexport interface CustomConstraintRegistration {\n /** The constraint name, unique within the extension. */\n readonly constraintName: string;\n /**\n * How this constraint composes with other constraints of the same kind.\n * - \"intersect\": combine with logical AND (both must hold)\n * - \"override\": last writer wins\n */\n readonly compositionRule: \"intersect\" | \"override\";\n /**\n * TypeNode kinds this constraint is applicable to, or `null` for any type.\n * Used by the validator to emit TYPE_MISMATCH diagnostics.\n */\n readonly applicableTypes: readonly ExtensionApplicableType[\"kind\"][] | null;\n /**\n * Optional precise type predicate used when kind-level applicability is too\n * broad (for example, constraints that apply to integer-like primitives but\n * not strings).\n */\n readonly isApplicableToType?: (type: ExtensionApplicableType) => boolean;\n /**\n * Optional comparator for payloads belonging to the same custom constraint.\n * Return values follow the `Array.prototype.sort()` contract.\n */\n readonly comparePayloads?: (left: ExtensionPayloadValue, right: ExtensionPayloadValue) => number;\n /**\n * Optional semantic family metadata for generic contradiction/broadening\n * handling across ordered constraints.\n */\n readonly semanticRole?: ConstraintSemanticRole;\n /**\n * Converts the custom constraint's payload into JSON Schema keywords.\n *\n * @param payload - The opaque JSON payload stored on the custom constraint node.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (\n payload: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced by FormSpec's internal custom-annotation nodes.\n * They describe or present a field but do not affect which values are valid.\n *\n * @public\n */\nexport interface CustomAnnotationRegistration {\n /** The annotation name, unique within the extension. */\n readonly annotationName: string;\n /**\n * Optionally converts the annotation value into JSON Schema keywords.\n * If omitted, the annotation has no JSON Schema representation (UI-only).\n */\n readonly toJsonSchema?: (\n value: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\n *\n * @public\n */\nexport interface VocabularyKeywordRegistration {\n /** The keyword name (without vendor prefix). */\n readonly keyword: string;\n /** JSON Schema that describes the valid values for this keyword. */\n readonly schema: ExtensionPayloadValue;\n}\n\n/**\n * Declarative authoring-side registration for a custom TSDoc constraint tag.\n *\n * @public\n */\nexport interface ConstraintTagRegistration {\n /** Tag name without the `@` prefix, e.g. `\"maxSigFig\"`. */\n readonly tagName: string;\n /** The custom constraint that this tag should produce. */\n readonly constraintName: string;\n /** Parser from raw TSDoc text to JSON-serializable payload. */\n readonly parseValue: (raw: string) => ExtensionPayloadValue;\n /**\n * Optional precise applicability predicate for the field type being parsed.\n * When omitted, the target custom constraint registration controls type\n * applicability during validation.\n */\n readonly isApplicableToType?: (type: ExtensionApplicableType) => boolean;\n}\n\n/**\n * Registration for mapping a built-in TSDoc tag onto a custom constraint when\n * it is used on a particular custom type.\n *\n * @public\n */\nexport interface BuiltinConstraintBroadeningRegistration {\n /** The built-in tag being broadened, without the `@` prefix. */\n readonly tagName: BuiltinConstraintName;\n /** The custom constraint to emit for this built-in tag. */\n readonly constraintName: string;\n /** Parser from raw TSDoc text to extension payload. */\n readonly parseValue: (raw: string) => ExtensionPayloadValue;\n}\n\n/**\n * Semantic metadata for ordered custom constraints that should participate in\n * the generic contradiction/broadening logic.\n *\n * @public\n */\nexport interface ConstraintSemanticRole {\n /**\n * Logical family identifier shared by related constraints, for example\n * `\"decimal-bound\"` or `\"date-bound\"`.\n */\n readonly family: string;\n /** Whether this constraint acts as a lower or upper bound. */\n readonly bound: \"lower\" | \"upper\" | \"exact\";\n /** Whether equality is allowed when comparing against the bound. */\n readonly inclusive: boolean;\n}\n\n// =============================================================================\n// EXTENSION DEFINITION\n// =============================================================================\n\n/**\n * A complete extension definition bundling types, constraints, annotations,\n * and vocabulary keywords.\n *\n * @example\n * ```typescript\n * const monetaryExtension = defineExtension({\n * extensionId: \"x-stripe/monetary\",\n * types: [\n * defineCustomType({\n * typeName: \"Decimal\",\n * toJsonSchema: (_payload, prefix) => ({\n * type: \"string\",\n * [`${prefix}-decimal`]: true,\n * }),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport interface ExtensionDefinition {\n /** Globally unique extension identifier, e.g., \"x-stripe/monetary\". */\n readonly extensionId: string;\n /** Custom type registrations provided by this extension. */\n readonly types?: readonly CustomTypeRegistration[];\n /** Custom constraint registrations provided by this extension. */\n readonly constraints?: readonly CustomConstraintRegistration[];\n /** Authoring-side TSDoc tag registrations provided by this extension. */\n readonly constraintTags?: readonly ConstraintTagRegistration[];\n /** Custom annotation registrations provided by this extension. */\n readonly annotations?: readonly CustomAnnotationRegistration[];\n /** Vocabulary keyword registrations provided by this extension. */\n readonly vocabularyKeywords?: readonly VocabularyKeywordRegistration[];\n}\n\n// =============================================================================\n// FACTORY FUNCTIONS\n// =============================================================================\n\n/**\n * Defines a complete extension. Currently an identity function that provides\n * type-checking and IDE autocompletion for the definition shape.\n *\n * @param def - The extension definition.\n * @returns The same definition, validated at the type level.\n *\n * @public\n */\nexport function defineExtension(def: ExtensionDefinition): ExtensionDefinition {\n return def;\n}\n\n/**\n * Defines a custom type registration. Currently an identity function that\n * provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom type registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineCustomType(reg: CustomTypeRegistration): CustomTypeRegistration {\n return reg;\n}\n\n/**\n * Defines a custom constraint registration. Currently an identity function\n * that provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom constraint registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration {\n return reg;\n}\n\n/**\n * Defines a custom TSDoc constraint tag registration.\n *\n * @param reg - The custom tag registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineConstraintTag(reg: ConstraintTagRegistration): ConstraintTagRegistration {\n return reg;\n}\n\n/**\n * Defines a custom annotation registration. Currently an identity function\n * that provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom annotation registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineAnnotation(reg: CustomAnnotationRegistration): CustomAnnotationRegistration {\n return reg;\n}\n","/**\n * Type guards for FormSpec form elements.\n *\n * Each guard narrows a {@link FormElement} to a specific field, group, or conditional type.\n */\n\nimport type {\n FormElement,\n AnyField,\n TextField,\n NumberField,\n BooleanField,\n StaticEnumField,\n DynamicEnumField,\n DynamicSchemaField,\n ArrayField,\n ObjectField,\n Group,\n Conditional,\n EnumOptionValue,\n} from \"./types/elements.js\";\n\n/**\n * Narrows a `FormElement` to any field type.\n *\n * @public\n */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/**\n * Narrows a `FormElement` to a text input field.\n *\n * @public\n */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/**\n * Narrows a `FormElement` to a numeric input field.\n *\n * @public\n */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/**\n * Narrows a `FormElement` to a boolean checkbox field.\n *\n * @public\n */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/**\n * Narrows a `FormElement` to a static enum field.\n *\n * @public\n */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/**\n * Narrows a `FormElement` to a dynamic enum field.\n *\n * @public\n */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/**\n * Narrows a `FormElement` to a dynamic schema field.\n *\n * @public\n */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/**\n * Narrows a `FormElement` to an array field.\n *\n * @public\n */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/**\n * Narrows a `FormElement` to an object field.\n *\n * @public\n */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/**\n * Narrows a `FormElement` to a visual group.\n *\n * @public\n */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/**\n * Narrows a `FormElement` to a conditional wrapper.\n *\n * @public\n */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";AAmCO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;AC1BO,IAAM,kCAAkC;AAAA,EAC7C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AACf;AAmCO,SAAS,4BAA4B,SAAyB;AACnE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAaO,SAAS,yBAAyB,SAAmD;AAC1F,SAAO,OAAO,OAAO,iCAAiC,OAAO;AAC/D;;;AC5DO,IAAM,aAAa;;;AC2QnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AAUO,SAAS,oBAAoB,KAA2D;AAC7F,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;AC5TO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAOO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAOO,SAAS,cACd,SACiE;AACjE,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
1
+ {"version":3,"sources":["../src/types/field-state.ts","../src/types/constraint-definitions.ts","../src/types/ir.ts","../src/extensions/index.ts","../src/guards.ts"],"sourcesContent":["import type { Validity } from \"./validity.js\";\n\n/**\n * Represents the runtime state of a single form field.\n *\n * @typeParam T - The value type of the field\n *\n * @public\n */\nexport interface FieldState<T> {\n /** Current value of the field */\n readonly value: T;\n\n /** Whether the field has been modified by the user */\n readonly dirty: boolean;\n\n /** Whether the field has been focused and blurred */\n readonly touched: boolean;\n\n /** Current validity state */\n readonly validity: Validity;\n\n /** Validation error messages, if any */\n readonly errors: readonly string[];\n}\n\n/**\n * Creates initial field state with default values.\n *\n * @typeParam T - The value type of the field\n * @param value - The initial value for the field\n * @returns Initial field state\n *\n * @public\n */\nexport function createInitialFieldState<T>(value: T): FieldState<T> {\n return {\n value,\n dirty: false,\n touched: false,\n validity: \"unknown\",\n errors: [],\n };\n}\n","/**\n * Built-in constraint definitions for FormSpec constraint validation.\n *\n * This is the single source of truth for which constraints FormSpec\n * recognizes. Both `@formspec/build` (schema generation)\n * and `@formspec/eslint-plugin` (lint-time validation) import from here.\n */\n\n/**\n * Built-in constraint names mapped to their expected value type for parsing.\n * Constraints are surface-agnostic — they manifest as both TSDoc tags\n * (e.g., `@minimum 0`) and chain DSL options (e.g., `{ minimum: 0 }`).\n *\n * Keys use camelCase matching JSON Schema property names.\n *\n * @internal\n */\nexport const _BUILTIN_CONSTRAINT_DEFINITIONS = {\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 uniqueItems: \"boolean\",\n pattern: \"string\",\n const: \"json\",\n enumOptions: \"json\",\n} as const;\n\n/**\n * Type of a built-in constraint name.\n *\n * @public\n */\nexport type BuiltinConstraintName =\n | \"minimum\"\n | \"maximum\"\n | \"exclusiveMinimum\"\n | \"exclusiveMaximum\"\n | \"multipleOf\"\n | \"minLength\"\n | \"maxLength\"\n | \"minItems\"\n | \"maxItems\"\n | \"uniqueItems\"\n | \"pattern\"\n | \"const\"\n | \"enumOptions\";\n\n/**\n * Normalizes a constraint tag name from PascalCase to camelCase.\n *\n * Lowercases the first character so that e.g. `\"Minimum\"` becomes `\"minimum\"`.\n * Callers must strip the `@` prefix before calling this function.\n *\n * @example\n * normalizeConstraintTagName(\"Minimum\") // \"minimum\"\n * normalizeConstraintTagName(\"MinLength\") // \"minLength\"\n * normalizeConstraintTagName(\"minimum\") // \"minimum\" (idempotent)\n *\n * @internal\n */\nexport function _normalizeConstraintTagName(tagName: string): string {\n return tagName.charAt(0).toLowerCase() + tagName.slice(1);\n}\n\n/**\n * Type guard: checks whether a tag name is a known built-in constraint.\n *\n * Uses `Object.hasOwn()` rather than `in` to prevent prototype-chain\n * matches on names like `\"toString\"` or `\"constructor\"`.\n *\n * Callers should normalize with {@link _normalizeConstraintTagName} first\n * if the input may be PascalCase.\n *\n * @internal\n */\nexport function _isBuiltinConstraintName(tagName: string): tagName is BuiltinConstraintName {\n return Object.hasOwn(_BUILTIN_CONSTRAINT_DEFINITIONS, tagName);\n}\n","/**\n * Canonical Intermediate Representation (IR) types for FormSpec.\n *\n * The IR is the shared intermediate structure that both authoring surfaces\n * (chain DSL and TSDoc-annotated types) compile to. All downstream operations\n * — JSON Schema generation, UI Schema generation, constraint validation,\n * diagnostics — consume the IR exclusively.\n *\n * All types are plain, serializable objects (no live compiler references).\n *\n * @see {@link https://github.com/stripe/formspec-workspace/blob/main/scratch/design/001-canonical-ir.md}\n */\n\n// =============================================================================\n// IR VERSION\n// =============================================================================\n\n/**\n * The current IR format version. Centralized here so all canonicalizers\n * and consumers reference a single source of truth.\n *\n * @beta\n */\nexport const IR_VERSION = \"0.1.0\" as const;\n\n// =============================================================================\n// UTILITY TYPES\n// =============================================================================\n\n/**\n * A JSON-serializable value. All IR nodes must be representable as JSON.\n *\n * @beta\n */\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | readonly JsonValue[]\n | { readonly [key: string]: JsonValue };\n\n// =============================================================================\n// PROVENANCE\n// =============================================================================\n\n/**\n * Describes the origin of an IR node.\n * Enables diagnostics that point to the source of a contradiction or error.\n *\n * @beta\n */\nexport interface Provenance {\n /** The authoring surface that produced this node. */\n readonly surface: \"tsdoc\" | \"chain-dsl\" | \"extension\" | \"inferred\";\n /** Absolute path to the source file. */\n readonly file: string;\n /** 1-based line number in the source file. */\n readonly line: number;\n /** 0-based column number in the source file. */\n readonly column: number;\n /** Length of the source span in characters (for IDE underline ranges). */\n readonly length?: number;\n /**\n * The specific tag, call, or construct that produced this node.\n * Examples: `@minimum`, `field.number({ min: 0 })`, `optional`\n */\n readonly tagName?: string;\n}\n\n// =============================================================================\n// PATH TARGET\n// =============================================================================\n\n/**\n * A path targeting a sub-field within a complex type.\n * Used by constraints and annotations to target nested properties.\n *\n * @beta\n */\nexport interface PathTarget {\n /**\n * Sequence of property names forming a path from the annotated field's type\n * to the target sub-field.\n * e.g., `[\"value\"]` or `[\"address\", \"zip\"]`\n */\n readonly segments: readonly string[];\n}\n\n// =============================================================================\n// TYPE NODES\n// =============================================================================\n\n/**\n * Discriminated union of all type representations in the IR.\n *\n * @beta\n */\nexport type TypeNode =\n | PrimitiveTypeNode\n | EnumTypeNode\n | ArrayTypeNode\n | ObjectTypeNode\n | RecordTypeNode\n | UnionTypeNode\n | ReferenceTypeNode\n | DynamicTypeNode\n | CustomTypeNode;\n\n/**\n * Primitive types mapping directly to JSON Schema primitives.\n *\n * Note: integer is NOT a primitive kind — integer semantics are expressed\n * via a `multipleOf: 1` constraint on a number type.\n *\n * @beta\n */\nexport interface PrimitiveTypeNode {\n /** Discriminator identifying this node as a primitive type. */\n readonly kind: \"primitive\";\n /** Primitive value family represented by this node. */\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n}\n\n/**\n * A member of a static enum type.\n *\n * @beta\n */\nexport interface EnumMember {\n /** The serialized value stored in data. */\n readonly value: string | number;\n /** Optional per-member display name. */\n readonly displayName?: string;\n}\n\n/**\n * Static enum type with members known at build time.\n *\n * @beta\n */\nexport interface EnumTypeNode {\n /** Discriminator identifying this node as an enum type. */\n readonly kind: \"enum\";\n /** Allowed enum members in declaration order. */\n readonly members: readonly EnumMember[];\n}\n\n/**\n * Array type with a single items type.\n *\n * @beta\n */\nexport interface ArrayTypeNode {\n /** Discriminator identifying this node as an array type. */\n readonly kind: \"array\";\n /** Item type for each array entry. */\n readonly items: TypeNode;\n}\n\n/**\n * A named property within an object type.\n *\n * @beta\n */\nexport interface ObjectProperty {\n /** Property name as it appears in the containing object type. */\n readonly name: string;\n /** Canonical IR type for this property. */\n readonly type: TypeNode;\n /** Whether the property may be omitted from object values. */\n readonly optional: boolean;\n /**\n * Use-site constraints on this property.\n * Distinct from constraints on the property's type — these are\n * use-site constraints (e.g., `@minimum :amount 0` targets the\n * `amount` property of a `MonetaryAmount` field).\n */\n readonly constraints: readonly ConstraintNode[];\n /** Use-site annotations on this property. */\n readonly annotations: readonly AnnotationNode[];\n /** Source location that produced this property entry. */\n readonly provenance: Provenance;\n}\n\n/**\n * Object type with named properties.\n *\n * @beta\n */\nexport interface ObjectTypeNode {\n /** Discriminator identifying this node as an object type. */\n readonly kind: \"object\";\n /**\n * Named properties of this object. Order is preserved from the source\n * declaration for deterministic output.\n */\n readonly properties: readonly ObjectProperty[];\n /**\n * Whether additional properties beyond those listed are permitted.\n * Ordinary static object types default to true under the current spec.\n * Explicitly closed-object modes may still set this to false.\n */\n readonly additionalProperties: boolean;\n}\n\n/**\n * Record (dictionary) type — an object with a string index signature and no\n * named properties. Corresponds to `Record<string, T>` or `{ [k: string]: T }`.\n *\n * Emitted as `{ \"type\": \"object\", \"additionalProperties\": <value schema> }` in\n * JSON Schema per spec 003 §2.5.\n *\n * @beta\n */\nexport interface RecordTypeNode {\n /** Discriminator identifying this node as a record type. */\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/**\n * Union type for non-enum unions. Nullable types are represented as `T | null`.\n *\n * @beta\n */\nexport interface UnionTypeNode {\n /** Discriminator identifying this node as a union type. */\n readonly kind: \"union\";\n /** Member types that participate in the union. */\n readonly members: readonly TypeNode[];\n}\n\n/**\n * Named type reference preserved for `$defs` and `$ref` emission.\n *\n * @beta\n */\nexport interface ReferenceTypeNode {\n /** Discriminator identifying this node as a named reference type. */\n readonly kind: \"reference\";\n /**\n * The fully-qualified name of the referenced type.\n * For TypeScript interfaces/type aliases: `\"<module>#<TypeName>\"`.\n * For built-in types: the primitive kind string.\n */\n readonly name: string;\n /**\n * Type arguments if this is a generic instantiation.\n * e.g., `Array<string>` → `{ name: \"Array\", typeArguments: [PrimitiveTypeNode(\"string\")] }`\n */\n readonly typeArguments: readonly TypeNode[];\n}\n\n/**\n * Dynamic type whose schema is resolved at runtime from a named data source.\n *\n * @beta\n */\nexport interface DynamicTypeNode {\n /** Discriminator identifying this node as a runtime-resolved type. */\n readonly kind: \"dynamic\";\n /** Dynamic schema family resolved for this field. */\n readonly dynamicKind: \"enum\" | \"schema\";\n /** Key identifying the runtime data source or schema provider. */\n readonly sourceKey: string;\n /**\n * For dynamic enums: field names whose current values are passed as\n * parameters to the data source resolver.\n */\n readonly parameterFields: readonly string[];\n}\n\n/**\n * Custom type registered by an extension.\n *\n * @beta\n */\nexport interface CustomTypeNode {\n /** Discriminator identifying this node as an extension-provided type. */\n readonly kind: \"custom\";\n /**\n * The extension-qualified type identifier.\n * Format: `\"<vendor-prefix>/<extension-name>/<type-name>\"`\n * e.g., `\"x-stripe/monetary/MonetaryAmount\"`\n */\n readonly typeId: string;\n /**\n * Opaque payload serialized by the extension that registered this type.\n * Must be JSON-serializable.\n */\n readonly payload: JsonValue;\n}\n\n// =============================================================================\n// CONSTRAINT NODES\n// =============================================================================\n\n/**\n * Discriminated union of all constraint types.\n * Constraints are set-influencing: they narrow the set of valid values.\n *\n * @beta\n */\nexport type ConstraintNode =\n | NumericConstraintNode\n | LengthConstraintNode\n | PatternConstraintNode\n | ArrayCardinalityConstraintNode\n | EnumMemberConstraintNode\n | ConstConstraintNode\n | CustomConstraintNode;\n\n/**\n * Numeric constraints: bounds and multipleOf.\n *\n * `minimum` and `maximum` are inclusive; `exclusiveMinimum` and\n * `exclusiveMaximum` are exclusive bounds (matching JSON Schema 2020-12\n * semantics).\n *\n * Type applicability: may only attach to fields with `PrimitiveTypeNode(\"number\")`\n * or a `ReferenceTypeNode` that resolves to one.\n *\n * @beta\n */\nexport interface NumericConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific numeric constraint represented by this node. */\n readonly constraintKind:\n | \"minimum\"\n | \"maximum\"\n | \"exclusiveMinimum\"\n | \"exclusiveMaximum\"\n | \"multipleOf\";\n /** Numeric value carried by the constraint. */\n readonly value: number;\n /** If present, targets a nested sub-field rather than the field itself. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * String length and array item count constraints.\n *\n * `minLength`/`maxLength` apply to strings; `minItems`/`maxItems` apply to\n * arrays. They share the same node shape because the composition rules are\n * identical.\n *\n * Type applicability: `minLength`/`maxLength` require `PrimitiveTypeNode(\"string\")`;\n * `minItems`/`maxItems` require `ArrayTypeNode`.\n *\n * @beta\n */\nexport interface LengthConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific length or cardinality constraint represented by this node. */\n readonly constraintKind: \"minLength\" | \"maxLength\" | \"minItems\" | \"maxItems\";\n /** Inclusive bound value carried by the constraint. */\n readonly value: number;\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * String pattern constraint (ECMA-262 regex without delimiters).\n *\n * Multiple `pattern` constraints on the same field compose via intersection:\n * all patterns must match simultaneously.\n *\n * Type applicability: requires `PrimitiveTypeNode(\"string\")`.\n *\n * @beta\n */\nexport interface PatternConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific pattern constraint represented by this node. */\n readonly constraintKind: \"pattern\";\n /** ECMA-262 regular expression, without delimiters. */\n readonly pattern: string;\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * Array uniqueness constraint.\n *\n * @beta\n */\nexport interface ArrayCardinalityConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific array-cardinality constraint represented by this node. */\n readonly constraintKind: \"uniqueItems\";\n /** Marker value used for boolean-style array uniqueness constraints. */\n readonly value: true;\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * Enum member subset constraint that only narrows the allowed member set.\n *\n * @beta\n */\nexport interface EnumMemberConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific enum-membership constraint represented by this node. */\n readonly constraintKind: \"allowedMembers\";\n /** Subset of enum member values that remain valid. */\n readonly members: readonly (string | number)[];\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * Literal-value equality constraint.\n *\n * @beta\n */\nexport interface ConstConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific literal-equality constraint represented by this node. */\n readonly constraintKind: \"const\";\n /** JSON-serializable literal value the field must equal. */\n readonly value: JsonValue;\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n/**\n * Extension-registered custom constraint.\n *\n * @beta\n */\nexport interface CustomConstraintNode {\n /** Discriminator identifying this node as a constraint. */\n readonly kind: \"constraint\";\n /** Specific custom-constraint marker used for extension nodes. */\n readonly constraintKind: \"custom\";\n /** Extension-qualified ID: `\"<vendor-prefix>/<extension-name>/<constraint-name>\"` */\n readonly constraintId: string;\n /** JSON-serializable payload defined by the extension. */\n readonly payload: JsonValue;\n /** How this constraint composes with others of the same `constraintId`. */\n readonly compositionRule: \"intersect\" | \"override\";\n /** Nested path target, when the constraint applies below the field root. */\n readonly path?: PathTarget;\n /** Source location that produced this constraint. */\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// ANNOTATION NODES\n// =============================================================================\n\n/**\n * Discriminated union of all annotation types.\n * Annotations are value-influencing: they describe or present a field\n * but do not affect which values are valid.\n *\n * @beta\n */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | RemarksAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\n/**\n * Display-name annotation.\n *\n * @beta\n */\nexport interface DisplayNameAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"displayName\";\n /** Human-readable display label for the field or type. */\n readonly value: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Description annotation.\n *\n * @beta\n */\nexport interface DescriptionAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"description\";\n /** Description text surfaced in generated schemas and tooling. */\n readonly value: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Remarks annotation — programmatic-persona documentation carried via\n * the `x-<vendor>-remarks` JSON Schema extension keyword.\n *\n * Populated from `@remarks` TSDoc tag content. SDK codegen can include\n * this in doc comments; API Documenter renders the source `@remarks`\n * natively in a dedicated Remarks section.\n *\n * @beta\n */\nexport interface RemarksAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"remarks\";\n /** Long-form remarks content carried through canonicalization. */\n readonly value: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Schema format annotation, for example `email`, `date`, or `uri`.\n *\n * @beta\n */\nexport interface FormatAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"format\";\n /** Schema format keyword value to emit downstream. */\n readonly value: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Placeholder annotation.\n *\n * @beta\n */\nexport interface PlaceholderAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"placeholder\";\n /** Placeholder text intended for UI renderers. */\n readonly value: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Default-value annotation.\n *\n * @beta\n */\nexport interface DefaultValueAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"defaultValue\";\n /** Must be JSON-serializable and type-compatible (verified during Validate phase). */\n readonly value: JsonValue;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Deprecated annotation.\n *\n * @beta\n */\nexport interface DeprecatedAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"deprecated\";\n /** Optional deprecation message. */\n readonly message?: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * UI rendering hint — does not affect schema validation.\n * Unlike FormatAnnotationNode, this never emits a JSON Schema `format`.\n *\n * @beta\n */\nexport interface FormatHintAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"formatHint\";\n /** Renderer-specific format identifier: \"textarea\", \"radio\", \"date\", \"color\", etc. */\n readonly format: string;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n/**\n * Extension-registered custom annotation.\n *\n * @beta\n */\nexport interface CustomAnnotationNode {\n /** Discriminator identifying this node as an annotation. */\n readonly kind: \"annotation\";\n /** Specific annotation kind represented by this node. */\n readonly annotationKind: \"custom\";\n /** Extension-qualified ID: `\"<vendor-prefix>/<extension-name>/<annotation-name>\"` */\n readonly annotationId: string;\n /** JSON-serializable extension payload carried by this annotation. */\n readonly value: JsonValue;\n /** Source location that produced this annotation. */\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// FIELD NODE\n// =============================================================================\n\n/**\n * A single form field after canonicalization.\n *\n * @beta\n */\nexport interface FieldNode {\n /** Discriminator identifying this node as a field. */\n readonly kind: \"field\";\n /** The field's key in the data schema. */\n readonly name: string;\n /** The resolved type of this field. */\n readonly type: TypeNode;\n /** Whether this field is required in the data schema. */\n readonly required: boolean;\n /** Set-influencing constraints, after merging. */\n readonly constraints: readonly ConstraintNode[];\n /** Value-influencing annotations, after merging. */\n readonly annotations: readonly AnnotationNode[];\n /** Where this field was declared. */\n readonly provenance: Provenance;\n /**\n * Debug only — ordered list of constraint/annotation nodes that participated\n * in merging, including dominated ones.\n */\n readonly mergeHistory?: readonly {\n readonly node: ConstraintNode | AnnotationNode;\n readonly dominated: boolean;\n }[];\n}\n\n// =============================================================================\n// LAYOUT NODES\n// =============================================================================\n\n/**\n * Union of layout node types.\n *\n * @beta\n */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/**\n * A visual grouping of form elements.\n *\n * @beta\n */\nexport interface GroupLayoutNode {\n /** Discriminator identifying this node as a group layout. */\n readonly kind: \"group\";\n /** Display label associated with the visual group. */\n readonly label: string;\n /** Elements contained in this group — may be fields or nested groups. */\n readonly elements: readonly FormIRElement[];\n /** Source location that produced this layout node. */\n readonly provenance: Provenance;\n}\n\n/**\n * Conditional visibility based on another field's value.\n *\n * @beta\n */\nexport interface ConditionalLayoutNode {\n /** Discriminator identifying this node as a conditional layout. */\n readonly kind: \"conditional\";\n /** The field whose value triggers visibility. */\n readonly fieldName: string;\n /** The value that makes the condition true (SHOW). */\n readonly value: JsonValue;\n /** Elements shown when the condition is met. */\n readonly elements: readonly FormIRElement[];\n /** Source location that produced this layout node. */\n readonly provenance: Provenance;\n}\n\n/**\n * Union of all IR element types.\n *\n * @beta\n */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/**\n * A named type definition stored in the type registry.\n *\n * @beta\n */\nexport interface TypeDefinition {\n /** The fully-qualified reference name (key in the registry). */\n readonly name: string;\n /** The resolved type node. */\n readonly type: TypeNode;\n /** Constraints declared on the named type itself. */\n readonly constraints?: readonly ConstraintNode[];\n /** Root-level value metadata for a named type definition. */\n readonly annotations?: readonly AnnotationNode[];\n /** Where this type was declared. */\n readonly provenance: Provenance;\n}\n\n// =============================================================================\n// FORM IR (TOP-LEVEL)\n// =============================================================================\n\n/**\n * The complete Canonical Intermediate Representation for a form.\n *\n * Output of the Canonicalize phase; input to Validate, Generate (JSON Schema),\n * and Generate (UI Schema) phases.\n *\n * Serializable to JSON — no live compiler objects.\n *\n * @beta\n */\nexport interface FormIR {\n /** Discriminator identifying this document as a top-level FormIR payload. */\n readonly kind: \"form-ir\";\n /**\n * Schema version for the IR format itself.\n * Should equal `IR_VERSION`.\n */\n readonly irVersion: string;\n /** Top-level elements of the form: fields and layout nodes. */\n readonly elements: readonly FormIRElement[];\n /** Root-level annotations derived from the source declaration itself. */\n readonly rootAnnotations?: readonly AnnotationNode[];\n /**\n * Registry of named types referenced by fields in this form.\n * Keys are fully-qualified type names matching `ReferenceTypeNode.name`.\n */\n readonly typeRegistry: Readonly<Record<string, TypeDefinition>>;\n /** Root-level metadata for the form itself. */\n readonly annotations?: readonly AnnotationNode[];\n /** Provenance of the form definition itself. */\n readonly provenance: Provenance;\n}\n","/**\n * Extension API for registering custom types, constraints, annotations,\n * and vocabulary keywords with FormSpec.\n *\n * Extensions allow third-party packages (e.g., \"Decimal\", \"DateOnly\") to\n * plug into the FormSpec pipeline. The types and factory functions defined\n * here are consumed by the FormSpec build pipeline.\n *\n * @packageDocumentation\n */\n\nimport type { BuiltinConstraintName } from \"../types/constraint-definitions.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * A JSON-serializable payload value used by extension registration hooks.\n *\n * @public\n */\nexport type ExtensionPayloadValue =\n | null\n | boolean\n | number\n | string\n | readonly ExtensionPayloadValue[]\n | { readonly [key: string]: ExtensionPayloadValue };\n\n/**\n * Top-level type kinds that extension applicability hooks may inspect.\n *\n * @public\n */\nexport type ExtensionTypeKind =\n | \"primitive\"\n | \"enum\"\n | \"array\"\n | \"object\"\n | \"record\"\n | \"union\"\n | \"reference\"\n | \"dynamic\"\n | \"custom\";\n\n/**\n * A curated type shape exposed to extension applicability hooks.\n *\n * This intentionally exposes only the fields needed to determine tag/type\n * applicability without committing the entire canonical IR as public API.\n *\n * @public\n */\nexport type ExtensionApplicableType =\n | {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n }\n | {\n readonly kind: \"custom\";\n readonly typeId: string;\n readonly payload: ExtensionPayloadValue;\n }\n | { readonly kind: Exclude<ExtensionTypeKind, \"primitive\" | \"custom\"> };\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced by FormSpec's internal custom-type IR nodes and\n * resolved to JSON Schema via `toJsonSchema` during generation.\n *\n * @public\n */\nexport interface CustomTypeRegistration {\n /** The type name, unique within the extension. */\n readonly typeName: string;\n /**\n * Optional TypeScript surface names that should resolve to this custom type\n * during TSDoc/class analysis. Defaults to `typeName` when omitted.\n */\n readonly tsTypeNames?: readonly string[];\n /**\n * Converts the custom type's payload into a JSON Schema fragment.\n *\n * @param payload - The opaque JSON payload stored on the custom type node.\n * @param vendorPrefix - The vendor prefix for extension keywords (e.g., \"x-stripe\").\n * @returns A JSON Schema fragment representing this type.\n */\n readonly toJsonSchema: (\n payload: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n /**\n * Optional broadening of built-in constraint tags so they can apply to this\n * custom type without modifying the core built-in constraint tables.\n */\n readonly builtinConstraintBroadenings?: readonly BuiltinConstraintBroadeningRegistration[];\n}\n\n/**\n * Registration for a custom constraint that maps to JSON Schema keywords.\n *\n * Custom constraints are referenced by FormSpec's internal custom-constraint nodes.\n *\n * @public\n */\nexport interface CustomConstraintRegistration {\n /** The constraint name, unique within the extension. */\n readonly constraintName: string;\n /**\n * How this constraint composes with other constraints of the same kind.\n * - \"intersect\": combine with logical AND (both must hold)\n * - \"override\": last writer wins\n */\n readonly compositionRule: \"intersect\" | \"override\";\n /**\n * TypeNode kinds this constraint is applicable to, or `null` for any type.\n * Used by the validator to emit TYPE_MISMATCH diagnostics.\n */\n readonly applicableTypes: readonly ExtensionApplicableType[\"kind\"][] | null;\n /**\n * Optional precise type predicate used when kind-level applicability is too\n * broad (for example, constraints that apply to integer-like primitives but\n * not strings).\n */\n readonly isApplicableToType?: (type: ExtensionApplicableType) => boolean;\n /**\n * Optional comparator for payloads belonging to the same custom constraint.\n * Return values follow the `Array.prototype.sort()` contract.\n */\n readonly comparePayloads?: (left: ExtensionPayloadValue, right: ExtensionPayloadValue) => number;\n /**\n * Optional semantic family metadata for generic contradiction/broadening\n * handling across ordered constraints.\n */\n readonly semanticRole?: ConstraintSemanticRole;\n /**\n * Converts the custom constraint's payload into JSON Schema keywords.\n *\n * @param payload - The opaque JSON payload stored on the custom constraint node.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (\n payload: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced by FormSpec's internal custom-annotation nodes.\n * They describe or present a field but do not affect which values are valid.\n *\n * @public\n */\nexport interface CustomAnnotationRegistration {\n /** The annotation name, unique within the extension. */\n readonly annotationName: string;\n /**\n * Optionally converts the annotation value into JSON Schema keywords.\n * If omitted, the annotation has no JSON Schema representation (UI-only).\n */\n readonly toJsonSchema?: (\n value: ExtensionPayloadValue,\n vendorPrefix: string\n ) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\n *\n * @public\n */\nexport interface VocabularyKeywordRegistration {\n /** The keyword name (without vendor prefix). */\n readonly keyword: string;\n /** JSON Schema that describes the valid values for this keyword. */\n readonly schema: ExtensionPayloadValue;\n}\n\n/**\n * Declarative authoring-side registration for a custom TSDoc constraint tag.\n *\n * @public\n */\nexport interface ConstraintTagRegistration {\n /** Tag name without the `@` prefix, e.g. `\"maxSigFig\"`. */\n readonly tagName: string;\n /** The custom constraint that this tag should produce. */\n readonly constraintName: string;\n /** Parser from raw TSDoc text to JSON-serializable payload. */\n readonly parseValue: (raw: string) => ExtensionPayloadValue;\n /**\n * Optional precise applicability predicate for the field type being parsed.\n * When omitted, the target custom constraint registration controls type\n * applicability during validation.\n */\n readonly isApplicableToType?: (type: ExtensionApplicableType) => boolean;\n}\n\n/**\n * Registration for mapping a built-in TSDoc tag onto a custom constraint when\n * it is used on a particular custom type.\n *\n * @public\n */\nexport interface BuiltinConstraintBroadeningRegistration {\n /** The built-in tag being broadened, without the `@` prefix. */\n readonly tagName: BuiltinConstraintName;\n /** The custom constraint to emit for this built-in tag. */\n readonly constraintName: string;\n /** Parser from raw TSDoc text to extension payload. */\n readonly parseValue: (raw: string) => ExtensionPayloadValue;\n}\n\n/**\n * Semantic metadata for ordered custom constraints that should participate in\n * the generic contradiction/broadening logic.\n *\n * @public\n */\nexport interface ConstraintSemanticRole {\n /**\n * Logical family identifier shared by related constraints, for example\n * `\"decimal-bound\"` or `\"date-bound\"`.\n */\n readonly family: string;\n /** Whether this constraint acts as a lower or upper bound. */\n readonly bound: \"lower\" | \"upper\" | \"exact\";\n /** Whether equality is allowed when comparing against the bound. */\n readonly inclusive: boolean;\n}\n\n// =============================================================================\n// EXTENSION DEFINITION\n// =============================================================================\n\n/**\n * A complete extension definition bundling types, constraints, annotations,\n * and vocabulary keywords.\n *\n * @example\n * ```typescript\n * const monetaryExtension = defineExtension({\n * extensionId: \"x-stripe/monetary\",\n * types: [\n * defineCustomType({\n * typeName: \"Decimal\",\n * toJsonSchema: (_payload, prefix) => ({\n * type: \"string\",\n * [`${prefix}-decimal`]: true,\n * }),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport interface ExtensionDefinition {\n /** Globally unique extension identifier, e.g., \"x-stripe/monetary\". */\n readonly extensionId: string;\n /** Custom type registrations provided by this extension. */\n readonly types?: readonly CustomTypeRegistration[];\n /** Custom constraint registrations provided by this extension. */\n readonly constraints?: readonly CustomConstraintRegistration[];\n /** Authoring-side TSDoc tag registrations provided by this extension. */\n readonly constraintTags?: readonly ConstraintTagRegistration[];\n /** Custom annotation registrations provided by this extension. */\n readonly annotations?: readonly CustomAnnotationRegistration[];\n /** Vocabulary keyword registrations provided by this extension. */\n readonly vocabularyKeywords?: readonly VocabularyKeywordRegistration[];\n}\n\n// =============================================================================\n// FACTORY FUNCTIONS\n// =============================================================================\n\n/**\n * Defines a complete extension. Currently an identity function that provides\n * type-checking and IDE autocompletion for the definition shape.\n *\n * @param def - The extension definition.\n * @returns The same definition, validated at the type level.\n *\n * @public\n */\nexport function defineExtension(def: ExtensionDefinition): ExtensionDefinition {\n return def;\n}\n\n/**\n * Defines a custom type registration. Currently an identity function that\n * provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom type registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineCustomType(reg: CustomTypeRegistration): CustomTypeRegistration {\n return reg;\n}\n\n/**\n * Defines a custom constraint registration. Currently an identity function\n * that provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom constraint registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration {\n return reg;\n}\n\n/**\n * Defines a custom TSDoc constraint tag registration.\n *\n * @param reg - The custom tag registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineConstraintTag(reg: ConstraintTagRegistration): ConstraintTagRegistration {\n return reg;\n}\n\n/**\n * Defines a custom annotation registration. Currently an identity function\n * that provides type-checking and IDE autocompletion.\n *\n * @param reg - The custom annotation registration.\n * @returns The same registration, validated at the type level.\n *\n * @public\n */\nexport function defineAnnotation(reg: CustomAnnotationRegistration): CustomAnnotationRegistration {\n return reg;\n}\n","/**\n * Type guards for FormSpec form elements.\n *\n * Each guard narrows a {@link FormElement} to a specific field, group, or conditional type.\n */\n\nimport type {\n FormElement,\n AnyField,\n TextField,\n NumberField,\n BooleanField,\n StaticEnumField,\n DynamicEnumField,\n DynamicSchemaField,\n ArrayField,\n ObjectField,\n Group,\n Conditional,\n EnumOptionValue,\n} from \"./types/elements.js\";\n\n/**\n * Narrows a `FormElement` to any field type.\n *\n * @public\n */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/**\n * Narrows a `FormElement` to a text input field.\n *\n * @public\n */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/**\n * Narrows a `FormElement` to a numeric input field.\n *\n * @public\n */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/**\n * Narrows a `FormElement` to a boolean checkbox field.\n *\n * @public\n */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/**\n * Narrows a `FormElement` to a static enum field.\n *\n * @public\n */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/**\n * Narrows a `FormElement` to a dynamic enum field.\n *\n * @public\n */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/**\n * Narrows a `FormElement` to a dynamic schema field.\n *\n * @public\n */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/**\n * Narrows a `FormElement` to an array field.\n *\n * @public\n */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/**\n * Narrows a `FormElement` to an object field.\n *\n * @public\n */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/**\n * Narrows a `FormElement` to a visual group.\n *\n * @public\n */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/**\n * Narrows a `FormElement` to a conditional wrapper.\n *\n * @public\n */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";AAmCO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;AC1BO,IAAM,kCAAkC;AAAA,EAC7C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AACf;AAmCO,SAAS,4BAA4B,SAAyB;AACnE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAaO,SAAS,yBAAyB,SAAmD;AAC1F,SAAO,OAAO,OAAO,iCAAiC,OAAO;AAC/D;;;AC5DO,IAAM,aAAa;;;AC2QnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AAUO,SAAS,oBAAoB,KAA2D;AAC7F,SAAO;AACT;AAWO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;AC5TO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAOO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAOO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAOO,SAAS,cACd,SACiE;AACjE,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
@@ -83,7 +83,9 @@ export interface BooleanField<N extends string> {
83
83
  * @public
84
84
  */
85
85
  export interface EnumOption {
86
+ /** Stored enum value written into submitted data. */
86
87
  readonly id: string;
88
+ /** Human-readable label shown to end users. */
87
89
  readonly label: string;
88
90
  }
89
91
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../../src/types/elements.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../../src/types/elements.ts"],"names":[],"mappings":"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"}
@@ -77,7 +77,9 @@ export type TypeNode = PrimitiveTypeNode | EnumTypeNode | ArrayTypeNode | Object
77
77
  * @beta
78
78
  */
79
79
  export interface PrimitiveTypeNode {
80
+ /** Discriminator identifying this node as a primitive type. */
80
81
  readonly kind: "primitive";
82
+ /** Primitive value family represented by this node. */
81
83
  readonly primitiveKind: "string" | "number" | "integer" | "bigint" | "boolean" | "null";
82
84
  }
83
85
  /**
@@ -97,7 +99,9 @@ export interface EnumMember {
97
99
  * @beta
98
100
  */
99
101
  export interface EnumTypeNode {
102
+ /** Discriminator identifying this node as an enum type. */
100
103
  readonly kind: "enum";
104
+ /** Allowed enum members in declaration order. */
101
105
  readonly members: readonly EnumMember[];
102
106
  }
103
107
  /**
@@ -106,7 +110,9 @@ export interface EnumTypeNode {
106
110
  * @beta
107
111
  */
108
112
  export interface ArrayTypeNode {
113
+ /** Discriminator identifying this node as an array type. */
109
114
  readonly kind: "array";
115
+ /** Item type for each array entry. */
110
116
  readonly items: TypeNode;
111
117
  }
112
118
  /**
@@ -115,8 +121,11 @@ export interface ArrayTypeNode {
115
121
  * @beta
116
122
  */
117
123
  export interface ObjectProperty {
124
+ /** Property name as it appears in the containing object type. */
118
125
  readonly name: string;
126
+ /** Canonical IR type for this property. */
119
127
  readonly type: TypeNode;
128
+ /** Whether the property may be omitted from object values. */
120
129
  readonly optional: boolean;
121
130
  /**
122
131
  * Use-site constraints on this property.
@@ -127,6 +136,7 @@ export interface ObjectProperty {
127
136
  readonly constraints: readonly ConstraintNode[];
128
137
  /** Use-site annotations on this property. */
129
138
  readonly annotations: readonly AnnotationNode[];
139
+ /** Source location that produced this property entry. */
130
140
  readonly provenance: Provenance;
131
141
  }
132
142
  /**
@@ -135,6 +145,7 @@ export interface ObjectProperty {
135
145
  * @beta
136
146
  */
137
147
  export interface ObjectTypeNode {
148
+ /** Discriminator identifying this node as an object type. */
138
149
  readonly kind: "object";
139
150
  /**
140
151
  * Named properties of this object. Order is preserved from the source
@@ -158,6 +169,7 @@ export interface ObjectTypeNode {
158
169
  * @beta
159
170
  */
160
171
  export interface RecordTypeNode {
172
+ /** Discriminator identifying this node as a record type. */
161
173
  readonly kind: "record";
162
174
  /** The type of each value in the dictionary. */
163
175
  readonly valueType: TypeNode;
@@ -168,7 +180,9 @@ export interface RecordTypeNode {
168
180
  * @beta
169
181
  */
170
182
  export interface UnionTypeNode {
183
+ /** Discriminator identifying this node as a union type. */
171
184
  readonly kind: "union";
185
+ /** Member types that participate in the union. */
172
186
  readonly members: readonly TypeNode[];
173
187
  }
174
188
  /**
@@ -177,6 +191,7 @@ export interface UnionTypeNode {
177
191
  * @beta
178
192
  */
179
193
  export interface ReferenceTypeNode {
194
+ /** Discriminator identifying this node as a named reference type. */
180
195
  readonly kind: "reference";
181
196
  /**
182
197
  * The fully-qualified name of the referenced type.
@@ -196,7 +211,9 @@ export interface ReferenceTypeNode {
196
211
  * @beta
197
212
  */
198
213
  export interface DynamicTypeNode {
214
+ /** Discriminator identifying this node as a runtime-resolved type. */
199
215
  readonly kind: "dynamic";
216
+ /** Dynamic schema family resolved for this field. */
200
217
  readonly dynamicKind: "enum" | "schema";
201
218
  /** Key identifying the runtime data source or schema provider. */
202
219
  readonly sourceKey: string;
@@ -212,6 +229,7 @@ export interface DynamicTypeNode {
212
229
  * @beta
213
230
  */
214
231
  export interface CustomTypeNode {
232
+ /** Discriminator identifying this node as an extension-provided type. */
215
233
  readonly kind: "custom";
216
234
  /**
217
235
  * The extension-qualified type identifier.
@@ -245,11 +263,15 @@ export type ConstraintNode = NumericConstraintNode | LengthConstraintNode | Patt
245
263
  * @beta
246
264
  */
247
265
  export interface NumericConstraintNode {
266
+ /** Discriminator identifying this node as a constraint. */
248
267
  readonly kind: "constraint";
268
+ /** Specific numeric constraint represented by this node. */
249
269
  readonly constraintKind: "minimum" | "maximum" | "exclusiveMinimum" | "exclusiveMaximum" | "multipleOf";
270
+ /** Numeric value carried by the constraint. */
250
271
  readonly value: number;
251
272
  /** If present, targets a nested sub-field rather than the field itself. */
252
273
  readonly path?: PathTarget;
274
+ /** Source location that produced this constraint. */
253
275
  readonly provenance: Provenance;
254
276
  }
255
277
  /**
@@ -265,10 +287,15 @@ export interface NumericConstraintNode {
265
287
  * @beta
266
288
  */
267
289
  export interface LengthConstraintNode {
290
+ /** Discriminator identifying this node as a constraint. */
268
291
  readonly kind: "constraint";
292
+ /** Specific length or cardinality constraint represented by this node. */
269
293
  readonly constraintKind: "minLength" | "maxLength" | "minItems" | "maxItems";
294
+ /** Inclusive bound value carried by the constraint. */
270
295
  readonly value: number;
296
+ /** Nested path target, when the constraint applies below the field root. */
271
297
  readonly path?: PathTarget;
298
+ /** Source location that produced this constraint. */
272
299
  readonly provenance: Provenance;
273
300
  }
274
301
  /**
@@ -282,11 +309,15 @@ export interface LengthConstraintNode {
282
309
  * @beta
283
310
  */
284
311
  export interface PatternConstraintNode {
312
+ /** Discriminator identifying this node as a constraint. */
285
313
  readonly kind: "constraint";
314
+ /** Specific pattern constraint represented by this node. */
286
315
  readonly constraintKind: "pattern";
287
316
  /** ECMA-262 regular expression, without delimiters. */
288
317
  readonly pattern: string;
318
+ /** Nested path target, when the constraint applies below the field root. */
289
319
  readonly path?: PathTarget;
320
+ /** Source location that produced this constraint. */
290
321
  readonly provenance: Provenance;
291
322
  }
292
323
  /**
@@ -295,10 +326,15 @@ export interface PatternConstraintNode {
295
326
  * @beta
296
327
  */
297
328
  export interface ArrayCardinalityConstraintNode {
329
+ /** Discriminator identifying this node as a constraint. */
298
330
  readonly kind: "constraint";
331
+ /** Specific array-cardinality constraint represented by this node. */
299
332
  readonly constraintKind: "uniqueItems";
333
+ /** Marker value used for boolean-style array uniqueness constraints. */
300
334
  readonly value: true;
335
+ /** Nested path target, when the constraint applies below the field root. */
301
336
  readonly path?: PathTarget;
337
+ /** Source location that produced this constraint. */
302
338
  readonly provenance: Provenance;
303
339
  }
304
340
  /**
@@ -307,10 +343,15 @@ export interface ArrayCardinalityConstraintNode {
307
343
  * @beta
308
344
  */
309
345
  export interface EnumMemberConstraintNode {
346
+ /** Discriminator identifying this node as a constraint. */
310
347
  readonly kind: "constraint";
348
+ /** Specific enum-membership constraint represented by this node. */
311
349
  readonly constraintKind: "allowedMembers";
350
+ /** Subset of enum member values that remain valid. */
312
351
  readonly members: readonly (string | number)[];
352
+ /** Nested path target, when the constraint applies below the field root. */
313
353
  readonly path?: PathTarget;
354
+ /** Source location that produced this constraint. */
314
355
  readonly provenance: Provenance;
315
356
  }
316
357
  /**
@@ -319,10 +360,15 @@ export interface EnumMemberConstraintNode {
319
360
  * @beta
320
361
  */
321
362
  export interface ConstConstraintNode {
363
+ /** Discriminator identifying this node as a constraint. */
322
364
  readonly kind: "constraint";
365
+ /** Specific literal-equality constraint represented by this node. */
323
366
  readonly constraintKind: "const";
367
+ /** JSON-serializable literal value the field must equal. */
324
368
  readonly value: JsonValue;
369
+ /** Nested path target, when the constraint applies below the field root. */
325
370
  readonly path?: PathTarget;
371
+ /** Source location that produced this constraint. */
326
372
  readonly provenance: Provenance;
327
373
  }
328
374
  /**
@@ -331,7 +377,9 @@ export interface ConstConstraintNode {
331
377
  * @beta
332
378
  */
333
379
  export interface CustomConstraintNode {
380
+ /** Discriminator identifying this node as a constraint. */
334
381
  readonly kind: "constraint";
382
+ /** Specific custom-constraint marker used for extension nodes. */
335
383
  readonly constraintKind: "custom";
336
384
  /** Extension-qualified ID: `"<vendor-prefix>/<extension-name>/<constraint-name>"` */
337
385
  readonly constraintId: string;
@@ -339,7 +387,9 @@ export interface CustomConstraintNode {
339
387
  readonly payload: JsonValue;
340
388
  /** How this constraint composes with others of the same `constraintId`. */
341
389
  readonly compositionRule: "intersect" | "override";
390
+ /** Nested path target, when the constraint applies below the field root. */
342
391
  readonly path?: PathTarget;
392
+ /** Source location that produced this constraint. */
343
393
  readonly provenance: Provenance;
344
394
  }
345
395
  /**
@@ -356,9 +406,13 @@ export type AnnotationNode = DisplayNameAnnotationNode | DescriptionAnnotationNo
356
406
  * @beta
357
407
  */
358
408
  export interface DisplayNameAnnotationNode {
409
+ /** Discriminator identifying this node as an annotation. */
359
410
  readonly kind: "annotation";
411
+ /** Specific annotation kind represented by this node. */
360
412
  readonly annotationKind: "displayName";
413
+ /** Human-readable display label for the field or type. */
361
414
  readonly value: string;
415
+ /** Source location that produced this annotation. */
362
416
  readonly provenance: Provenance;
363
417
  }
364
418
  /**
@@ -367,9 +421,13 @@ export interface DisplayNameAnnotationNode {
367
421
  * @beta
368
422
  */
369
423
  export interface DescriptionAnnotationNode {
424
+ /** Discriminator identifying this node as an annotation. */
370
425
  readonly kind: "annotation";
426
+ /** Specific annotation kind represented by this node. */
371
427
  readonly annotationKind: "description";
428
+ /** Description text surfaced in generated schemas and tooling. */
372
429
  readonly value: string;
430
+ /** Source location that produced this annotation. */
373
431
  readonly provenance: Provenance;
374
432
  }
375
433
  /**
@@ -383,9 +441,13 @@ export interface DescriptionAnnotationNode {
383
441
  * @beta
384
442
  */
385
443
  export interface RemarksAnnotationNode {
444
+ /** Discriminator identifying this node as an annotation. */
386
445
  readonly kind: "annotation";
446
+ /** Specific annotation kind represented by this node. */
387
447
  readonly annotationKind: "remarks";
448
+ /** Long-form remarks content carried through canonicalization. */
388
449
  readonly value: string;
450
+ /** Source location that produced this annotation. */
389
451
  readonly provenance: Provenance;
390
452
  }
391
453
  /**
@@ -394,9 +456,13 @@ export interface RemarksAnnotationNode {
394
456
  * @beta
395
457
  */
396
458
  export interface FormatAnnotationNode {
459
+ /** Discriminator identifying this node as an annotation. */
397
460
  readonly kind: "annotation";
461
+ /** Specific annotation kind represented by this node. */
398
462
  readonly annotationKind: "format";
463
+ /** Schema format keyword value to emit downstream. */
399
464
  readonly value: string;
465
+ /** Source location that produced this annotation. */
400
466
  readonly provenance: Provenance;
401
467
  }
402
468
  /**
@@ -405,9 +471,13 @@ export interface FormatAnnotationNode {
405
471
  * @beta
406
472
  */
407
473
  export interface PlaceholderAnnotationNode {
474
+ /** Discriminator identifying this node as an annotation. */
408
475
  readonly kind: "annotation";
476
+ /** Specific annotation kind represented by this node. */
409
477
  readonly annotationKind: "placeholder";
478
+ /** Placeholder text intended for UI renderers. */
410
479
  readonly value: string;
480
+ /** Source location that produced this annotation. */
411
481
  readonly provenance: Provenance;
412
482
  }
413
483
  /**
@@ -416,10 +486,13 @@ export interface PlaceholderAnnotationNode {
416
486
  * @beta
417
487
  */
418
488
  export interface DefaultValueAnnotationNode {
489
+ /** Discriminator identifying this node as an annotation. */
419
490
  readonly kind: "annotation";
491
+ /** Specific annotation kind represented by this node. */
420
492
  readonly annotationKind: "defaultValue";
421
493
  /** Must be JSON-serializable and type-compatible (verified during Validate phase). */
422
494
  readonly value: JsonValue;
495
+ /** Source location that produced this annotation. */
423
496
  readonly provenance: Provenance;
424
497
  }
425
498
  /**
@@ -428,10 +501,13 @@ export interface DefaultValueAnnotationNode {
428
501
  * @beta
429
502
  */
430
503
  export interface DeprecatedAnnotationNode {
504
+ /** Discriminator identifying this node as an annotation. */
431
505
  readonly kind: "annotation";
506
+ /** Specific annotation kind represented by this node. */
432
507
  readonly annotationKind: "deprecated";
433
508
  /** Optional deprecation message. */
434
509
  readonly message?: string;
510
+ /** Source location that produced this annotation. */
435
511
  readonly provenance: Provenance;
436
512
  }
437
513
  /**
@@ -441,10 +517,13 @@ export interface DeprecatedAnnotationNode {
441
517
  * @beta
442
518
  */
443
519
  export interface FormatHintAnnotationNode {
520
+ /** Discriminator identifying this node as an annotation. */
444
521
  readonly kind: "annotation";
522
+ /** Specific annotation kind represented by this node. */
445
523
  readonly annotationKind: "formatHint";
446
524
  /** Renderer-specific format identifier: "textarea", "radio", "date", "color", etc. */
447
525
  readonly format: string;
526
+ /** Source location that produced this annotation. */
448
527
  readonly provenance: Provenance;
449
528
  }
450
529
  /**
@@ -453,11 +532,15 @@ export interface FormatHintAnnotationNode {
453
532
  * @beta
454
533
  */
455
534
  export interface CustomAnnotationNode {
535
+ /** Discriminator identifying this node as an annotation. */
456
536
  readonly kind: "annotation";
537
+ /** Specific annotation kind represented by this node. */
457
538
  readonly annotationKind: "custom";
458
539
  /** Extension-qualified ID: `"<vendor-prefix>/<extension-name>/<annotation-name>"` */
459
540
  readonly annotationId: string;
541
+ /** JSON-serializable extension payload carried by this annotation. */
460
542
  readonly value: JsonValue;
543
+ /** Source location that produced this annotation. */
461
544
  readonly provenance: Provenance;
462
545
  }
463
546
  /**
@@ -466,6 +549,7 @@ export interface CustomAnnotationNode {
466
549
  * @beta
467
550
  */
468
551
  export interface FieldNode {
552
+ /** Discriminator identifying this node as a field. */
469
553
  readonly kind: "field";
470
554
  /** The field's key in the data schema. */
471
555
  readonly name: string;
@@ -500,10 +584,13 @@ export type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;
500
584
  * @beta
501
585
  */
502
586
  export interface GroupLayoutNode {
587
+ /** Discriminator identifying this node as a group layout. */
503
588
  readonly kind: "group";
589
+ /** Display label associated with the visual group. */
504
590
  readonly label: string;
505
591
  /** Elements contained in this group — may be fields or nested groups. */
506
592
  readonly elements: readonly FormIRElement[];
593
+ /** Source location that produced this layout node. */
507
594
  readonly provenance: Provenance;
508
595
  }
509
596
  /**
@@ -512,6 +599,7 @@ export interface GroupLayoutNode {
512
599
  * @beta
513
600
  */
514
601
  export interface ConditionalLayoutNode {
602
+ /** Discriminator identifying this node as a conditional layout. */
515
603
  readonly kind: "conditional";
516
604
  /** The field whose value triggers visibility. */
517
605
  readonly fieldName: string;
@@ -519,6 +607,7 @@ export interface ConditionalLayoutNode {
519
607
  readonly value: JsonValue;
520
608
  /** Elements shown when the condition is met. */
521
609
  readonly elements: readonly FormIRElement[];
610
+ /** Source location that produced this layout node. */
522
611
  readonly provenance: Provenance;
523
612
  }
524
613
  /**
@@ -555,6 +644,7 @@ export interface TypeDefinition {
555
644
  * @beta
556
645
  */
557
646
  export interface FormIR {
647
+ /** Discriminator identifying this document as a top-level FormIR payload. */
558
648
  readonly kind: "form-ir";
559
649
  /**
560
650
  * Schema version for the IR format itself.