@formspec/core 0.1.0-alpha.16 → 0.1.0-alpha.19

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.
package/README.md CHANGED
@@ -1,160 +1,84 @@
1
1
  # @formspec/core
2
2
 
3
- Core type definitions for the FormSpec library.
3
+ Shared types, canonical IR nodes, and extension registration APIs for FormSpec.
4
4
 
5
- ## Installation
5
+ ## Install
6
6
 
7
7
  ```bash
8
- npm install @formspec/core
9
- # or
10
8
  pnpm add @formspec/core
11
9
  ```
12
10
 
13
- > **Note:** Most users should install the `formspec` umbrella package instead, which re-exports everything from this package.
11
+ Most app code should prefer `formspec` unless you are building tooling, extensions, or lower-level integrations.
14
12
 
15
- ## Requirements
13
+ ## Main Responsibilities
16
14
 
17
- This package is ESM-only and requires:
15
+ - Form element and state types
16
+ - Canonical IR types used by the build pipeline
17
+ - Constraint-definition metadata
18
+ - Extension registration helpers for custom types, constraints, and annotations
19
+ - Shared type guards
18
20
 
19
- ```json
20
- // package.json
21
- {
22
- "type": "module"
23
- }
24
- ```
21
+ ## Example
25
22
 
26
- ```json
27
- // tsconfig.json
28
- {
29
- "compilerOptions": {
30
- "module": "NodeNext",
31
- "moduleResolution": "NodeNext"
32
- }
33
- }
34
- ```
23
+ ```ts
24
+ import type { FormElement, FormIR } from "@formspec/core";
25
+ import { defineConstraint, defineCustomType, defineExtension } from "@formspec/core";
35
26
 
36
- ## Overview
37
-
38
- This package provides the foundational types used throughout the FormSpec ecosystem:
39
-
40
- - **Form element types**: `TextField`, `NumberField`, `BooleanField`, `StaticEnumField`, `DynamicEnumField`, `ArrayField`, `ObjectField`
41
- - **Structural types**: `Group`, `Conditional`, `FormElement`, `FormSpec`
42
- - **State types**: `FieldState`, `FormState`, `Validity`
43
- - **Data source types**: `DataSourceRegistry`, `DataSourceOption`, `FetchOptionsResponse`
44
- - **Predicate types**: `EqualsPredicate`, `Predicate`
45
- - **IR types**: `FormIR`, `FormIRElement`, `FieldNode`, `LayoutNode`, `TypeNode`, `ConstraintNode`, `AnnotationNode`, `Provenance`, `IR_VERSION`
46
- - **Extension API**: `defineExtension`, `defineConstraint`, `defineAnnotation`, `defineCustomType`
47
-
48
- ## Usage
49
-
50
- ```typescript
51
- import type {
52
- FormSpec,
53
- FormElement,
54
- TextField,
55
- NumberField,
56
- AnyField,
57
- Group,
58
- Conditional,
59
- } from "@formspec/core";
60
-
61
- // Type guard for field elements
62
- function isField(element: FormElement): element is AnyField {
27
+ function isFieldElement(element: FormElement): boolean {
63
28
  return element._type === "field";
64
29
  }
65
30
 
66
- // Process form elements
67
- function processForm(form: FormSpec<readonly FormElement[]>) {
68
- for (const element of form.elements) {
69
- if (isField(element)) {
70
- console.log(`Field: ${element.name} (${element._field})`);
71
- } else if (element._type === "group") {
72
- console.log(`Group: ${element.label}`);
73
- }
74
- }
75
- }
76
- ```
77
-
78
- ## Type Reference
79
-
80
- ### Field Types
81
-
82
- | Type | Description |
83
- | -------------------- | ------------------------------------------- |
84
- | `TextField` | Text input field |
85
- | `NumberField` | Numeric input field |
86
- | `BooleanField` | Boolean/checkbox field |
87
- | `StaticEnumField` | Dropdown with static options |
88
- | `DynamicEnumField` | Dropdown with dynamic options from resolver |
89
- | `DynamicSchemaField` | Field with dynamic schema from resolver |
90
- | `ArrayField` | Array of nested elements |
91
- | `ObjectField` | Nested object with child fields |
92
- | `AnyField` | Union of all field types |
31
+ const decimalType = defineCustomType({
32
+ typeName: "Decimal",
33
+ tsTypeNames: ["Decimal"],
34
+ toJsonSchema: (_payload, vendorPrefix) => ({
35
+ type: "string",
36
+ [`${vendorPrefix}-decimal`]: true,
37
+ }),
38
+ });
93
39
 
94
- ### Structural Types
40
+ const extension = defineExtension({
41
+ extensionId: "x-example/decimal",
42
+ types: [decimalType],
43
+ constraints: [],
44
+ annotations: [],
45
+ });
46
+ ```
95
47
 
96
- | Type | Description |
97
- | ------------- | ------------------------------------------- |
98
- | `Group` | Groups related fields with a label |
99
- | `Conditional` | Shows fields based on predicate |
100
- | `FormElement` | Union of `AnyField`, `Group`, `Conditional` |
101
- | `FormSpec<E>` | Complete form specification |
48
+ ## Key Exports
102
49
 
103
- ### State Types
50
+ ### Form Types
104
51
 
105
- | Type | Description |
106
- | --------------- | ----------------------------------- |
107
- | `Validity` | `"valid"`, `"invalid"`, `"unknown"` |
108
- | `FieldState<T>` | Runtime state of a single field |
109
- | `FormState<S>` | Runtime state of entire form |
52
+ - `FormSpec`
53
+ - `FormElement`
54
+ - `AnyField`
55
+ - `Group`
56
+ - `Conditional`
57
+ - `FieldState`
58
+ - `FormState`
110
59
 
111
60
  ### IR Types
112
61
 
113
- | Type | Description |
114
- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
- | `FormIR` | Root IR node — contains elements, type registry, IR version |
116
- | `FormIRElement` | Union of `FieldNode` and `LayoutNode` |
117
- | `FieldNode` | IR field with name, type, constraints, annotations |
118
- | `LayoutNode` | Union of `GroupLayoutNode` and `ConditionalLayoutNode` |
119
- | `TypeNode` | Union: `PrimitiveTypeNode`, `EnumTypeNode`, `ArrayTypeNode`, `ObjectTypeNode`, `UnionTypeNode`, `ReferenceTypeNode`, `DynamicTypeNode`, `CustomTypeNode` |
120
- | `ConstraintNode` | Union: `NumericConstraintNode`, `LengthConstraintNode`, `PatternConstraintNode`, `ArrayCardinalityConstraintNode`, `EnumMemberConstraintNode`, `CustomConstraintNode` |
121
- | `AnnotationNode` | Union: `DisplayNameAnnotationNode`, `DescriptionAnnotationNode`, `PlaceholderAnnotationNode`, `DefaultValueAnnotationNode`, `DeprecatedAnnotationNode`, `FormatHintAnnotationNode`, `CustomAnnotationNode` |
122
- | `Provenance` | Source location tracking — file, line, column, surface |
123
- | `IR_VERSION` | Current IR version (`"0.1.0"`) |
62
+ - `FormIR`
63
+ - `FieldNode`
64
+ - `LayoutNode`
65
+ - `TypeNode`
66
+ - `ConstraintNode`
67
+ - `AnnotationNode`
68
+ - `Provenance`
124
69
 
125
70
  ### Extension API
126
71
 
127
- FormSpec's type system is extensible via registration functions:
128
-
129
- | Function | Description |
130
- | ----------------------- | ------------------------------------------------------------------------------------------- |
131
- | `defineExtension(def)` | Register a complete extension with constraints, annotations, types, and vocabulary keywords |
132
- | `defineConstraint(reg)` | Register a custom constraint (e.g., `multipleOf`, `uniqueItems`) |
133
- | `defineAnnotation(reg)` | Register a custom annotation (e.g., tooltip, help URL) |
134
- | `defineCustomType(reg)` | Register a custom type node for JSON Schema generation |
135
-
136
- ```typescript
137
- import { defineExtension, defineConstraint, defineAnnotation } from "@formspec/core";
138
-
139
- // Register a complete extension
140
- const myExtension = defineExtension({
141
- extensionId: "my-ext",
142
- constraints: [
143
- {
144
- constraintName: "Precision",
145
- applicableTypes: ["primitive"],
146
- compositionRule: "override",
147
- toJsonSchema: (payload, vendorPrefix) => ({ [`${vendorPrefix}-precision`]: payload }),
148
- },
149
- ],
150
- annotations: [
151
- {
152
- annotationName: "HelpUrl",
153
- toJsonSchema: (value, vendorPrefix) => ({ [`${vendorPrefix}-help-url`]: value }),
154
- },
155
- ],
156
- });
157
- ```
72
+ - `defineExtension`
73
+ - `defineConstraint`
74
+ - `defineConstraintTag`
75
+ - `defineAnnotation`
76
+ - `defineCustomType`
77
+
78
+ ### Utilities
79
+
80
+ - `normalizeConstraintTagName`
81
+ - field and layout type guards
158
82
 
159
83
  ## License
160
84
 
package/dist/core.d.ts CHANGED
@@ -99,12 +99,25 @@ export declare const BUILTIN_CONSTRAINT_DEFINITIONS: {
99
99
  readonly maxLength: "number";
100
100
  readonly minItems: "number";
101
101
  readonly maxItems: "number";
102
- readonly pattern: "string";
103
102
  readonly uniqueItems: "boolean";
103
+ readonly pattern: "string";
104
104
  readonly const: "json";
105
105
  readonly enumOptions: "json";
106
106
  };
107
107
 
108
+ /**
109
+ * Registration for mapping a built-in TSDoc tag onto a custom constraint when
110
+ * it is used on a particular custom type.
111
+ */
112
+ export declare interface BuiltinConstraintBroadeningRegistration {
113
+ /** The built-in tag being broadened, without the `@` prefix. */
114
+ readonly tagName: BuiltinConstraintName;
115
+ /** The custom constraint to emit for this built-in tag. */
116
+ readonly constraintName: string;
117
+ /** Parser from raw TSDoc text to extension payload. */
118
+ readonly parseValue: (raw: string) => JsonValue;
119
+ }
120
+
108
121
  /** Type of a built-in constraint name. */
109
122
  export declare type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;
110
123
 
@@ -153,6 +166,40 @@ export declare interface ConstConstraintNode {
153
166
  */
154
167
  export declare type ConstraintNode = NumericConstraintNode | LengthConstraintNode | PatternConstraintNode | ArrayCardinalityConstraintNode | EnumMemberConstraintNode | ConstConstraintNode | CustomConstraintNode;
155
168
 
169
+ /**
170
+ * Semantic metadata for ordered custom constraints that should participate in
171
+ * the generic contradiction/broadening logic.
172
+ */
173
+ export declare interface ConstraintSemanticRole {
174
+ /**
175
+ * Logical family identifier shared by related constraints, for example
176
+ * `"decimal-bound"` or `"date-bound"`.
177
+ */
178
+ readonly family: string;
179
+ /** Whether this constraint acts as a lower or upper bound. */
180
+ readonly bound: "lower" | "upper" | "exact";
181
+ /** Whether equality is allowed when comparing against the bound. */
182
+ readonly inclusive: boolean;
183
+ }
184
+
185
+ /**
186
+ * Declarative authoring-side registration for a custom TSDoc constraint tag.
187
+ */
188
+ export declare interface ConstraintTagRegistration {
189
+ /** Tag name without the `@` prefix, e.g. `"maxSigFig"`. */
190
+ readonly tagName: string;
191
+ /** The custom constraint that this tag should produce. */
192
+ readonly constraintName: string;
193
+ /** Parser from raw TSDoc text to JSON-serializable payload. */
194
+ readonly parseValue: (raw: string) => JsonValue;
195
+ /**
196
+ * Optional precise applicability predicate for the field type being parsed.
197
+ * When omitted, the target custom constraint registration controls type
198
+ * applicability during validation.
199
+ */
200
+ readonly isApplicableToType?: (type: TypeNode) => boolean;
201
+ }
202
+
156
203
  /**
157
204
  * Creates initial field state with default values.
158
205
  *
@@ -221,6 +268,22 @@ export declare interface CustomConstraintRegistration {
221
268
  * Used by the validator to emit TYPE_MISMATCH diagnostics.
222
269
  */
223
270
  readonly applicableTypes: readonly TypeNode["kind"][] | null;
271
+ /**
272
+ * Optional precise type predicate used when kind-level applicability is too
273
+ * broad (for example, constraints that apply to integer-like primitives but
274
+ * not strings).
275
+ */
276
+ readonly isApplicableToType?: (type: TypeNode) => boolean;
277
+ /**
278
+ * Optional comparator for payloads belonging to the same custom constraint.
279
+ * Return values follow the `Array.prototype.sort()` contract.
280
+ */
281
+ readonly comparePayloads?: (left: JsonValue, right: JsonValue) => number;
282
+ /**
283
+ * Optional semantic family metadata for generic contradiction/broadening
284
+ * handling across ordered constraints.
285
+ */
286
+ readonly semanticRole?: ConstraintSemanticRole;
224
287
  /**
225
288
  * Converts the custom constraint's payload into JSON Schema keywords.
226
289
  *
@@ -256,6 +319,11 @@ export declare interface CustomTypeNode {
256
319
  export declare interface CustomTypeRegistration {
257
320
  /** The type name, unique within the extension. */
258
321
  readonly typeName: string;
322
+ /**
323
+ * Optional TypeScript surface names that should resolve to this custom type
324
+ * during TSDoc/class analysis. Defaults to `typeName` when omitted.
325
+ */
326
+ readonly tsTypeNames?: readonly string[];
259
327
  /**
260
328
  * Converts the custom type's payload into a JSON Schema fragment.
261
329
  *
@@ -264,6 +332,11 @@ export declare interface CustomTypeRegistration {
264
332
  * @returns A JSON Schema fragment representing this type.
265
333
  */
266
334
  readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;
335
+ /**
336
+ * Optional broadening of built-in constraint tags so they can apply to this
337
+ * custom type without modifying the core built-in constraint tables.
338
+ */
339
+ readonly builtinConstraintBroadenings?: readonly BuiltinConstraintBroadeningRegistration[];
267
340
  }
268
341
 
269
342
  /**
@@ -334,6 +407,14 @@ export declare function defineAnnotation(reg: CustomAnnotationRegistration): Cus
334
407
  */
335
408
  export declare function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration;
336
409
 
410
+ /**
411
+ * Defines a custom TSDoc constraint tag registration.
412
+ *
413
+ * @param reg - The custom tag registration.
414
+ * @returns The same registration, validated at the type level.
415
+ */
416
+ export declare function defineConstraintTag(reg: ConstraintTagRegistration): ConstraintTagRegistration;
417
+
337
418
  /**
338
419
  * Defines a custom type registration. Currently an identity function that
339
420
  * provides type-checking and IDE autocompletion.
@@ -517,6 +598,8 @@ export declare interface ExtensionDefinition {
517
598
  readonly types?: readonly CustomTypeRegistration[];
518
599
  /** Custom constraint registrations provided by this extension. */
519
600
  readonly constraints?: readonly CustomConstraintRegistration[];
601
+ /** Authoring-side TSDoc tag registrations provided by this extension. */
602
+ readonly constraintTags?: readonly ConstraintTagRegistration[];
520
603
  /** Custom annotation registrations provided by this extension. */
521
604
  readonly annotations?: readonly CustomAnnotationRegistration[];
522
605
  /** Vocabulary keyword registrations provided by this extension. */
@@ -622,6 +705,8 @@ export declare interface FormIR {
622
705
  readonly irVersion: string;
623
706
  /** Top-level elements of the form: fields and layout nodes. */
624
707
  readonly elements: readonly FormIRElement[];
708
+ /** Root-level annotations derived from the source declaration itself. */
709
+ readonly rootAnnotations?: readonly AnnotationNode[];
625
710
  /**
626
711
  * Registry of named types referenced by fields in this form.
627
712
  * Keys are fully-qualified type names matching `ReferenceTypeNode.name`.
@@ -934,7 +1019,7 @@ export declare type Predicate<K extends string = string, V = unknown> = EqualsPr
934
1019
  */
935
1020
  export declare interface PrimitiveTypeNode {
936
1021
  readonly kind: "primitive";
937
- readonly primitiveKind: "string" | "number" | "boolean" | "null";
1022
+ readonly primitiveKind: "string" | "number" | "integer" | "bigint" | "boolean" | "null";
938
1023
  }
939
1024
 
940
1025
  /**
@@ -1049,6 +1134,8 @@ export declare interface TypeDefinition {
1049
1134
  readonly name: string;
1050
1135
  /** The resolved type node. */
1051
1136
  readonly type: TypeNode;
1137
+ /** Constraints declared on the named type itself. */
1138
+ readonly constraints?: readonly ConstraintNode[];
1052
1139
  /** Root-level value metadata for a named type definition. */
1053
1140
  readonly annotations?: readonly AnnotationNode[];
1054
1141
  /** Where this type was declared. */
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * @packageDocumentation
10
10
  */
11
+ import type { BuiltinConstraintName } from "../types/constraint-definitions.js";
11
12
  import type { JsonValue, TypeNode } from "../types/ir.js";
12
13
  /**
13
14
  * Registration for a custom type that maps to a JSON Schema representation.
@@ -18,6 +19,11 @@ import type { JsonValue, TypeNode } from "../types/ir.js";
18
19
  export interface CustomTypeRegistration {
19
20
  /** The type name, unique within the extension. */
20
21
  readonly typeName: string;
22
+ /**
23
+ * Optional TypeScript surface names that should resolve to this custom type
24
+ * during TSDoc/class analysis. Defaults to `typeName` when omitted.
25
+ */
26
+ readonly tsTypeNames?: readonly string[];
21
27
  /**
22
28
  * Converts the custom type's payload into a JSON Schema fragment.
23
29
  *
@@ -26,6 +32,11 @@ export interface CustomTypeRegistration {
26
32
  * @returns A JSON Schema fragment representing this type.
27
33
  */
28
34
  readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;
35
+ /**
36
+ * Optional broadening of built-in constraint tags so they can apply to this
37
+ * custom type without modifying the core built-in constraint tables.
38
+ */
39
+ readonly builtinConstraintBroadenings?: readonly BuiltinConstraintBroadeningRegistration[];
29
40
  }
30
41
  /**
31
42
  * Registration for a custom constraint that maps to JSON Schema keywords.
@@ -46,6 +57,22 @@ export interface CustomConstraintRegistration {
46
57
  * Used by the validator to emit TYPE_MISMATCH diagnostics.
47
58
  */
48
59
  readonly applicableTypes: readonly TypeNode["kind"][] | null;
60
+ /**
61
+ * Optional precise type predicate used when kind-level applicability is too
62
+ * broad (for example, constraints that apply to integer-like primitives but
63
+ * not strings).
64
+ */
65
+ readonly isApplicableToType?: (type: TypeNode) => boolean;
66
+ /**
67
+ * Optional comparator for payloads belonging to the same custom constraint.
68
+ * Return values follow the `Array.prototype.sort()` contract.
69
+ */
70
+ readonly comparePayloads?: (left: JsonValue, right: JsonValue) => number;
71
+ /**
72
+ * Optional semantic family metadata for generic contradiction/broadening
73
+ * handling across ordered constraints.
74
+ */
75
+ readonly semanticRole?: ConstraintSemanticRole;
49
76
  /**
50
77
  * Converts the custom constraint's payload into JSON Schema keywords.
51
78
  *
@@ -79,6 +106,50 @@ export interface VocabularyKeywordRegistration {
79
106
  /** JSON Schema that describes the valid values for this keyword. */
80
107
  readonly schema: JsonValue;
81
108
  }
