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

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.
@@ -0,0 +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":[]}
@@ -12,9 +12,9 @@
12
12
  *
13
13
  * Keys use camelCase matching JSON Schema property names.
14
14
  *
15
- * @public
15
+ * @internal
16
16
  */
17
- export declare const BUILTIN_CONSTRAINT_DEFINITIONS: {
17
+ export declare const _BUILTIN_CONSTRAINT_DEFINITIONS: {
18
18
  readonly minimum: "number";
19
19
  readonly maximum: "number";
20
20
  readonly exclusiveMinimum: "number";
@@ -34,7 +34,7 @@ export declare const BUILTIN_CONSTRAINT_DEFINITIONS: {
34
34
  *
35
35
  * @public
36
36
  */
37
- export type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;
37
+ export type BuiltinConstraintName = "minimum" | "maximum" | "exclusiveMinimum" | "exclusiveMaximum" | "multipleOf" | "minLength" | "maxLength" | "minItems" | "maxItems" | "uniqueItems" | "pattern" | "const" | "enumOptions";
38
38
  /**
39
39
  * Normalizes a constraint tag name from PascalCase to camelCase.
40
40
  *
@@ -46,19 +46,19 @@ export type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;
46
46
  * normalizeConstraintTagName("MinLength") // "minLength"
47
47
  * normalizeConstraintTagName("minimum") // "minimum" (idempotent)
48
48
  *
49
- * @public
49
+ * @internal
50
50
  */
51
- export declare function normalizeConstraintTagName(tagName: string): string;
51
+ export declare function _normalizeConstraintTagName(tagName: string): string;
52
52
  /**
53
53
  * Type guard: checks whether a tag name is a known built-in constraint.
54
54
  *
55
55
  * Uses `Object.hasOwn()` rather than `in` to prevent prototype-chain
56
56
  * matches on names like `"toString"` or `"constructor"`.
57
57
  *
58
- * Callers should normalize with {@link normalizeConstraintTagName} first
58
+ * Callers should normalize with {@link _normalizeConstraintTagName} first
59
59
  * if the input may be PascalCase.
60
60
  *
61
- * @public
61
+ * @internal
62
62
  */
63
- export declare function isBuiltinConstraintName(tagName: string): tagName is BuiltinConstraintName;
63
+ export declare function _isBuiltinConstraintName(tagName: string): tagName is BuiltinConstraintName;
64
64
  //# sourceMappingURL=constraint-definitions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constraint-definitions.d.ts","sourceRoot":"","sources":["../../src/types/constraint-definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;CAcjC,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,8BAA8B,CAAC;AAEhF;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,qBAAqB,CAEzF"}
1
+ {"version":3,"file":"constraint-definitions.d.ts","sourceRoot":"","sources":["../../src/types/constraint-definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;CAclC,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,SAAS,GACT,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,WAAW,GACX,WAAW,GACX,UAAU,GACV,UAAU,GACV,aAAa,GACb,SAAS,GACT,OAAO,GACP,aAAa,CAAC;AAElB;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,qBAAqB,CAE1F"}
@@ -5,8 +5,8 @@ export type { FormState } from "./form-state.js";
5
5
  export type { DataSourceRegistry, DataSourceOption, FetchOptionsResponse, DataSourceValueType, } from "./data-source.js";
6
6
  export type { TextField, NumberField, BooleanField, EnumOption, EnumOptionValue, StaticEnumField, DynamicEnumField, DynamicSchemaField, ArrayField, ObjectField, AnyField, Group, Conditional, FormElement, FormSpec, } from "./elements.js";
7
7
  export type { EqualsPredicate, Predicate } from "./predicate.js";
8
- export { BUILTIN_CONSTRAINT_DEFINITIONS, normalizeConstraintTagName, isBuiltinConstraintName, } from "./constraint-definitions.js";
9
8
  export type { BuiltinConstraintName } from "./constraint-definitions.js";
9
+ export { _BUILTIN_CONSTRAINT_DEFINITIONS, _normalizeConstraintTagName, _isBuiltinConstraintName, } from "./constraint-definitions.js";
10
10
  export { IR_VERSION } from "./ir.js";
11
11
  export type { JsonValue, Provenance, PathTarget, TypeNode, PrimitiveTypeNode, EnumMember, EnumTypeNode, ArrayTypeNode, ObjectProperty, ObjectTypeNode, RecordTypeNode, UnionTypeNode, ReferenceTypeNode, DynamicTypeNode, CustomTypeNode, ConstraintNode, NumericConstraintNode, LengthConstraintNode, PatternConstraintNode, ArrayCardinalityConstraintNode, EnumMemberConstraintNode, ConstConstraintNode, CustomConstraintNode, AnnotationNode, DisplayNameAnnotationNode, DescriptionAnnotationNode, RemarksAnnotationNode, FormatAnnotationNode, PlaceholderAnnotationNode, DefaultValueAnnotationNode, DeprecatedAnnotationNode, FormatHintAnnotationNode, CustomAnnotationNode, FieldNode, LayoutNode, GroupLayoutNode, ConditionalLayoutNode, FormIRElement, TypeDefinition, FormIR, } from "./ir.js";
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,GACT,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,8BAA8B,EAC9B,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,SAAS,EACT,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,MAAM,GACP,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,GACT,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,8BAA8B,EAC9B,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,SAAS,EACT,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,MAAM,GACP,MAAM,SAAS,CAAC"}
@@ -14,13 +14,13 @@
14
14
  * The current IR format version. Centralized here so all canonicalizers
15
15
  * and consumers reference a single source of truth.
16
16
  *
17
- * @public
17
+ * @beta
18
18
  */
19
19
  export declare const IR_VERSION: "0.1.0";
20
20
  /**
21
21
  * A JSON-serializable value. All IR nodes must be representable as JSON.
22
22
  *
23
- * @public
23
+ * @beta
24
24
  */
25
25
  export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
26
26
  readonly [key: string]: JsonValue;
@@ -29,7 +29,7 @@ export type JsonValue = null | boolean | number | string | readonly JsonValue[]
29
29
  * Describes the origin of an IR node.
30
30
  * Enables diagnostics that point to the source of a contradiction or error.
31
31
  *
32
- * @public
32
+ * @beta
33
33
  */
34
34
  export interface Provenance {
35
35
  /** The authoring surface that produced this node. */
@@ -52,7 +52,7 @@ export interface Provenance {
52
52
  * A path targeting a sub-field within a complex type.
53
53
  * Used by constraints and annotations to target nested properties.
54
54
  *
55
- * @public
55
+ * @beta
56
56
  */
57
57
  export interface PathTarget {
58
58
  /**
@@ -65,7 +65,7 @@ export interface PathTarget {
65
65
  /**
66
66
  * Discriminated union of all type representations in the IR.
67
67
  *
68
- * @public
68
+ * @beta
69
69
  */
70
70
  export type TypeNode = PrimitiveTypeNode | EnumTypeNode | ArrayTypeNode | ObjectTypeNode | RecordTypeNode | UnionTypeNode | ReferenceTypeNode | DynamicTypeNode | CustomTypeNode;
71
71
  /**
@@ -74,7 +74,7 @@ export type TypeNode = PrimitiveTypeNode | EnumTypeNode | ArrayTypeNode | Object
74
74
  * Note: integer is NOT a primitive kind — integer semantics are expressed
75
75
  * via a `multipleOf: 1` constraint on a number type.
76
76
  *
77
- * @public
77
+ * @beta
78
78
  */
79
79
  export interface PrimitiveTypeNode {
80
80
  readonly kind: "primitive";
@@ -83,7 +83,7 @@ export interface PrimitiveTypeNode {
83
83
  /**
84
84
  * A member of a static enum type.
85
85
  *
86
- * @public
86
+ * @beta
87
87
  */
88
88
  export interface EnumMember {
89
89
  /** The serialized value stored in data. */
@@ -94,7 +94,7 @@ export interface EnumMember {
94
94
  /**
95
95
  * Static enum type with members known at build time.
96
96
  *
97
- * @public
97
+ * @beta
98
98
  */
99
99
  export interface EnumTypeNode {
100
100
  readonly kind: "enum";
@@ -103,7 +103,7 @@ export interface EnumTypeNode {
103
103
  /**
104
104
  * Array type with a single items type.
105
105
  *
106
- * @public
106
+ * @beta
107
107
  */
108
108
  export interface ArrayTypeNode {
109
109
  readonly kind: "array";
@@ -112,7 +112,7 @@ export interface ArrayTypeNode {
112
112
  /**
113
113
  * A named property within an object type.
114
114
  *
115
- * @public
115
+ * @beta
116
116
  */
117
117
  export interface ObjectProperty {
118
118
  readonly name: string;
@@ -132,7 +132,7 @@ export interface ObjectProperty {
132
132
  /**
133
133
  * Object type with named properties.
134
134
  *
135
- * @public
135
+ * @beta
136
136
  */
137
137
  export interface ObjectTypeNode {
138
138
  readonly kind: "object";
@@ -155,7 +155,7 @@ export interface ObjectTypeNode {
155
155
  * Emitted as `{ "type": "object", "additionalProperties": <value schema> }` in
156
156
  * JSON Schema per spec 003 §2.5.
157
157
  *
158
- * @public
158
+ * @beta
159
159
  */
160
160
  export interface RecordTypeNode {
161
161
  readonly kind: "record";
@@ -165,7 +165,7 @@ export interface RecordTypeNode {
165
165
  /**
166
166
  * Union type for non-enum unions. Nullable types are represented as `T | null`.
167
167
  *
168
- * @public
168
+ * @beta
169
169
  */
170
170
  export interface UnionTypeNode {
171
171
  readonly kind: "union";
@@ -174,7 +174,7 @@ export interface UnionTypeNode {
174
174
  /**
175
175
  * Named type reference preserved for `$defs` and `$ref` emission.
176
176
  *
177
- * @public
177
+ * @beta
178
178
  */
179
179
  export interface ReferenceTypeNode {
180
180
  readonly kind: "reference";
@@ -193,7 +193,7 @@ export interface ReferenceTypeNode {
193
193
  /**
194
194
  * Dynamic type whose schema is resolved at runtime from a named data source.
195
195
  *
196
- * @public
196
+ * @beta
197
197
  */
198
198
  export interface DynamicTypeNode {
199
199
  readonly kind: "dynamic";
@@ -209,7 +209,7 @@ export interface DynamicTypeNode {
209
209
  /**
210
210
  * Custom type registered by an extension.
211
211
  *
212
- * @public
212
+ * @beta
213
213
  */
214
214
  export interface CustomTypeNode {
215
215
  readonly kind: "custom";
@@ -229,7 +229,7 @@ export interface CustomTypeNode {
229
229
  * Discriminated union of all constraint types.
230
230
  * Constraints are set-influencing: they narrow the set of valid values.
231
231
  *
232
- * @public
232
+ * @beta
233
233
  */
234
234
  export type ConstraintNode = NumericConstraintNode | LengthConstraintNode | PatternConstraintNode | ArrayCardinalityConstraintNode | EnumMemberConstraintNode | ConstConstraintNode | CustomConstraintNode;
235
235
  /**
@@ -242,7 +242,7 @@ export type ConstraintNode = NumericConstraintNode | LengthConstraintNode | Patt
242
242
  * Type applicability: may only attach to fields with `PrimitiveTypeNode("number")`
243
243
  * or a `ReferenceTypeNode` that resolves to one.
244
244
  *
245
- * @public
245
+ * @beta
246
246
  */
247
247
  export interface NumericConstraintNode {
248
248
  readonly kind: "constraint";
@@ -262,7 +262,7 @@ export interface NumericConstraintNode {
262
262
  * Type applicability: `minLength`/`maxLength` require `PrimitiveTypeNode("string")`;
263
263
  * `minItems`/`maxItems` require `ArrayTypeNode`.
264
264
  *
265
- * @public
265
+ * @beta
266
266
  */
267
267
  export interface LengthConstraintNode {
268
268
  readonly kind: "constraint";
@@ -279,7 +279,7 @@ export interface LengthConstraintNode {
279
279
  *
280
280
  * Type applicability: requires `PrimitiveTypeNode("string")`.
281
281
  *
282
- * @public
282
+ * @beta
283
283
  */
284
284
  export interface PatternConstraintNode {
285
285
  readonly kind: "constraint";
@@ -292,7 +292,7 @@ export interface PatternConstraintNode {
292
292
  /**
293
293
  * Array uniqueness constraint.
294
294
  *
295
- * @public
295
+ * @beta
296
296
  */
297
297
  export interface ArrayCardinalityConstraintNode {
298
298
  readonly kind: "constraint";
@@ -304,7 +304,7 @@ export interface ArrayCardinalityConstraintNode {
304
304
  /**
305
305
  * Enum member subset constraint that only narrows the allowed member set.
306
306
  *
307
- * @public
307
+ * @beta
308
308
  */
309
309
  export interface EnumMemberConstraintNode {
310
310
  readonly kind: "constraint";
@@ -316,7 +316,7 @@ export interface EnumMemberConstraintNode {
316
316
  /**
317
317
  * Literal-value equality constraint.
318
318
  *
319
- * @public
319
+ * @beta
320
320
  */
321
321
  export interface ConstConstraintNode {
322
322
  readonly kind: "constraint";
@@ -328,7 +328,7 @@ export interface ConstConstraintNode {
328
328
  /**
329
329
  * Extension-registered custom constraint.
330
330
  *
331
- * @public
331
+ * @beta
332
332
  */
333
333
  export interface CustomConstraintNode {
334
334
  readonly kind: "constraint";
@@ -347,13 +347,13 @@ export interface CustomConstraintNode {
347
347
  * Annotations are value-influencing: they describe or present a field
348
348
  * but do not affect which values are valid.
349
349
  *
350
- * @public
350
+ * @beta
351
351
  */
352
352
  export type AnnotationNode = DisplayNameAnnotationNode | DescriptionAnnotationNode | RemarksAnnotationNode | FormatAnnotationNode | PlaceholderAnnotationNode | DefaultValueAnnotationNode | DeprecatedAnnotationNode | FormatHintAnnotationNode | CustomAnnotationNode;
353
353
  /**
354
354
  * Display-name annotation.
355
355
  *
356
- * @public
356
+ * @beta
357
357
  */
358
358
  export interface DisplayNameAnnotationNode {
359
359
  readonly kind: "annotation";
@@ -364,7 +364,7 @@ export interface DisplayNameAnnotationNode {
364
364
  /**
365
365
  * Description annotation.
366
366
  *
367
- * @public
367
+ * @beta
368
368
  */
369
369
  export interface DescriptionAnnotationNode {
370
370
  readonly kind: "annotation";
@@ -380,7 +380,7 @@ export interface DescriptionAnnotationNode {
380
380
  * this in doc comments; API Documenter renders the source `@remarks`
381
381
  * natively in a dedicated Remarks section.
382
382
  *
383
- * @public
383
+ * @beta
384
384
  */
385
385
  export interface RemarksAnnotationNode {
386
386
  readonly kind: "annotation";
@@ -391,7 +391,7 @@ export interface RemarksAnnotationNode {
391
391
  /**
392
392
  * Schema format annotation, for example `email`, `date`, or `uri`.
393
393
  *
394
- * @public
394
+ * @beta
395
395
  */
396
396
  export interface FormatAnnotationNode {
397
397
  readonly kind: "annotation";
@@ -402,7 +402,7 @@ export interface FormatAnnotationNode {
402
402
  /**
403
403
  * Placeholder annotation.
404
404
  *
405
- * @public
405
+ * @beta
406
406
  */
407
407
  export interface PlaceholderAnnotationNode {
408
408
  readonly kind: "annotation";
@@ -413,7 +413,7 @@ export interface PlaceholderAnnotationNode {
413
413
  /**
414
414
  * Default-value annotation.
415
415
  *
416
- * @public
416
+ * @beta
417
417
  */
418
418
  export interface DefaultValueAnnotationNode {
419
419
  readonly kind: "annotation";
@@ -425,7 +425,7 @@ export interface DefaultValueAnnotationNode {
425
425
  /**
426
426
  * Deprecated annotation.
427
427
  *
428
- * @public
428
+ * @beta
429
429
  */
430
430
  export interface DeprecatedAnnotationNode {
431
431
  readonly kind: "annotation";
@@ -438,7 +438,7 @@ export interface DeprecatedAnnotationNode {
438
438
  * UI rendering hint — does not affect schema validation.
439
439
  * Unlike FormatAnnotationNode, this never emits a JSON Schema `format`.
440
440
  *
441
- * @public
441
+ * @beta
442
442
  */
443
443
  export interface FormatHintAnnotationNode {
444
444
  readonly kind: "annotation";
@@ -450,7 +450,7 @@ export interface FormatHintAnnotationNode {
450
450
  /**
451
451
  * Extension-registered custom annotation.
452
452
  *
453
- * @public
453
+ * @beta
454
454
  */
455
455
  export interface CustomAnnotationNode {
456
456
  readonly kind: "annotation";
@@ -463,7 +463,7 @@ export interface CustomAnnotationNode {
463
463
  /**
464
464
  * A single form field after canonicalization.
465
465
  *
466
- * @public
466
+ * @beta
467
467
  */
468
468
  export interface FieldNode {
469
469
  readonly kind: "field";
@@ -491,13 +491,13 @@ export interface FieldNode {
491
491
  /**
492
492
  * Union of layout node types.
493
493
  *
494
- * @public
494
+ * @beta
495
495
  */
496
496
  export type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;
497
497
  /**
498
498
  * A visual grouping of form elements.
499
499
  *
500
- * @public
500
+ * @beta
501
501
  */
502
502
  export interface GroupLayoutNode {
503
503
  readonly kind: "group";
@@ -509,7 +509,7 @@ export interface GroupLayoutNode {
509
509
  /**
510
510
  * Conditional visibility based on another field's value.
511
511
  *
512
- * @public
512
+ * @beta
513
513
  */
514
514
  export interface ConditionalLayoutNode {
515
515
  readonly kind: "conditional";
@@ -524,13 +524,13 @@ export interface ConditionalLayoutNode {
524
524
  /**
525
525
  * Union of all IR element types.
526
526
  *
527
- * @public
527
+ * @beta
528
528
  */
529
529
  export type FormIRElement = FieldNode | LayoutNode;
530
530
  /**
531
531
  * A named type definition stored in the type registry.
532
532
  *
533
- * @public
533
+ * @beta
534
534
  */
535
535
  export interface TypeDefinition {
536
536
  /** The fully-qualified reference name (key in the registry). */
@@ -552,7 +552,7 @@ export interface TypeDefinition {
552
552
  *
553
553
  * Serializable to JSON — no live compiler objects.
554
554
  *
555
- * @public
555
+ * @beta
556
556
  */
557
557
  export interface FormIR {
558
558
  readonly kind: "form-ir";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formspec/core",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "Core utilities for formspec",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -11,6 +11,11 @@
11
11
  "types": "./dist/core.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
+ },
15
+ "./internals": {
16
+ "types": "./dist/internals.d.ts",
17
+ "import": "./dist/internals.js",
18
+ "require": "./dist/internals.cjs"
14
19
  }
15
20
  },
16
21
  "files": [
@@ -30,13 +35,13 @@
30
35
  "keywords": [],
31
36
  "license": "UNLICENSED",
32
37
  "scripts": {
33
- "build": "tsup && tsc --emitDeclarationOnly && api-extractor run --local",
38
+ "build": "tsup && tsc --emitDeclarationOnly && pnpm run api-extractor:local",
34
39
  "clean": "rm -rf dist temp",
35
40
  "typecheck": "tsc --noEmit",
36
41
  "test": "vitest run && tsd",
37
42
  "test:types": "tsd",
38
- "api-extractor": "api-extractor run",
39
- "api-extractor:local": "api-extractor run --local",
40
- "api-documenter": "api-documenter markdown -i temp -o docs"
43
+ "api-extractor": "api-extractor run && node ../../scripts/normalize-generated-markdown.mjs api-report",
44
+ "api-extractor:local": "api-extractor run --local && node ../../scripts/normalize-generated-markdown.mjs api-report",
45
+ "api-documenter": "api-documenter markdown -i temp -o docs && node ../../scripts/normalize-generated-markdown.mjs docs"
41
46
  }
42
47
  }