@formspec/dsl 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Field builder functions for creating form field definitions.
3
+ *
4
+ * Each function creates a field descriptor that captures both schema information
5
+ * (name, type) and UI hints (label, placeholder, etc.).
6
+ */
7
+ import type { TextField, NumberField, BooleanField, StaticEnumField, DynamicEnumField, DynamicSchemaField, ArrayField, ObjectField, FormElement } from "@formspec/core";
8
+ /**
9
+ * Field builder namespace containing functions to create each field type.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { field } from "@formspec/dsl";
14
+ *
15
+ * field.text("name", { label: "Full Name" });
16
+ * field.number("age", { min: 0, max: 150 });
17
+ * field.enum("status", ["draft", "sent", "paid"]);
18
+ * field.dynamicEnum("country", "countries", { label: "Country" });
19
+ * ```
20
+ */
21
+ export declare const field: {
22
+ /**
23
+ * Creates a text input field.
24
+ *
25
+ * @param name - The field name (used as the schema key)
26
+ * @param config - Optional configuration for label, placeholder, etc.
27
+ * @returns A TextField descriptor
28
+ */
29
+ text: <const N extends string>(name: N, config?: Omit<TextField<N>, "_type" | "_field" | "name">) => TextField<N>;
30
+ /**
31
+ * Creates a numeric input field.
32
+ *
33
+ * @param name - The field name (used as the schema key)
34
+ * @param config - Optional configuration for label, min, max, etc.
35
+ * @returns A NumberField descriptor
36
+ */
37
+ number: <const N extends string>(name: N, config?: Omit<NumberField<N>, "_type" | "_field" | "name">) => NumberField<N>;
38
+ /**
39
+ * Creates a boolean checkbox field.
40
+ *
41
+ * @param name - The field name (used as the schema key)
42
+ * @param config - Optional configuration for label, etc.
43
+ * @returns A BooleanField descriptor
44
+ */
45
+ boolean: <const N extends string>(name: N, config?: Omit<BooleanField<N>, "_type" | "_field" | "name">) => BooleanField<N>;
46
+ /**
47
+ * Creates a field with static enum options (known at compile time).
48
+ *
49
+ * Literal types are automatically inferred - no `as const` needed:
50
+ * ```typescript
51
+ * field.enum("status", ["draft", "sent", "paid"])
52
+ * // Schema type: "draft" | "sent" | "paid"
53
+ * ```
54
+ *
55
+ * @param name - The field name (used as the schema key)
56
+ * @param options - Array of allowed string values
57
+ * @param config - Optional configuration for label, etc.
58
+ * @returns A StaticEnumField descriptor
59
+ */
60
+ enum: <const N extends string, const O extends readonly string[]>(name: N, options: O, config?: Omit<StaticEnumField<N, O>, "_type" | "_field" | "name" | "options">) => StaticEnumField<N, O>;
61
+ /**
62
+ * Creates a field with dynamic enum options (fetched from a data source at runtime).
63
+ *
64
+ * The data source must be registered in DataSourceRegistry via module augmentation:
65
+ * ```typescript
66
+ * declare module "@formspec/core" {
67
+ * interface DataSourceRegistry {
68
+ * countries: { id: string; code: string; name: string };
69
+ * }
70
+ * }
71
+ *
72
+ * field.dynamicEnum("country", "countries", { label: "Country" })
73
+ * ```
74
+ *
75
+ * @param name - The field name (used as the schema key)
76
+ * @param source - The data source key (must be in DataSourceRegistry)
77
+ * @param config - Optional configuration for label, params, etc.
78
+ * @returns A DynamicEnumField descriptor
79
+ */
80
+ dynamicEnum: <const N extends string, const Source extends string>(name: N, source: Source, config?: Omit<DynamicEnumField<N, Source>, "_type" | "_field" | "name" | "source">) => DynamicEnumField<N, Source>;
81
+ /**
82
+ * Creates a field that loads its schema dynamically (e.g., from an extension).
83
+ *
84
+ * @param name - The field name (used as the schema key)
85
+ * @param schemaSource - Identifier for the schema source
86
+ * @param config - Optional configuration for label, etc.
87
+ * @returns A DynamicSchemaField descriptor
88
+ */
89
+ dynamicSchema: <const N extends string>(name: N, schemaSource: string, config?: Omit<DynamicSchemaField<N>, "_type" | "_field" | "name" | "schemaSource">) => DynamicSchemaField<N>;
90
+ /**
91
+ * Creates an array field containing repeating items.
92
+ *
93
+ * Use this for lists of values (e.g., multiple addresses, line items).
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * field.array("addresses",
98
+ * field.text("street", { label: "Street" }),
99
+ * field.text("city", { label: "City" }),
100
+ * field.text("zip", { label: "ZIP Code" }),
101
+ * )
102
+ * ```
103
+ *
104
+ * @param name - The field name (used as the schema key)
105
+ * @param items - The form elements that define each array item
106
+ * @returns An ArrayField descriptor
107
+ */
108
+ array: <const N extends string, const Items extends readonly FormElement[]>(name: N, ...items: Items) => ArrayField<N, Items>;
109
+ /**
110
+ * Creates an array field with additional configuration options.
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * field.arrayWithConfig("lineItems", {
115
+ * label: "Line Items",
116
+ * minItems: 1,
117
+ * maxItems: 10,
118
+ * },
119
+ * field.text("description"),
120
+ * field.number("quantity"),
121
+ * )
122
+ * ```
123
+ *
124
+ * @param name - The field name (used as the schema key)
125
+ * @param config - Configuration for label, minItems, maxItems, etc.
126
+ * @param items - The form elements that define each array item
127
+ * @returns An ArrayField descriptor
128
+ */
129
+ arrayWithConfig: <const N extends string, const Items extends readonly FormElement[]>(name: N, config: Omit<ArrayField<N, Items>, "_type" | "_field" | "name" | "items">, ...items: Items) => ArrayField<N, Items>;
130
+ /**
131
+ * Creates an object field containing nested properties.
132
+ *
133
+ * Use this for grouping related fields under a single key in the schema.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * field.object("address",
138
+ * field.text("street", { label: "Street" }),
139
+ * field.text("city", { label: "City" }),
140
+ * field.text("zip", { label: "ZIP Code" }),
141
+ * )
142
+ * ```
143
+ *
144
+ * @param name - The field name (used as the schema key)
145
+ * @param properties - The form elements that define the object's properties
146
+ * @returns An ObjectField descriptor
147
+ */
148
+ object: <const N extends string, const Properties extends readonly FormElement[]>(name: N, ...properties: Properties) => ObjectField<N, Properties>;
149
+ /**
150
+ * Creates an object field with additional configuration options.
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * field.objectWithConfig("billingAddress", { label: "Billing Address", required: true },
155
+ * field.text("street"),
156
+ * field.text("city"),
157
+ * )
158
+ * ```
159
+ *
160
+ * @param name - The field name (used as the schema key)
161
+ * @param config - Configuration for label, required, etc.
162
+ * @param properties - The form elements that define the object's properties
163
+ * @returns An ObjectField descriptor
164
+ */
165
+ objectWithConfig: <const N extends string, const Properties extends readonly FormElement[]>(name: N, config: Omit<ObjectField<N, Properties>, "_type" | "_field" | "name" | "properties">, ...properties: Properties) => ObjectField<N, Properties>;
166
+ };
167
+ //# sourceMappingURL=field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;OAMG;iBACU,CAAC,SAAS,MAAM,QACrB,CAAC,WACE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,KACvD,SAAS,CAAC,CAAC,CAAC;IAOf;;;;;;OAMG;mBACY,CAAC,SAAS,MAAM,QACvB,CAAC,WACE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,KACzD,WAAW,CAAC,CAAC,CAAC;IAOjB;;;;;;OAMG;oBACa,CAAC,SAAS,MAAM,QACxB,CAAC,WACE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,KAC1D,YAAY,CAAC,CAAC,CAAC;IAOlB;;;;;;;;;;;;;OAaG;iBACU,CAAC,SAAS,MAAM,QAAQ,CAAC,SAAS,SAAS,MAAM,EAAE,QACxD,CAAC,WACE,CAAC,WACD,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC,KAC5E,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;IAQxB;;;;;;;;;;;;;;;;;;OAkBG;wBACiB,CAAC,SAAS,MAAM,QAAQ,MAAM,SAAS,MAAM,QACzD,CAAC,UACC,MAAM,WACL,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC,KACjF,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC;IAQ9B;;;;;;;OAOG;0BACmB,CAAC,SAAS,MAAM,QAC9B,CAAC,gBACO,MAAM,WACX,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,cAAc,CAAC,KACjF,kBAAkB,CAAC,CAAC,CAAC;IAQxB;;;;;;;;;;;;;;;;;OAiBG;kBACW,CAAC,SAAS,MAAM,QAAQ,KAAK,SAAS,SAAS,WAAW,EAAE,QAClE,CAAC,YACG,KAAK,KACd,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC;IAOvB;;;;;;;;;;;;;;;;;;;OAmBG;4BACqB,CAAC,SAAS,MAAM,QAAQ,KAAK,SAAS,SAAS,WAAW,EAAE,QAC5E,CAAC,UACC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,YAC/D,KAAK,KACd,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC;IAQvB;;;;;;;;;;;;;;;;;OAiBG;mBACY,CAAC,SAAS,MAAM,QAAQ,UAAU,SAAS,SAAS,WAAW,EAAE,QACxE,CAAC,iBACQ,UAAU,KACxB,WAAW,CAAC,CAAC,EAAE,UAAU,CAAC;IAO7B;;;;;;;;;;;;;;;OAeG;6BACsB,CAAC,SAAS,MAAM,QAAQ,UAAU,SAAS,SAAS,WAAW,EAAE,QAClF,CAAC,UACC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC,iBACrE,UAAU,KACxB,WAAW,CAAC,CAAC,EAAE,UAAU,CAAC;CAO9B,CAAC"}
package/dist/field.js ADDED
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Field builder functions for creating form field definitions.
3
+ *
4
+ * Each function creates a field descriptor that captures both schema information
5
+ * (name, type) and UI hints (label, placeholder, etc.).
6
+ */
7
+ /**
8
+ * Field builder namespace containing functions to create each field type.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { field } from "@formspec/dsl";
13
+ *
14
+ * field.text("name", { label: "Full Name" });
15
+ * field.number("age", { min: 0, max: 150 });
16
+ * field.enum("status", ["draft", "sent", "paid"]);
17
+ * field.dynamicEnum("country", "countries", { label: "Country" });
18
+ * ```
19
+ */
20
+ export const field = {
21
+ /**
22
+ * Creates a text input field.
23
+ *
24
+ * @param name - The field name (used as the schema key)
25
+ * @param config - Optional configuration for label, placeholder, etc.
26
+ * @returns A TextField descriptor
27
+ */
28
+ text: (name, config) => ({
29
+ _type: "field",
30
+ _field: "text",
31
+ name,
32
+ ...config,
33
+ }),
34
+ /**
35
+ * Creates a numeric input field.
36
+ *
37
+ * @param name - The field name (used as the schema key)
38
+ * @param config - Optional configuration for label, min, max, etc.
39
+ * @returns A NumberField descriptor
40
+ */
41
+ number: (name, config) => ({
42
+ _type: "field",
43
+ _field: "number",
44
+ name,
45
+ ...config,
46
+ }),
47
+ /**
48
+ * Creates a boolean checkbox field.
49
+ *
50
+ * @param name - The field name (used as the schema key)
51
+ * @param config - Optional configuration for label, etc.
52
+ * @returns A BooleanField descriptor
53
+ */
54
+ boolean: (name, config) => ({
55
+ _type: "field",
56
+ _field: "boolean",
57
+ name,
58
+ ...config,
59
+ }),
60
+ /**
61
+ * Creates a field with static enum options (known at compile time).
62
+ *
63
+ * Literal types are automatically inferred - no `as const` needed:
64
+ * ```typescript
65
+ * field.enum("status", ["draft", "sent", "paid"])
66
+ * // Schema type: "draft" | "sent" | "paid"
67
+ * ```
68
+ *
69
+ * @param name - The field name (used as the schema key)
70
+ * @param options - Array of allowed string values
71
+ * @param config - Optional configuration for label, etc.
72
+ * @returns A StaticEnumField descriptor
73
+ */
74
+ enum: (name, options, config) => ({
75
+ _type: "field",
76
+ _field: "enum",
77
+ name,
78
+ options,
79
+ ...config,
80
+ }),
81
+ /**
82
+ * Creates a field with dynamic enum options (fetched from a data source at runtime).
83
+ *
84
+ * The data source must be registered in DataSourceRegistry via module augmentation:
85
+ * ```typescript
86
+ * declare module "@formspec/core" {
87
+ * interface DataSourceRegistry {
88
+ * countries: { id: string; code: string; name: string };
89
+ * }
90
+ * }
91
+ *
92
+ * field.dynamicEnum("country", "countries", { label: "Country" })
93
+ * ```
94
+ *
95
+ * @param name - The field name (used as the schema key)
96
+ * @param source - The data source key (must be in DataSourceRegistry)
97
+ * @param config - Optional configuration for label, params, etc.
98
+ * @returns A DynamicEnumField descriptor
99
+ */
100
+ dynamicEnum: (name, source, config) => ({
101
+ _type: "field",
102
+ _field: "dynamic_enum",
103
+ name,
104
+ source,
105
+ ...config,
106
+ }),
107
+ /**
108
+ * Creates a field that loads its schema dynamically (e.g., from an extension).
109
+ *
110
+ * @param name - The field name (used as the schema key)
111
+ * @param schemaSource - Identifier for the schema source
112
+ * @param config - Optional configuration for label, etc.
113
+ * @returns A DynamicSchemaField descriptor
114
+ */
115
+ dynamicSchema: (name, schemaSource, config) => ({
116
+ _type: "field",
117
+ _field: "dynamic_schema",
118
+ name,
119
+ schemaSource,
120
+ ...config,
121
+ }),
122
+ /**
123
+ * Creates an array field containing repeating items.
124
+ *
125
+ * Use this for lists of values (e.g., multiple addresses, line items).
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * field.array("addresses",
130
+ * field.text("street", { label: "Street" }),
131
+ * field.text("city", { label: "City" }),
132
+ * field.text("zip", { label: "ZIP Code" }),
133
+ * )
134
+ * ```
135
+ *
136
+ * @param name - The field name (used as the schema key)
137
+ * @param items - The form elements that define each array item
138
+ * @returns An ArrayField descriptor
139
+ */
140
+ array: (name, ...items) => ({
141
+ _type: "field",
142
+ _field: "array",
143
+ name,
144
+ items,
145
+ }),
146
+ /**
147
+ * Creates an array field with additional configuration options.
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * field.arrayWithConfig("lineItems", {
152
+ * label: "Line Items",
153
+ * minItems: 1,
154
+ * maxItems: 10,
155
+ * },
156
+ * field.text("description"),
157
+ * field.number("quantity"),
158
+ * )
159
+ * ```
160
+ *
161
+ * @param name - The field name (used as the schema key)
162
+ * @param config - Configuration for label, minItems, maxItems, etc.
163
+ * @param items - The form elements that define each array item
164
+ * @returns An ArrayField descriptor
165
+ */
166
+ arrayWithConfig: (name, config, ...items) => ({
167
+ _type: "field",
168
+ _field: "array",
169
+ name,
170
+ items,
171
+ ...config,
172
+ }),
173
+ /**
174
+ * Creates an object field containing nested properties.
175
+ *
176
+ * Use this for grouping related fields under a single key in the schema.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * field.object("address",
181
+ * field.text("street", { label: "Street" }),
182
+ * field.text("city", { label: "City" }),
183
+ * field.text("zip", { label: "ZIP Code" }),
184
+ * )
185
+ * ```
186
+ *
187
+ * @param name - The field name (used as the schema key)
188
+ * @param properties - The form elements that define the object's properties
189
+ * @returns An ObjectField descriptor
190
+ */
191
+ object: (name, ...properties) => ({
192
+ _type: "field",
193
+ _field: "object",
194
+ name,
195
+ properties,
196
+ }),
197
+ /**
198
+ * Creates an object field with additional configuration options.
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * field.objectWithConfig("billingAddress", { label: "Billing Address", required: true },
203
+ * field.text("street"),
204
+ * field.text("city"),
205
+ * )
206
+ * ```
207
+ *
208
+ * @param name - The field name (used as the schema key)
209
+ * @param config - Configuration for label, required, etc.
210
+ * @param properties - The form elements that define the object's properties
211
+ * @returns An ObjectField descriptor
212
+ */
213
+ objectWithConfig: (name, config, ...properties) => ({
214
+ _type: "field",
215
+ _field: "object",
216
+ name,
217
+ properties,
218
+ ...config,
219
+ }),
220
+ };
221
+ //# sourceMappingURL=field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB;;;;;;OAMG;IACH,IAAI,EAAE,CACJ,IAAO,EACP,MAAwD,EAC1C,EAAE,CAAC,CAAC;QAClB,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,MAAM;QACd,IAAI;QACJ,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;OAMG;IACH,MAAM,EAAE,CACN,IAAO,EACP,MAA0D,EAC1C,EAAE,CAAC,CAAC;QACpB,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,QAAQ;QAChB,IAAI;QACJ,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;OAMG;IACH,OAAO,EAAE,CACP,IAAO,EACP,MAA2D,EAC1C,EAAE,CAAC,CAAC;QACrB,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,SAAS;QACjB,IAAI;QACJ,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;;;;;;;;OAaG;IACH,IAAI,EAAE,CACJ,IAAO,EACP,OAAU,EACV,MAA6E,EACtD,EAAE,CAAC,CAAC;QAC3B,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,MAAM;QACd,IAAI;QACJ,OAAO;QACP,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,EAAE,CACX,IAAO,EACP,MAAc,EACd,MAAkF,EACrD,EAAE,CAAC,CAAC;QACjC,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,cAAc;QACtB,IAAI;QACJ,MAAM;QACN,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;;OAOG;IACH,aAAa,EAAE,CACb,IAAO,EACP,YAAoB,EACpB,MAAkF,EAC3D,EAAE,CAAC,CAAC;QAC3B,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,gBAAgB;QACxB,IAAI;QACJ,YAAY;QACZ,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,EAAE,CACL,IAAO,EACP,GAAG,KAAY,EACO,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,OAAO;QACf,IAAI;QACJ,KAAK;KACN,CAAC;IAEF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,EAAE,CACf,IAAO,EACP,MAAyE,EACzE,GAAG,KAAY,EACO,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,OAAO;QACf,IAAI;QACJ,KAAK;QACL,GAAG,MAAM;KACV,CAAC;IAEF;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,EAAE,CACN,IAAO,EACP,GAAG,UAAsB,EACG,EAAE,CAAC,CAAC;QAChC,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,QAAQ;QAChB,IAAI;QACJ,UAAU;KACX,CAAC;IAEF;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,EAAE,CAChB,IAAO,EACP,MAAoF,EACpF,GAAG,UAAsB,EACG,EAAE,CAAC,CAAC;QAChC,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,QAAQ;QAChB,IAAI;QACJ,UAAU;QACV,GAAG,MAAM;KACV,CAAC;CACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `@formspec/dsl` - DSL functions for defining FormSpec forms
3
+ *
4
+ * This package provides the builder functions for creating form specifications:
5
+ * - `field.*` - Field builders (text, number, boolean, enum, dynamicEnum)
6
+ * - `group()` - Visual grouping
7
+ * - `when()` + `is()` - Conditional visibility
8
+ * - `formspec()` - Top-level form definition
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { formspec, field, group, when, is } from "@formspec/dsl";
13
+ *
14
+ * const InvoiceForm = formspec(
15
+ * group("Customer",
16
+ * field.text("customerName", { label: "Customer Name" }),
17
+ * field.dynamicEnum("country", "fetch_countries", { label: "Country" }),
18
+ * ),
19
+ * group("Invoice Details",
20
+ * field.number("amount", { label: "Amount", min: 0 }),
21
+ * field.enum("status", ["draft", "sent", "paid"] as const),
22
+ * when(is("status", "draft"),
23
+ * field.text("internalNotes", { label: "Internal Notes" }),
24
+ * ),
25
+ * ),
26
+ * );
27
+ * ```
28
+ *
29
+ * @packageDocumentation
30
+ */
31
+ export { field } from "./field.js";
32
+ export { is } from "./predicate.js";
33
+ export { group, when, formspec, formspecWithValidation } from "./structure.js";
34
+ export type { FormSpecOptions } from "./structure.js";
35
+ export { validateForm, logValidationIssues } from "./validation.js";
36
+ export type { ValidationSeverity, ValidationIssue, ValidationResult, } from "./validation.js";
37
+ export type { InferFieldValue, ExtractFields, ExtractFieldsFromArray, BuildSchema, InferSchema, InferFormSchema, } from "./inference.js";
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `@formspec/dsl` - DSL functions for defining FormSpec forms
3
+ *
4
+ * This package provides the builder functions for creating form specifications:
5
+ * - `field.*` - Field builders (text, number, boolean, enum, dynamicEnum)
6
+ * - `group()` - Visual grouping
7
+ * - `when()` + `is()` - Conditional visibility
8
+ * - `formspec()` - Top-level form definition
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { formspec, field, group, when, is } from "@formspec/dsl";
13
+ *
14
+ * const InvoiceForm = formspec(
15
+ * group("Customer",
16
+ * field.text("customerName", { label: "Customer Name" }),
17
+ * field.dynamicEnum("country", "fetch_countries", { label: "Country" }),
18
+ * ),
19
+ * group("Invoice Details",
20
+ * field.number("amount", { label: "Amount", min: 0 }),
21
+ * field.enum("status", ["draft", "sent", "paid"] as const),
22
+ * when(is("status", "draft"),
23
+ * field.text("internalNotes", { label: "Internal Notes" }),
24
+ * ),
25
+ * ),
26
+ * );
27
+ * ```
28
+ *
29
+ * @packageDocumentation
30
+ */
31
+ // Field builders
32
+ export { field } from "./field.js";
33
+ // Predicate builders
34
+ export { is } from "./predicate.js";
35
+ // Structure builders
36
+ export { group, when, formspec, formspecWithValidation } from "./structure.js";
37
+ // Validation
38
+ export { validateForm, logValidationIssues } from "./validation.js";
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,iBAAiB;AACjB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,qBAAqB;AACrB,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAEpC,qBAAqB;AACrB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Type-level utilities for inferring schema types from form elements.
3
+ *
4
+ * These types allow TypeScript to automatically derive the form's schema type
5
+ * from its nested element structure.
6
+ */
7
+ import type { TextField, NumberField, BooleanField, StaticEnumField, DynamicEnumField, DynamicSchemaField, ArrayField, ObjectField, AnyField, Group, Conditional, FormElement, FormSpec, DataSourceValueType } from "@formspec/core";
8
+ /**
9
+ * Infers the value type from a single field.
10
+ *
11
+ * - TextField returns string
12
+ * - NumberField returns number
13
+ * - BooleanField returns boolean
14
+ * - StaticEnumField returns union of option literals
15
+ * - DynamicEnumField returns DataSourceValueType (usually string)
16
+ * - DynamicSchemaField returns Record of string to unknown
17
+ * - ArrayField returns array of inferred item schema
18
+ * - ObjectField returns object of inferred property schema
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Simple fields
23
+ * type T1 = InferFieldValue<TextField<"name">>; // string
24
+ * type T2 = InferFieldValue<NumberField<"age">>; // number
25
+ *
26
+ * // Enum fields
27
+ * type T3 = InferFieldValue<StaticEnumField<"status", ["draft", "sent"]>>; // "draft" | "sent"
28
+ *
29
+ * // Nested fields
30
+ * type T4 = InferFieldValue<ArrayField<"items", [TextField<"name">]>>; // { name: string }[]
31
+ * type T5 = InferFieldValue<ObjectField<"address", [TextField<"city">]>>; // { city: string }
32
+ * ```
33
+ */
34
+ export type InferFieldValue<F> = F extends TextField<string> ? string : F extends NumberField<string> ? number : F extends BooleanField<string> ? boolean : F extends StaticEnumField<string, infer O> ? O[number] : F extends DynamicEnumField<string, infer Source> ? DataSourceValueType<Source> : F extends DynamicSchemaField<string> ? Record<string, unknown> : F extends ArrayField<string, infer Items extends readonly FormElement[]> ? InferSchema<Items>[] : F extends ObjectField<string, infer Properties extends readonly FormElement[]> ? InferSchema<Properties> : never;
35
+ /**
36
+ * Extracts all fields from a single element (recursively).
37
+ *
38
+ * - Field elements return themselves
39
+ * - Groups extract fields from all child elements
40
+ * - Conditionals extract fields from all child elements
41
+ */
42
+ export type ExtractFields<E> = E extends AnyField ? E : E extends Group<infer Elements> ? ExtractFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractFieldsFromArray<Elements> : never;
43
+ /**
44
+ * Extracts fields from an array of elements.
45
+ *
46
+ * Recursively processes each element and unions the results.
47
+ */
48
+ export type ExtractFieldsFromArray<Elements> = Elements extends readonly [
49
+ infer First,
50
+ ...infer Rest
51
+ ] ? ExtractFields<First> | ExtractFieldsFromArray<Rest> : never;
52
+ /**
53
+ * Builds a schema type from extracted fields.
54
+ *
55
+ * Maps field names to their inferred value types.
56
+ */
57
+ export type BuildSchema<Fields> = {
58
+ [F in Fields as F extends {
59
+ name: infer N extends string;
60
+ } ? N : never]: F extends AnyField ? InferFieldValue<F> : never;
61
+ };
62
+ /**
63
+ * Infers the complete schema type from a form's elements.
64
+ *
65
+ * This is the main inference type that converts a form structure
66
+ * into its corresponding TypeScript schema type.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const form = formspec(
71
+ * field.text("name"),
72
+ * field.number("age"),
73
+ * field.enum("status", ["active", "inactive"] as const),
74
+ * );
75
+ *
76
+ * type Schema = InferSchema<typeof form.elements>;
77
+ * // { name: string; age: number; status: "active" | "inactive" }
78
+ * ```
79
+ */
80
+ export type InferSchema<Elements extends readonly FormElement[]> = BuildSchema<ExtractFieldsFromArray<Elements>>;
81
+ /**
82
+ * Infers the schema type from a FormSpec.
83
+ *
84
+ * Convenience type that extracts elements and infers the schema.
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const form = formspec(...);
89
+ * type Schema = InferFormSchema<typeof form>;
90
+ * ```
91
+ */
92
+ export type InferFormSchema<F extends FormSpec<readonly FormElement[]>> = F extends FormSpec<infer Elements> ? InferSchema<Elements> : never;
93
+ //# sourceMappingURL=inference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference.d.ts","sourceRoot":"","sources":["../src/inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,GACxD,MAAM,GACN,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,GAC3B,MAAM,GACN,CAAC,SAAS,YAAY,CAAC,MAAM,CAAC,GAC5B,OAAO,GACP,CAAC,SAAS,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACxC,CAAC,CAAC,MAAM,CAAC,GACT,CAAC,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,GAC9C,mBAAmB,CAAC,MAAM,CAAC,GAC3B,CAAC,SAAS,kBAAkB,CAAC,MAAM,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,SAAS,UAAU,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,SAAS,WAAW,EAAE,CAAC,GACtE,WAAW,CAAC,KAAK,CAAC,EAAE,GACpB,CAAC,SAAS,WAAW,CAAC,MAAM,EAAE,MAAM,UAAU,SAAS,SAAS,WAAW,EAAE,CAAC,GAC5E,WAAW,CAAC,UAAU,CAAC,GACvB,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,GAC7C,CAAC,GACD,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ,CAAC,GAC7B,sBAAsB,CAAC,QAAQ,CAAC,GAChC,CAAC,SAAS,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC,GACpD,sBAAsB,CAAC,QAAQ,CAAC,GAChC,KAAK,CAAC;AAEd;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,CAAC,QAAQ,IAAI,QAAQ,SAAS,SAAS;IACvE,MAAM,KAAK;IACX,GAAG,MAAM,IAAI;CACd,GACG,aAAa,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAAC,IAAI,CAAC,GACnD,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,WAAW,CAAC,MAAM,IAAI;KAC/B,CAAC,IAAI,MAAM,IAAI,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;KAAE,GACtD,CAAC,GACD,KAAK,GAAG,CAAC,SAAS,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK;CAC5D,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,IAAI,WAAW,CAC5E,sBAAsB,CAAC,QAAQ,CAAC,CACjC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,QAAQ,CAAC,SAAS,WAAW,EAAE,CAAC,IACpE,CAAC,SAAS,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type-level utilities for inferring schema types from form elements.
3
+ *
4
+ * These types allow TypeScript to automatically derive the form's schema type
5
+ * from its nested element structure.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=inference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference.js","sourceRoot":"","sources":["../src/inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Predicate builder functions for conditional logic.
3
+ *
4
+ * These functions create predicates for use with `when()`:
5
+ * - `is()` - Check if a field equals a specific value
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * when(is("status", "draft"),
10
+ * field.text("notes"),
11
+ * )
12
+ * ```
13
+ */
14
+ import type { EqualsPredicate } from "@formspec/core";
15
+ /**
16
+ * Creates an equality predicate that checks if a field equals a specific value.
17
+ *
18
+ * Use this with `when()` to create readable conditional expressions:
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Show cardNumber field when paymentMethod is "card"
23
+ * when(is("paymentMethod", "card"),
24
+ * field.text("cardNumber", { label: "Card Number" }),
25
+ * )
26
+ * ```
27
+ *
28
+ * @typeParam K - The field name (inferred as string literal)
29
+ * @typeParam V - The value type (inferred as literal)
30
+ * @param field - The name of the field to check
31
+ * @param value - The value the field must equal
32
+ * @returns An EqualsPredicate for use with `when()`
33
+ */
34
+ export declare function is<const K extends string, const V>(field: K, value: V): EqualsPredicate<K, V>;
35
+ //# sourceMappingURL=predicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,CAAC,EAChD,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,CAAC,GACP,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAMvB"}