109
+ /**
110
+ * Declarative authoring-side registration for a custom TSDoc constraint tag.
111
+ */
112
+ export interface ConstraintTagRegistration {
113
+ /** Tag name without the `@` prefix, e.g. `"maxSigFig"`. */
114
+ readonly tagName: string;
115
+ /** The custom constraint that this tag should produce. */
116
+ readonly constraintName: string;
117
+ /** Parser from raw TSDoc text to JSON-serializable payload. */
118
+ readonly parseValue: (raw: string) => JsonValue;
119
+ /**
120
+ * Optional precise applicability predicate for the field type being parsed.
121
+ * When omitted, the target custom constraint registration controls type
122
+ * applicability during validation.
123
+ */
124
+ readonly isApplicableToType?: (type: TypeNode) => boolean;
125
+ }
126
+ /**
127
+ * Registration for mapping a built-in TSDoc tag onto a custom constraint when
128
+ * it is used on a particular custom type.
129
+ */
130
+ export interface BuiltinConstraintBroadeningRegistration {
131
+ /** The built-in tag being broadened, without the `@` prefix. */
132
+ readonly tagName: BuiltinConstraintName;
133
+ /** The custom constraint to emit for this built-in tag. */
134
+ readonly constraintName: string;
135
+ /** Parser from raw TSDoc text to extension payload. */
136
+ readonly parseValue: (raw: string) => JsonValue;
137
+ }
138
+ /**
139
+ * Semantic metadata for ordered custom constraints that should participate in
140
+ * the generic contradiction/broadening logic.
141
+ */
142
+ export interface ConstraintSemanticRole {
143
+ /**
144
+ * Logical family identifier shared by related constraints, for example
145
+ * `"decimal-bound"` or `"date-bound"`.
146
+ */
147
+ readonly family: string;
148
+ /** Whether this constraint acts as a lower or upper bound. */
149
+ readonly bound: "lower" | "upper" | "exact";
150
+ /** Whether equality is allowed when comparing against the bound. */
151
+ readonly inclusive: boolean;
152
+ }
82
153
  /**
83
154
  * A complete extension definition bundling types, constraints, annotations,
84
155
  * and vocabulary keywords.
@@ -106,6 +177,8 @@ export interface ExtensionDefinition {
106
177
  readonly types?: readonly CustomTypeRegistration[];
107
178
  /** Custom constraint registrations provided by this extension. */
108
179
  readonly constraints?: readonly CustomConstraintRegistration[];
180
+ /** Authoring-side TSDoc tag registrations provided by this extension. */
181
+ readonly constraintTags?: readonly ConstraintTagRegistration[];
109
182
  /** Custom annotation registrations provided by this extension. */
110
183
  readonly annotations?: readonly CustomAnnotationRegistration[];
111
184
  /** Vocabulary keyword registrations provided by this extension. */
@@ -135,6 +208,13 @@ export declare function defineCustomType(reg: CustomTypeRegistration): CustomTyp
135
208
  * @returns The same registration, validated at the type level.
136
209
  */
137
210
  export declare function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration;
211
+ /**
212
+ * Defines a custom TSDoc constraint tag registration.
213
+ *
214
+ * @param reg - The custom tag registration.
215
+ * @returns The same registration, validated at the type level.
216
+ */
217
+ export declare function defineConstraintTag(reg: ConstraintTagRegistration): ConstraintTagRegistration;
138
218
  /**
139
219
  * Defines a custom annotation registration. Currently an identity function
140
220
  * that provides type-checking and IDE autocompletion.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM1D;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9F;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,wDAAwD;IACxD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,WAAW,GAAG,UAAU,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC;IAC7D;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9F;AAED;;;;;GAKG;AACH,MAAM,WAAW,4BAA4B;IAC3C,wDAAwD;IACxD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7F;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACnD,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAC/D,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAC/D,mEAAmE;IACnE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,6BAA6B,EAAE,CAAC;CACxE;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,mBAAmB,CAE7E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,sBAAsB,GAAG,sBAAsB,CAEpF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,4BAA4B,GAAG,4BAA4B,CAEhG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,4BAA4B,GAAG,4BAA4B,CAEhG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  createInitialFieldState: () => createInitialFieldState,
26
26
  defineAnnotation: () => defineAnnotation,
27
27
  defineConstraint: () => defineConstraint,
28
+ defineConstraintTag: () => defineConstraintTag,
28
29
  defineCustomType: () => defineCustomType,
29
30
  defineExtension: () => defineExtension,
30
31
  isArrayField: () => isArrayField,
@@ -65,8 +66,8 @@ var BUILTIN_CONSTRAINT_DEFINITIONS = {
65
66
  maxLength: "number",
66
67
  minItems: "number",
67
68
  maxItems: "number",
68
- pattern: "string",
69
69
  uniqueItems: "boolean",
70
+ pattern: "string",
70
71
  const: "json",
71
72
  enumOptions: "json"
72
73
  };
@@ -90,6 +91,9 @@ function defineCustomType(reg) {
90
91
  function defineConstraint(reg) {
91
92
  return reg;
92
93
  }
94
+ function defineConstraintTag(reg) {
95
+ return reg;
96
+ }
93
97
  function defineAnnotation(reg) {
94
98
  return reg;
95
99
  }
@@ -135,6 +139,7 @@ function isConditional(element) {
135
139
  createInitialFieldState,
136
140
  defineAnnotation,
137
141
  defineConstraint,
142
+ defineConstraintTag,
138
143
  defineCustomType,
139
144
  defineExtension,
140
145
  isArrayField,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/field-state.ts","../src/types/constraint-definitions.ts","../src/types/ir.ts","../src/extensions/index.ts","../src/guards.ts"],"sourcesContent":["/**\n * `@formspec/core` - Core type definitions for FormSpec\n *\n * This package provides the foundational types used throughout the FormSpec ecosystem:\n * - Form element types (fields, groups, conditionals)\n * - Field and form state types\n * - Data source registry for dynamic enums\n * - Canonical IR types (FormIR, FieldNode, TypeNode, ConstraintNode, AnnotationNode, etc.)\n *\n * @packageDocumentation\n */\n\n// Re-export all types\nexport type {\n // Validity\n Validity,\n\n // Field state\n FieldState,\n\n // Form state\n FormState,\n\n // Data sources\n DataSourceRegistry,\n DataSourceOption,\n FetchOptionsResponse,\n DataSourceValueType,\n\n // Elements\n TextField,\n NumberField,\n BooleanField,\n EnumOption,\n EnumOptionValue,\n StaticEnumField,\n DynamicEnumField,\n DynamicSchemaField,\n ArrayField,\n ObjectField,\n AnyField,\n Group,\n Conditional,\n FormElement,\n FormSpec,\n\n // Predicates\n EqualsPredicate,\n Predicate,\n\n // Built-in constraints\n BuiltinConstraintName,\n\n // Canonical IR\n JsonValue,\n Provenance,\n PathTarget,\n TypeNode,\n PrimitiveTypeNode,\n EnumMember,\n EnumTypeNode,\n ArrayTypeNode,\n ObjectProperty,\n ObjectTypeNode,\n RecordTypeNode,\n UnionTypeNode,\n ReferenceTypeNode,\n DynamicTypeNode,\n CustomTypeNode,\n ConstraintNode,\n NumericConstraintNode,\n LengthConstraintNode,\n PatternConstraintNode,\n ArrayCardinalityConstraintNode,\n EnumMemberConstraintNode,\n ConstConstraintNode,\n CustomConstraintNode,\n AnnotationNode,\n DisplayNameAnnotationNode,\n DescriptionAnnotationNode,\n FormatAnnotationNode,\n PlaceholderAnnotationNode,\n DefaultValueAnnotationNode,\n DeprecatedAnnotationNode,\n FormatHintAnnotationNode,\n CustomAnnotationNode,\n FieldNode,\n LayoutNode,\n GroupLayoutNode,\n ConditionalLayoutNode,\n FormIRElement,\n TypeDefinition,\n FormIR,\n} from \"./types/index.js\";\n\n// Re-export functions and constants\nexport {\n createInitialFieldState,\n BUILTIN_CONSTRAINT_DEFINITIONS,\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n IR_VERSION,\n} from \"./types/index.js\";\n\n// Extension API\nexport type {\n ExtensionDefinition,\n CustomTypeRegistration,\n CustomConstraintRegistration,\n CustomAnnotationRegistration,\n VocabularyKeywordRegistration,\n} from \"./extensions/index.js\";\n\nexport {\n defineExtension,\n defineCustomType,\n defineConstraint,\n defineAnnotation,\n} from \"./extensions/index.js\";\n\n// Re-export type guards\nexport {\n isField,\n isTextField,\n isNumberField,\n isBooleanField,\n isStaticEnumField,\n isDynamicEnumField,\n isDynamicSchemaField,\n isArrayField,\n isObjectField,\n isGroup,\n isConditional,\n} from \"./guards.js\";\n","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 */\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 */\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 */\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 pattern: \"string\",\n uniqueItems: \"boolean\",\n const: \"json\",\n enumOptions: \"json\",\n} as const;\n\n/** Type of a built-in constraint name. */\nexport type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\nexport interface PrimitiveTypeNode {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"boolean\" | \"null\";\n}\n\n/** A member of a static enum type. */\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/** Static enum type — members known at build time. */\nexport interface EnumTypeNode {\n readonly kind: \"enum\";\n readonly members: readonly EnumMember[];\n}\n\n/** Array type with a single items type. */\nexport interface ArrayTypeNode {\n readonly kind: \"array\";\n readonly items: TypeNode;\n}\n\n/** A named property within an object type. */\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/** Object type with named properties. */\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 */\nexport interface RecordTypeNode {\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/** Union type for non-enum unions. Nullable types are `T | null` using this. */\nexport interface UnionTypeNode {\n readonly kind: \"union\";\n readonly members: readonly TypeNode[];\n}\n\n/** Named type reference — preserved as references for `$defs`/`$ref` emission. */\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/** Dynamic type — schema resolved at runtime from a named data source. */\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/** Custom type registered by an extension. */\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 */\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 */\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 */\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 */\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/** Array uniqueness constraint. */\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/** Enum member subset constraint (refinement — only narrows). */\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/** Literal-value equality constraint. */\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/** Extension-registered custom constraint. */\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 */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\nexport interface DisplayNameAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"displayName\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface DescriptionAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"description\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/** Schema format annotation (e.g. email/date/uri). */\nexport interface FormatAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"format\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface PlaceholderAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"placeholder\";\n readonly value: string;\n readonly provenance: Provenance;\n}\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\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 */\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/** Extension-registered custom annotation. */\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/** A single form field after canonicalization. */\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/** Union of layout node types. */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/** A visual grouping of form elements. */\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/** Conditional visibility based on another field's value. */\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/** Union of all IR element types. */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/** A named type definition stored in the type registry. */\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 /** 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 */\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 /**\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 { JsonValue, TypeNode } from \"../types/ir.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced via {@link CustomTypeNode} in the IR and\n * resolved to JSON Schema via `toJsonSchema` during generation.\n */\nexport interface CustomTypeRegistration {\n /** The type name, unique within the extension. */\n readonly typeName: string;\n /**\n * Converts the custom type's payload into a JSON Schema fragment.\n *\n * @param payload - The opaque JSON payload from the {@link CustomTypeNode}.\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: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom constraint that maps to JSON Schema keywords.\n *\n * Custom constraints are referenced via {@link CustomConstraintNode} in the IR.\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 TypeNode[\"kind\"][] | null;\n /**\n * Converts the custom constraint's payload into JSON Schema keywords.\n *\n * @param payload - The opaque JSON payload from the {@link CustomConstraintNode}.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced via {@link CustomAnnotationNode} in the IR.\n * They describe or present a field but do not affect which values are valid.\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?: (value: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\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: JsonValue;\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 */\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 /** 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 */\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 */\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 */\nexport function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration {\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 */\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/** Narrows a FormElement to any field type. */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/** Narrows a FormElement to a text input field. */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/** Narrows a FormElement to a numeric input field. */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/** Narrows a FormElement to a boolean checkbox field. */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/** Narrows a FormElement to a static enum field. */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/** Narrows a FormElement to a dynamic enum field. */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/** Narrows a FormElement to a dynamic schema field. */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/** Narrows a FormElement to an array field. */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/** Narrows a FormElement to an object field. */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/** Narrows a FormElement to a visual group. */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/** Narrows a FormElement to a conditional wrapper. */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC+BO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;ACxBO,IAAM,iCAAiC;AAAA,EAC5C,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,SAAS;AAAA,EACT,aAAa;AAAA,EACb,OAAO;AAAA,EACP,aAAa;AACf;AAgBO,SAAS,2BAA2B,SAAyB;AAClE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAWO,SAAS,wBAAwB,SAAmD;AACzF,SAAO,OAAO,OAAO,gCAAgC,OAAO;AAC9D;;;ACvCO,IAAM,aAAa;;;ACsHnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AASO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;ACvJO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,cACd,SACiE;AACjE,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/field-state.ts","../src/types/constraint-definitions.ts","../src/types/ir.ts","../src/extensions/index.ts","../src/guards.ts"],"sourcesContent":["/**\n * `@formspec/core` - Core type definitions for FormSpec\n *\n * This package provides the foundational types used throughout the FormSpec ecosystem:\n * - Form element types (fields, groups, conditionals)\n * - Field and form state types\n * - Data source registry for dynamic enums\n * - Canonical IR types (FormIR, FieldNode, TypeNode, ConstraintNode, AnnotationNode, etc.)\n *\n * @packageDocumentation\n */\n\n// Re-export all types\nexport type {\n // Validity\n Validity,\n\n // Field state\n FieldState,\n\n // Form state\n FormState,\n\n // Data sources\n DataSourceRegistry,\n DataSourceOption,\n FetchOptionsResponse,\n DataSourceValueType,\n\n // Elements\n TextField,\n NumberField,\n BooleanField,\n EnumOption,\n EnumOptionValue,\n StaticEnumField,\n DynamicEnumField,\n DynamicSchemaField,\n ArrayField,\n ObjectField,\n AnyField,\n Group,\n Conditional,\n FormElement,\n FormSpec,\n\n // Predicates\n EqualsPredicate,\n Predicate,\n\n // Built-in constraints\n BuiltinConstraintName,\n\n // Canonical IR\n JsonValue,\n Provenance,\n PathTarget,\n TypeNode,\n PrimitiveTypeNode,\n EnumMember,\n EnumTypeNode,\n ArrayTypeNode,\n ObjectProperty,\n ObjectTypeNode,\n RecordTypeNode,\n UnionTypeNode,\n ReferenceTypeNode,\n DynamicTypeNode,\n CustomTypeNode,\n ConstraintNode,\n NumericConstraintNode,\n LengthConstraintNode,\n PatternConstraintNode,\n ArrayCardinalityConstraintNode,\n EnumMemberConstraintNode,\n ConstConstraintNode,\n CustomConstraintNode,\n AnnotationNode,\n DisplayNameAnnotationNode,\n DescriptionAnnotationNode,\n FormatAnnotationNode,\n PlaceholderAnnotationNode,\n DefaultValueAnnotationNode,\n DeprecatedAnnotationNode,\n FormatHintAnnotationNode,\n CustomAnnotationNode,\n FieldNode,\n LayoutNode,\n GroupLayoutNode,\n ConditionalLayoutNode,\n FormIRElement,\n TypeDefinition,\n FormIR,\n} from \"./types/index.js\";\n\n// Re-export functions and constants\nexport {\n createInitialFieldState,\n BUILTIN_CONSTRAINT_DEFINITIONS,\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n IR_VERSION,\n} from \"./types/index.js\";\n\n// Extension API\nexport type {\n ExtensionDefinition,\n CustomTypeRegistration,\n CustomConstraintRegistration,\n ConstraintTagRegistration,\n BuiltinConstraintBroadeningRegistration,\n ConstraintSemanticRole,\n CustomAnnotationRegistration,\n VocabularyKeywordRegistration,\n} from \"./extensions/index.js\";\n\nexport {\n defineExtension,\n defineCustomType,\n defineConstraint,\n defineConstraintTag,\n defineAnnotation,\n} from \"./extensions/index.js\";\n\n// Re-export type guards\nexport {\n isField,\n isTextField,\n isNumberField,\n isBooleanField,\n isStaticEnumField,\n isDynamicEnumField,\n isDynamicSchemaField,\n isArrayField,\n isObjectField,\n isGroup,\n isConditional,\n} from \"./guards.js\";\n","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 */\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 */\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 */\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/** Type of a built-in constraint name. */\nexport type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\nexport interface PrimitiveTypeNode {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n}\n\n/** A member of a static enum type. */\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/** Static enum type — members known at build time. */\nexport interface EnumTypeNode {\n readonly kind: \"enum\";\n readonly members: readonly EnumMember[];\n}\n\n/** Array type with a single items type. */\nexport interface ArrayTypeNode {\n readonly kind: \"array\";\n readonly items: TypeNode;\n}\n\n/** A named property within an object type. */\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/** Object type with named properties. */\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 */\nexport interface RecordTypeNode {\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/** Union type for non-enum unions. Nullable types are `T | null` using this. */\nexport interface UnionTypeNode {\n readonly kind: \"union\";\n readonly members: readonly TypeNode[];\n}\n\n/** Named type reference — preserved as references for `$defs`/`$ref` emission. */\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/** Dynamic type — schema resolved at runtime from a named data source. */\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/** Custom type registered by an extension. */\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 */\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 */\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 */\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 */\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/** Array uniqueness constraint. */\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/** Enum member subset constraint (refinement — only narrows). */\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/** Literal-value equality constraint. */\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/** Extension-registered custom constraint. */\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 */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\nexport interface DisplayNameAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"displayName\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface DescriptionAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"description\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/** Schema format annotation (e.g. email/date/uri). */\nexport interface FormatAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"format\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface PlaceholderAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"placeholder\";\n readonly value: string;\n readonly provenance: Provenance;\n}\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\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 */\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/** Extension-registered custom annotation. */\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/** A single form field after canonicalization. */\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/** Union of layout node types. */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/** A visual grouping of form elements. */\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/** Conditional visibility based on another field's value. */\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/** Union of all IR element types. */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/** A named type definition stored in the type registry. */\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 */\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\";\nimport type { JsonValue, TypeNode } from \"../types/ir.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced via {@link CustomTypeNode} in the IR and\n * resolved to JSON Schema via `toJsonSchema` during generation.\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 from the {@link CustomTypeNode}.\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: (payload: JsonValue, vendorPrefix: string) => 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 via {@link CustomConstraintNode} in the IR.\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 TypeNode[\"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: TypeNode) => 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: JsonValue, right: JsonValue) => 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 from the {@link CustomConstraintNode}.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced via {@link CustomAnnotationNode} in the IR.\n * They describe or present a field but do not affect which values are valid.\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?: (value: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\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: JsonValue;\n}\n\n/**\n * Declarative authoring-side registration for a custom TSDoc constraint tag.\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) => JsonValue;\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: TypeNode) => 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 */\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) => JsonValue;\n}\n\n/**\n * Semantic metadata for ordered custom constraints that should participate in\n * the generic contradiction/broadening logic.\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 */\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 */\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 */\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 */\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 */\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 */\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/** Narrows a FormElement to any field type. */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/** Narrows a FormElement to a text input field. */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/** Narrows a FormElement to a numeric input field. */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/** Narrows a FormElement to a boolean checkbox field. */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/** Narrows a FormElement to a static enum field. */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/** Narrows a FormElement to a dynamic enum field. */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/** Narrows a FormElement to a dynamic schema field. */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/** Narrows a FormElement to an array field. */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/** Narrows a FormElement to an object field. */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/** Narrows a FormElement to a visual group. */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/** Narrows a FormElement to a conditional wrapper. */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC+BO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;ACxBO,IAAM,iCAAiC;AAAA,EAC5C,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;AAgBO,SAAS,2BAA2B,SAAyB;AAClE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAWO,SAAS,wBAAwB,SAAmD;AACzF,SAAO,OAAO,OAAO,gCAAgC,OAAO;AAC9D;;;ACvCO,IAAM,aAAa;;;ACkMnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AASO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AAQO,SAAS,oBAAoB,KAA2D;AAC7F,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;AC7OO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,cACd,SACiE;AACjE,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
package/dist/index.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
  export type { Validity, FieldState, FormState, DataSourceRegistry, DataSourceOption, FetchOptionsResponse, DataSourceValueType, TextField, NumberField, BooleanField, EnumOption, EnumOptionValue, StaticEnumField, DynamicEnumField, DynamicSchemaField, ArrayField, ObjectField, AnyField, Group, Conditional, FormElement, FormSpec, EqualsPredicate, Predicate, BuiltinConstraintName, 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, FormatAnnotationNode, PlaceholderAnnotationNode, DefaultValueAnnotationNode, DeprecatedAnnotationNode, FormatHintAnnotationNode, CustomAnnotationNode, FieldNode, LayoutNode, GroupLayoutNode, ConditionalLayoutNode, FormIRElement, TypeDefinition, FormIR, } from "./types/index.js";
13
13
  export { createInitialFieldState, BUILTIN_CONSTRAINT_DEFINITIONS, normalizeConstraintTagName, isBuiltinConstraintName, IR_VERSION, } from "./types/index.js";
14
- export type { ExtensionDefinition, CustomTypeRegistration, CustomConstraintRegistration, CustomAnnotationRegistration, VocabularyKeywordRegistration, } from "./extensions/index.js";
15
- export { defineExtension, defineCustomType, defineConstraint, defineAnnotation, } from "./extensions/index.js";
14
+ export type { ExtensionDefinition, CustomTypeRegistration, CustomConstraintRegistration, ConstraintTagRegistration, BuiltinConstraintBroadeningRegistration, ConstraintSemanticRole, CustomAnnotationRegistration, VocabularyKeywordRegistration, } from "./extensions/index.js";
15
+ export { defineExtension, defineCustomType, defineConstraint, defineConstraintTag, defineAnnotation, } from "./extensions/index.js";
16
16
  export { isField, isTextField, isNumberField, isBooleanField, isStaticEnumField, isDynamicEnumField, isDynamicSchemaField, isArrayField, isObjectField, isGroup, isConditional, } from "./guards.js";
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,YAAY,EAEV,QAAQ,EAGR,UAAU,EAGV,SAAS,EAGT,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EAGnB,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,EAGR,eAAe,EACf,SAAS,EAGT,qBAAqB,EAGrB,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,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,kBAAkB,CAAC;AAG1B,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,uBAAuB,EACvB,UAAU,GACX,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,mBAAmB,EACnB,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,OAAO,EACP,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,aAAa,GACd,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,YAAY,EAEV,QAAQ,EAGR,UAAU,EAGV,SAAS,EAGT,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EAGnB,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,EAGR,eAAe,EACf,SAAS,EAGT,qBAAqB,EAGrB,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,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,kBAAkB,CAAC;AAG1B,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,uBAAuB,EACvB,UAAU,GACX,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,mBAAmB,EACnB,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,uCAAuC,EACvC,sBAAsB,EACtB,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,OAAO,EACP,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,aAAa,GACd,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -20,8 +20,8 @@ var BUILTIN_CONSTRAINT_DEFINITIONS = {
20
20
  maxLength: "number",
21
21
  minItems: "number",
22
22
  maxItems: "number",
23
- pattern: "string",
24
23
  uniqueItems: "boolean",
24
+ pattern: "string",
25
25
  const: "json",
26
26
  enumOptions: "json"
27
27
  };
@@ -45,6 +45,9 @@ function defineCustomType(reg) {
45
45
  function defineConstraint(reg) {
46
46
  return reg;
47
47
  }
48
+ function defineConstraintTag(reg) {
49
+ return reg;
50
+ }
48
51
  function defineAnnotation(reg) {
49
52
  return reg;
50
53
  }
@@ -89,6 +92,7 @@ export {
89
92
  createInitialFieldState,
90
93
  defineAnnotation,
91
94
  defineConstraint,
95
+ defineConstraintTag,
92
96
  defineCustomType,
93
97
  defineExtension,
94
98
  isArrayField,
package/dist/index.js.map CHANGED
@@ -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 */\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 */\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 */\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 pattern: \"string\",\n uniqueItems: \"boolean\",\n const: \"json\",\n enumOptions: \"json\",\n} as const;\n\n/** Type of a built-in constraint name. */\nexport type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\nexport interface PrimitiveTypeNode {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"boolean\" | \"null\";\n}\n\n/** A member of a static enum type. */\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/** Static enum type — members known at build time. */\nexport interface EnumTypeNode {\n readonly kind: \"enum\";\n readonly members: readonly EnumMember[];\n}\n\n/** Array type with a single items type. */\nexport interface ArrayTypeNode {\n readonly kind: \"array\";\n readonly items: TypeNode;\n}\n\n/** A named property within an object type. */\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/** Object type with named properties. */\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 */\nexport interface RecordTypeNode {\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/** Union type for non-enum unions. Nullable types are `T | null` using this. */\nexport interface UnionTypeNode {\n readonly kind: \"union\";\n readonly members: readonly TypeNode[];\n}\n\n/** Named type reference — preserved as references for `$defs`/`$ref` emission. */\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/** Dynamic type — schema resolved at runtime from a named data source. */\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/** Custom type registered by an extension. */\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 */\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 */\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 */\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 */\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/** Array uniqueness constraint. */\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/** Enum member subset constraint (refinement — only narrows). */\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/** Literal-value equality constraint. */\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/** Extension-registered custom constraint. */\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 */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\nexport interface DisplayNameAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"displayName\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface DescriptionAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"description\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/** Schema format annotation (e.g. email/date/uri). */\nexport interface FormatAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"format\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface PlaceholderAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"placeholder\";\n readonly value: string;\n readonly provenance: Provenance;\n}\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\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 */\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/** Extension-registered custom annotation. */\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/** A single form field after canonicalization. */\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/** Union of layout node types. */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/** A visual grouping of form elements. */\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/** Conditional visibility based on another field's value. */\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/** Union of all IR element types. */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/** A named type definition stored in the type registry. */\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 /** 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 */\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 /**\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 { JsonValue, TypeNode } from \"../types/ir.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced via {@link CustomTypeNode} in the IR and\n * resolved to JSON Schema via `toJsonSchema` during generation.\n */\nexport interface CustomTypeRegistration {\n /** The type name, unique within the extension. */\n readonly typeName: string;\n /**\n * Converts the custom type's payload into a JSON Schema fragment.\n *\n * @param payload - The opaque JSON payload from the {@link CustomTypeNode}.\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: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom constraint that maps to JSON Schema keywords.\n *\n * Custom constraints are referenced via {@link CustomConstraintNode} in the IR.\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 TypeNode[\"kind\"][] | null;\n /**\n * Converts the custom constraint's payload into JSON Schema keywords.\n *\n * @param payload - The opaque JSON payload from the {@link CustomConstraintNode}.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced via {@link CustomAnnotationNode} in the IR.\n * They describe or present a field but do not affect which values are valid.\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?: (value: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\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: JsonValue;\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 */\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 /** 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 */\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 */\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 */\nexport function defineConstraint(reg: CustomConstraintRegistration): CustomConstraintRegistration {\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 */\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/** Narrows a FormElement to any field type. */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/** Narrows a FormElement to a text input field. */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/** Narrows a FormElement to a numeric input field. */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/** Narrows a FormElement to a boolean checkbox field. */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/** Narrows a FormElement to a static enum field. */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/** Narrows a FormElement to a dynamic enum field. */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/** Narrows a FormElement to a dynamic schema field. */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/** Narrows a FormElement to an array field. */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/** Narrows a FormElement to an object field. */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/** Narrows a FormElement to a visual group. */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/** Narrows a FormElement to a conditional wrapper. */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";AA+BO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;ACxBO,IAAM,iCAAiC;AAAA,EAC5C,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,SAAS;AAAA,EACT,aAAa;AAAA,EACb,OAAO;AAAA,EACP,aAAa;AACf;AAgBO,SAAS,2BAA2B,SAAyB;AAClE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAWO,SAAS,wBAAwB,SAAmD;AACzF,SAAO,OAAO,OAAO,gCAAgC,OAAO;AAC9D;;;ACvCO,IAAM,aAAa;;;ACsHnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AASO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;ACvJO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAGO,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 */\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 */\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 */\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/** Type of a built-in constraint name. */\nexport type BuiltinConstraintName = keyof typeof BUILTIN_CONSTRAINT_DEFINITIONS;\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\nexport interface PrimitiveTypeNode {\n readonly kind: \"primitive\";\n readonly primitiveKind: \"string\" | \"number\" | \"integer\" | \"bigint\" | \"boolean\" | \"null\";\n}\n\n/** A member of a static enum type. */\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/** Static enum type — members known at build time. */\nexport interface EnumTypeNode {\n readonly kind: \"enum\";\n readonly members: readonly EnumMember[];\n}\n\n/** Array type with a single items type. */\nexport interface ArrayTypeNode {\n readonly kind: \"array\";\n readonly items: TypeNode;\n}\n\n/** A named property within an object type. */\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/** Object type with named properties. */\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 */\nexport interface RecordTypeNode {\n readonly kind: \"record\";\n /** The type of each value in the dictionary. */\n readonly valueType: TypeNode;\n}\n\n/** Union type for non-enum unions. Nullable types are `T | null` using this. */\nexport interface UnionTypeNode {\n readonly kind: \"union\";\n readonly members: readonly TypeNode[];\n}\n\n/** Named type reference — preserved as references for `$defs`/`$ref` emission. */\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/** Dynamic type — schema resolved at runtime from a named data source. */\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/** Custom type registered by an extension. */\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 */\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 */\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 */\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 */\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/** Array uniqueness constraint. */\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/** Enum member subset constraint (refinement — only narrows). */\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/** Literal-value equality constraint. */\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/** Extension-registered custom constraint. */\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 */\nexport type AnnotationNode =\n | DisplayNameAnnotationNode\n | DescriptionAnnotationNode\n | FormatAnnotationNode\n | PlaceholderAnnotationNode\n | DefaultValueAnnotationNode\n | DeprecatedAnnotationNode\n | FormatHintAnnotationNode\n | CustomAnnotationNode;\n\nexport interface DisplayNameAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"displayName\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface DescriptionAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"description\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\n/** Schema format annotation (e.g. email/date/uri). */\nexport interface FormatAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"format\";\n readonly value: string;\n readonly provenance: Provenance;\n}\n\nexport interface PlaceholderAnnotationNode {\n readonly kind: \"annotation\";\n readonly annotationKind: \"placeholder\";\n readonly value: string;\n readonly provenance: Provenance;\n}\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\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 */\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/** Extension-registered custom annotation. */\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/** A single form field after canonicalization. */\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/** Union of layout node types. */\nexport type LayoutNode = GroupLayoutNode | ConditionalLayoutNode;\n\n/** A visual grouping of form elements. */\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/** Conditional visibility based on another field's value. */\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/** Union of all IR element types. */\nexport type FormIRElement = FieldNode | LayoutNode;\n\n// =============================================================================\n// TYPE REGISTRY\n// =============================================================================\n\n/** A named type definition stored in the type registry. */\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 */\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\";\nimport type { JsonValue, TypeNode } from \"../types/ir.js\";\n\n// =============================================================================\n// REGISTRATION TYPES\n// =============================================================================\n\n/**\n * Registration for a custom type that maps to a JSON Schema representation.\n *\n * Custom types are referenced via {@link CustomTypeNode} in the IR and\n * resolved to JSON Schema via `toJsonSchema` during generation.\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 from the {@link CustomTypeNode}.\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: (payload: JsonValue, vendorPrefix: string) => 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 via {@link CustomConstraintNode} in the IR.\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 TypeNode[\"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: TypeNode) => 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: JsonValue, right: JsonValue) => 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 from the {@link CustomConstraintNode}.\n * @param vendorPrefix - The vendor prefix for extension keywords.\n * @returns A JSON Schema fragment with the constraint keywords.\n */\n readonly toJsonSchema: (payload: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a custom annotation that may produce JSON Schema keywords.\n *\n * Custom annotations are referenced via {@link CustomAnnotationNode} in the IR.\n * They describe or present a field but do not affect which values are valid.\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?: (value: JsonValue, vendorPrefix: string) => Record<string, unknown>;\n}\n\n/**\n * Registration for a vocabulary keyword to include in a JSON Schema `$vocabulary` declaration.\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: JsonValue;\n}\n\n/**\n * Declarative authoring-side registration for a custom TSDoc constraint tag.\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) => JsonValue;\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: TypeNode) => 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 */\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) => JsonValue;\n}\n\n/**\n * Semantic metadata for ordered custom constraints that should participate in\n * the generic contradiction/broadening logic.\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 */\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 */\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 */\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 */\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 */\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 */\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/** Narrows a FormElement to any field type. */\nexport function isField(element: FormElement): element is AnyField {\n return element._type === \"field\";\n}\n\n/** Narrows a FormElement to a text input field. */\nexport function isTextField(element: FormElement): element is TextField<string> {\n return element._type === \"field\" && element._field === \"text\";\n}\n\n/** Narrows a FormElement to a numeric input field. */\nexport function isNumberField(element: FormElement): element is NumberField<string> {\n return element._type === \"field\" && element._field === \"number\";\n}\n\n/** Narrows a FormElement to a boolean checkbox field. */\nexport function isBooleanField(element: FormElement): element is BooleanField<string> {\n return element._type === \"field\" && element._field === \"boolean\";\n}\n\n/** Narrows a FormElement to a static enum field. */\nexport function isStaticEnumField(\n element: FormElement\n): element is StaticEnumField<string, readonly EnumOptionValue[]> {\n return element._type === \"field\" && element._field === \"enum\";\n}\n\n/** Narrows a FormElement to a dynamic enum field. */\nexport function isDynamicEnumField(\n element: FormElement\n): element is DynamicEnumField<string, string> {\n return element._type === \"field\" && element._field === \"dynamic_enum\";\n}\n\n/** Narrows a FormElement to a dynamic schema field. */\nexport function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string> {\n return element._type === \"field\" && element._field === \"dynamic_schema\";\n}\n\n/** Narrows a FormElement to an array field. */\nexport function isArrayField(\n element: FormElement\n): element is ArrayField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"array\";\n}\n\n/** Narrows a FormElement to an object field. */\nexport function isObjectField(\n element: FormElement\n): element is ObjectField<string, readonly FormElement[]> {\n return element._type === \"field\" && element._field === \"object\";\n}\n\n/** Narrows a FormElement to a visual group. */\nexport function isGroup(element: FormElement): element is Group<readonly FormElement[]> {\n return element._type === \"group\";\n}\n\n/** Narrows a FormElement to a conditional wrapper. */\nexport function isConditional(\n element: FormElement\n): element is Conditional<string, unknown, readonly FormElement[]> {\n return element._type === \"conditional\";\n}\n"],"mappings":";AA+BO,SAAS,wBAA2B,OAAyB;AAClE,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACF;;;ACxBO,IAAM,iCAAiC;AAAA,EAC5C,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;AAgBO,SAAS,2BAA2B,SAAyB;AAClE,SAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC1D;AAWO,SAAS,wBAAwB,SAAmD;AACzF,SAAO,OAAO,OAAO,gCAAgC,OAAO;AAC9D;;;ACvCO,IAAM,aAAa;;;ACkMnB,SAAS,gBAAgB,KAA+C;AAC7E,SAAO;AACT;AASO,SAAS,iBAAiB,KAAqD;AACpF,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;AAQO,SAAS,oBAAoB,KAA2D;AAC7F,SAAO;AACT;AASO,SAAS,iBAAiB,KAAiE;AAChG,SAAO;AACT;;;AC7OO,SAAS,QAAQ,SAA2C;AACjE,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,YAAY,SAAoD;AAC9E,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cAAc,SAAsD;AAClF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,eAAe,SAAuD;AACpF,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,kBACd,SACgE;AAChE,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,mBACd,SAC6C;AAC7C,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,qBAAqB,SAA6D;AAChG,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,aACd,SACuD;AACvD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,cACd,SACwD;AACxD,SAAO,QAAQ,UAAU,WAAW,QAAQ,WAAW;AACzD;AAGO,SAAS,QAAQ,SAAgE;AACtF,SAAO,QAAQ,UAAU;AAC3B;AAGO,SAAS,cACd,SACiE;AACjE,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
@@ -22,8 +22,8 @@ export declare const BUILTIN_CONSTRAINT_DEFINITIONS: {
22
22
  readonly maxLength: "number";
23
23
  readonly minItems: "number";
24
24
  readonly maxItems: "number";
25
- readonly pattern: "string";
26
25
  readonly uniqueItems: "boolean";
26
+ readonly pattern: "string";
27
27
  readonly const: "json";
28
28
  readonly enumOptions: "json";
29
29
  };
@@ -66,7 +66,7 @@ export type TypeNode = PrimitiveTypeNode | EnumTypeNode | ArrayTypeNode | Object
66
66
  */
67
67
  export interface PrimitiveTypeNode {
68
68
  readonly kind: "primitive";
69
- readonly primitiveKind: "string" | "number" | "boolean" | "null";
69
+ readonly primitiveKind: "string" | "number" | "integer" | "bigint" | "boolean" | "null";
70
70
  }
71
71
  /** A member of a static enum type. */
72
72
  export interface EnumMember {
@@ -386,6 +386,8 @@ export interface TypeDefinition {
386
386
  readonly name: string;
387
387
  /** The resolved type node. */
388
388
  readonly type: TypeNode;
389
+ /** Constraints declared on the named type itself. */
390
+ readonly constraints?: readonly ConstraintNode[];
389
391
  /** Root-level value metadata for a named type definition. */
390
392
  readonly annotations?: readonly AnnotationNode[];
391
393
  /** Where this type was declared. */
@@ -408,6 +410,8 @@ export interface FormIR {
408
410
  readonly irVersion: string;
409
411
  /** Top-level elements of the form: fields and layout nodes. */
410
412
  readonly elements: readonly FormIRElement[];
413
+ /** Root-level annotations derived from the source declaration itself. */
414
+ readonly rootAnnotations?: readonly AnnotationNode[];
411
415
  /**
412
416
  * Registry of named types referenced by fields in this form.
413
417
  * Keys are fully-qualified type names matching `ReferenceTypeNode.name`.
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../src/types/ir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../src/types/ir.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formspec/core",
3
- "version": "0.1.0-alpha.16",
3
+ "version": "0.1.0-alpha.19",
4
4
  "description": "Core utilities for formspec",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",