@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.
- package/dist/__tests__/builders.test.d.ts +2 -0
- package/dist/__tests__/builders.test.d.ts.map +1 -0
- package/dist/__tests__/builders.test.js +167 -0
- package/dist/__tests__/builders.test.js.map +1 -0
- package/dist/__tests__/inference.test-d.d.ts +8 -0
- package/dist/__tests__/inference.test-d.d.ts.map +1 -0
- package/dist/__tests__/inference.test-d.js +76 -0
- package/dist/__tests__/inference.test-d.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +2 -0
- package/dist/__tests__/validation.test.d.ts.map +1 -0
- package/dist/__tests__/validation.test.js +180 -0
- package/dist/__tests__/validation.test.js.map +1 -0
- package/dist/field.d.ts +167 -0
- package/dist/field.d.ts.map +1 -0
- package/dist/field.js +221 -0
- package/dist/field.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +93 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +8 -0
- package/dist/inference.js.map +1 -0
- package/dist/predicate.d.ts +35 -0
- package/dist/predicate.d.ts.map +1 -0
- package/dist/predicate.js +40 -0
- package/dist/predicate.js.map +1 -0
- package/dist/structure.d.ts +120 -0
- package/dist/structure.d.ts.map +1 -0
- package/dist/structure.js +129 -0
- package/dist/structure.js.map +1 -0
- package/dist/validation.d.ts +66 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +186 -0
- package/dist/validation.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
/**
|
|
15
|
+
* Creates an equality predicate that checks if a field equals a specific value.
|
|
16
|
+
*
|
|
17
|
+
* Use this with `when()` to create readable conditional expressions:
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Show cardNumber field when paymentMethod is "card"
|
|
22
|
+
* when(is("paymentMethod", "card"),
|
|
23
|
+
* field.text("cardNumber", { label: "Card Number" }),
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @typeParam K - The field name (inferred as string literal)
|
|
28
|
+
* @typeParam V - The value type (inferred as literal)
|
|
29
|
+
* @param field - The name of the field to check
|
|
30
|
+
* @param value - The value the field must equal
|
|
31
|
+
* @returns An EqualsPredicate for use with `when()`
|
|
32
|
+
*/
|
|
33
|
+
export function is(field, value) {
|
|
34
|
+
return {
|
|
35
|
+
_predicate: "equals",
|
|
36
|
+
field,
|
|
37
|
+
value,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=predicate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate.js","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,EAAE,CAChB,KAAQ,EACR,KAAQ;IAER,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,KAAK;QACL,KAAK;KACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structure builder functions for organizing form elements.
|
|
3
|
+
*
|
|
4
|
+
* These functions create layout and conditional structures:
|
|
5
|
+
* - `group()` - Visual grouping of fields
|
|
6
|
+
* - `when()` - Conditional visibility based on field values
|
|
7
|
+
* - `formspec()` - Top-level form specification
|
|
8
|
+
*/
|
|
9
|
+
import type { FormElement, Group, Conditional, FormSpec, Predicate } from "@formspec/core";
|
|
10
|
+
/**
|
|
11
|
+
* Options for creating a form specification.
|
|
12
|
+
*/
|
|
13
|
+
export interface FormSpecOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to validate the form structure.
|
|
16
|
+
* - `true` or `"warn"`: Validate and log warnings/errors to console
|
|
17
|
+
* - `"throw"`: Validate and throw an error if validation fails
|
|
18
|
+
* - `false`: Skip validation (default in production for performance)
|
|
19
|
+
*
|
|
20
|
+
* @defaultValue false
|
|
21
|
+
*/
|
|
22
|
+
validate?: boolean | "warn" | "throw";
|
|
23
|
+
/**
|
|
24
|
+
* Optional name for the form (used in validation messages).
|
|
25
|
+
*/
|
|
26
|
+
name?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a visual group of form elements.
|
|
30
|
+
*
|
|
31
|
+
* Groups provide visual organization and can be rendered as fieldsets or sections.
|
|
32
|
+
* The nesting of groups defines the visual hierarchy of the form.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* group("Customer Information",
|
|
37
|
+
* field.text("name", { label: "Name" }),
|
|
38
|
+
* field.text("email", { label: "Email" }),
|
|
39
|
+
* )
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param label - The group's display label
|
|
43
|
+
* @param elements - The form elements contained in this group
|
|
44
|
+
* @returns A Group descriptor
|
|
45
|
+
*/
|
|
46
|
+
export declare function group<const Elements extends readonly FormElement[]>(label: string, ...elements: Elements): Group<Elements>;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a conditional wrapper that shows elements based on a predicate.
|
|
49
|
+
*
|
|
50
|
+
* When the predicate evaluates to true, the contained elements are shown.
|
|
51
|
+
* Otherwise, they are hidden (but still part of the schema).
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { is } from "@formspec/dsl";
|
|
56
|
+
*
|
|
57
|
+
* field.enum("status", ["draft", "sent", "paid"] as const),
|
|
58
|
+
* when(is("status", "draft"),
|
|
59
|
+
* field.text("internalNotes", { label: "Internal Notes" }),
|
|
60
|
+
* )
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @param predicate - The condition to evaluate (use `is()` to create)
|
|
64
|
+
* @param elements - The form elements to show when condition is met
|
|
65
|
+
* @returns A Conditional descriptor
|
|
66
|
+
*/
|
|
67
|
+
export declare function when<const K extends string, const V, const Elements extends readonly FormElement[]>(predicate: Predicate<K, V>, ...elements: Elements): Conditional<K, V, Elements>;
|
|
68
|
+
/**
|
|
69
|
+
* Creates a complete form specification.
|
|
70
|
+
*
|
|
71
|
+
* The structure IS the definition:
|
|
72
|
+
* - Nesting with `group()` defines visual layout
|
|
73
|
+
* - Nesting with `when()` defines conditional visibility
|
|
74
|
+
* - Field type implies control type (text field → text input)
|
|
75
|
+
* - Array position implies field ordering
|
|
76
|
+
*
|
|
77
|
+
* Schema is automatically inferred from all fields in the structure.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const InvoiceForm = formspec(
|
|
82
|
+
* group("Customer",
|
|
83
|
+
* field.text("customerName", { label: "Customer Name" }),
|
|
84
|
+
* field.dynamicEnum("country", "fetch_countries", { label: "Country" }),
|
|
85
|
+
* ),
|
|
86
|
+
* group("Invoice Details",
|
|
87
|
+
* field.number("amount", { label: "Amount", min: 0 }),
|
|
88
|
+
* field.enum("status", ["draft", "sent", "paid"] as const),
|
|
89
|
+
* when(is("status", "draft"),
|
|
90
|
+
* field.text("internalNotes", { label: "Internal Notes" }),
|
|
91
|
+
* ),
|
|
92
|
+
* ),
|
|
93
|
+
* );
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @param elements - The top-level form elements
|
|
97
|
+
* @returns A FormSpec descriptor
|
|
98
|
+
*/
|
|
99
|
+
export declare function formspec<const Elements extends readonly FormElement[]>(...elements: Elements): FormSpec<Elements>;
|
|
100
|
+
/**
|
|
101
|
+
* Creates a complete form specification with validation options.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const form = formspecWithValidation(
|
|
106
|
+
* { validate: true, name: "MyForm" },
|
|
107
|
+
* field.text("name"),
|
|
108
|
+
* field.enum("status", ["draft", "sent"] as const),
|
|
109
|
+
* when(is("status", "draft"),
|
|
110
|
+
* field.text("notes"),
|
|
111
|
+
* ),
|
|
112
|
+
* );
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @param options - Validation options
|
|
116
|
+
* @param elements - The top-level form elements
|
|
117
|
+
* @returns A FormSpec descriptor
|
|
118
|
+
*/
|
|
119
|
+
export declare function formspecWithValidation<const Elements extends readonly FormElement[]>(options: FormSpecOptions, ...elements: Elements): FormSpec<Elements>;
|
|
120
|
+
//# sourceMappingURL=structure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3F;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAEtC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,EACjE,KAAK,EAAE,MAAM,EACb,GAAG,QAAQ,EAAE,QAAQ,GACpB,KAAK,CAAC,QAAQ,CAAC,CAEjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,IAAI,CAClB,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,KAAK,CAAC,CAAC,EACP,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,EAE7C,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,GAAG,QAAQ,EAAE,QAAQ,GACpB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAO7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,QAAQ,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,EACpE,GAAG,QAAQ,EAAE,QAAQ,GACpB,QAAQ,CAAC,QAAQ,CAAC,CAEpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,EAClF,OAAO,EAAE,eAAe,EACxB,GAAG,QAAQ,EAAE,QAAQ,GACpB,QAAQ,CAAC,QAAQ,CAAC,CAmBpB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structure builder functions for organizing form elements.
|
|
3
|
+
*
|
|
4
|
+
* These functions create layout and conditional structures:
|
|
5
|
+
* - `group()` - Visual grouping of fields
|
|
6
|
+
* - `when()` - Conditional visibility based on field values
|
|
7
|
+
* - `formspec()` - Top-level form specification
|
|
8
|
+
*/
|
|
9
|
+
import { validateForm, logValidationIssues } from "./validation.js";
|
|
10
|
+
/**
|
|
11
|
+
* Creates a visual group of form elements.
|
|
12
|
+
*
|
|
13
|
+
* Groups provide visual organization and can be rendered as fieldsets or sections.
|
|
14
|
+
* The nesting of groups defines the visual hierarchy of the form.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* group("Customer Information",
|
|
19
|
+
* field.text("name", { label: "Name" }),
|
|
20
|
+
* field.text("email", { label: "Email" }),
|
|
21
|
+
* )
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param label - The group's display label
|
|
25
|
+
* @param elements - The form elements contained in this group
|
|
26
|
+
* @returns A Group descriptor
|
|
27
|
+
*/
|
|
28
|
+
export function group(label, ...elements) {
|
|
29
|
+
return { _type: "group", label, elements };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a conditional wrapper that shows elements based on a predicate.
|
|
33
|
+
*
|
|
34
|
+
* When the predicate evaluates to true, the contained elements are shown.
|
|
35
|
+
* Otherwise, they are hidden (but still part of the schema).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { is } from "@formspec/dsl";
|
|
40
|
+
*
|
|
41
|
+
* field.enum("status", ["draft", "sent", "paid"] as const),
|
|
42
|
+
* when(is("status", "draft"),
|
|
43
|
+
* field.text("internalNotes", { label: "Internal Notes" }),
|
|
44
|
+
* )
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @param predicate - The condition to evaluate (use `is()` to create)
|
|
48
|
+
* @param elements - The form elements to show when condition is met
|
|
49
|
+
* @returns A Conditional descriptor
|
|
50
|
+
*/
|
|
51
|
+
export function when(predicate, ...elements) {
|
|
52
|
+
return {
|
|
53
|
+
_type: "conditional",
|
|
54
|
+
field: predicate.field,
|
|
55
|
+
value: predicate.value,
|
|
56
|
+
elements,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates a complete form specification.
|
|
61
|
+
*
|
|
62
|
+
* The structure IS the definition:
|
|
63
|
+
* - Nesting with `group()` defines visual layout
|
|
64
|
+
* - Nesting with `when()` defines conditional visibility
|
|
65
|
+
* - Field type implies control type (text field → text input)
|
|
66
|
+
* - Array position implies field ordering
|
|
67
|
+
*
|
|
68
|
+
* Schema is automatically inferred from all fields in the structure.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const InvoiceForm = formspec(
|
|
73
|
+
* group("Customer",
|
|
74
|
+
* field.text("customerName", { label: "Customer Name" }),
|
|
75
|
+
* field.dynamicEnum("country", "fetch_countries", { label: "Country" }),
|
|
76
|
+
* ),
|
|
77
|
+
* group("Invoice Details",
|
|
78
|
+
* field.number("amount", { label: "Amount", min: 0 }),
|
|
79
|
+
* field.enum("status", ["draft", "sent", "paid"] as const),
|
|
80
|
+
* when(is("status", "draft"),
|
|
81
|
+
* field.text("internalNotes", { label: "Internal Notes" }),
|
|
82
|
+
* ),
|
|
83
|
+
* ),
|
|
84
|
+
* );
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @param elements - The top-level form elements
|
|
88
|
+
* @returns A FormSpec descriptor
|
|
89
|
+
*/
|
|
90
|
+
export function formspec(...elements) {
|
|
91
|
+
return { elements };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Creates a complete form specification with validation options.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const form = formspecWithValidation(
|
|
99
|
+
* { validate: true, name: "MyForm" },
|
|
100
|
+
* field.text("name"),
|
|
101
|
+
* field.enum("status", ["draft", "sent"] as const),
|
|
102
|
+
* when(is("status", "draft"),
|
|
103
|
+
* field.text("notes"),
|
|
104
|
+
* ),
|
|
105
|
+
* );
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @param options - Validation options
|
|
109
|
+
* @param elements - The top-level form elements
|
|
110
|
+
* @returns A FormSpec descriptor
|
|
111
|
+
*/
|
|
112
|
+
export function formspecWithValidation(options, ...elements) {
|
|
113
|
+
// Run validation if requested
|
|
114
|
+
if (options.validate) {
|
|
115
|
+
const result = validateForm(elements);
|
|
116
|
+
if (options.validate === "throw" && !result.valid) {
|
|
117
|
+
const errors = result.issues
|
|
118
|
+
.filter((i) => i.severity === "error")
|
|
119
|
+
.map((i) => i.message)
|
|
120
|
+
.join("; ");
|
|
121
|
+
throw new Error(`Form validation failed: ${errors}`);
|
|
122
|
+
}
|
|
123
|
+
if (options.validate === true || options.validate === "warn") {
|
|
124
|
+
logValidationIssues(result, options.name);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return { elements };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure.js","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAsBpE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,KAAK,CACnB,KAAa,EACb,GAAG,QAAkB;IAErB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,IAAI,CAKlB,SAA0B,EAC1B,GAAG,QAAkB;IAErB,OAAO;QACL,KAAK,EAAE,aAAa;QACpB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAG,QAAkB;IAErB,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAwB,EACxB,GAAG,QAAkB;IAErB,8BAA8B;IAC9B,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAEtC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM;iBACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;iBACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBACrB,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC7D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation for form specifications.
|
|
3
|
+
*
|
|
4
|
+
* Validates:
|
|
5
|
+
* - No duplicate field names at the same scope level
|
|
6
|
+
* - All field references in conditionals point to existing fields
|
|
7
|
+
*/
|
|
8
|
+
import type { FormElement } from "@formspec/core";
|
|
9
|
+
/**
|
|
10
|
+
* Validation issue severity levels.
|
|
11
|
+
*/
|
|
12
|
+
export type ValidationSeverity = "error" | "warning";
|
|
13
|
+
/**
|
|
14
|
+
* A validation issue found in a form specification.
|
|
15
|
+
*/
|
|
16
|
+
export interface ValidationIssue {
|
|
17
|
+
/** Severity of the issue */
|
|
18
|
+
severity: ValidationSeverity;
|
|
19
|
+
/** Human-readable message describing the issue */
|
|
20
|
+
message: string;
|
|
21
|
+
/** Path to the element with the issue (e.g., "group.fieldName") */
|
|
22
|
+
path: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Result of validating a form specification.
|
|
26
|
+
*/
|
|
27
|
+
export interface ValidationResult {
|
|
28
|
+
/** Whether the form is valid (no errors, warnings are ok) */
|
|
29
|
+
valid: boolean;
|
|
30
|
+
/** List of validation issues found */
|
|
31
|
+
issues: ValidationIssue[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validates a form specification for common issues.
|
|
35
|
+
*
|
|
36
|
+
* Checks for:
|
|
37
|
+
* - Duplicate field names at the root level (warning)
|
|
38
|
+
* - References to non-existent fields in conditionals (error)
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const form = formspec(
|
|
43
|
+
* field.text("name"),
|
|
44
|
+
* field.text("name"), // Duplicate!
|
|
45
|
+
* when("nonExistent", "value", // Reference to non-existent field!
|
|
46
|
+
* field.text("extra"),
|
|
47
|
+
* ),
|
|
48
|
+
* );
|
|
49
|
+
*
|
|
50
|
+
* const result = validateForm(form.elements);
|
|
51
|
+
* // result.valid === false
|
|
52
|
+
* // result.issues contains duplicate and reference errors
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param elements - The form elements to validate
|
|
56
|
+
* @returns Validation result with any issues found
|
|
57
|
+
*/
|
|
58
|
+
export declare function validateForm(elements: readonly FormElement[]): ValidationResult;
|
|
59
|
+
/**
|
|
60
|
+
* Logs validation issues to the console.
|
|
61
|
+
*
|
|
62
|
+
* @param result - The validation result to log
|
|
63
|
+
* @param formName - Optional name for the form (for better error messages)
|
|
64
|
+
*/
|
|
65
|
+
export declare function logValidationIssues(result: ValidationResult, formName?: string): void;
|
|
66
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAMZ,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,sCAAsC;IACtC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAuHD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,gBAAgB,CAmC/E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBrF"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation for form specifications.
|
|
3
|
+
*
|
|
4
|
+
* Validates:
|
|
5
|
+
* - No duplicate field names at the same scope level
|
|
6
|
+
* - All field references in conditionals point to existing fields
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Collects all field names from a list of form elements.
|
|
10
|
+
* Returns a Map of field name to count (for duplicate detection).
|
|
11
|
+
*/
|
|
12
|
+
function collectFieldNames(elements, path = "") {
|
|
13
|
+
const fieldNames = new Map();
|
|
14
|
+
function visit(elements, currentPath) {
|
|
15
|
+
for (const element of elements) {
|
|
16
|
+
switch (element._type) {
|
|
17
|
+
case "field": {
|
|
18
|
+
const field = element;
|
|
19
|
+
const fieldPath = currentPath ? `${currentPath}.${field.name}` : field.name;
|
|
20
|
+
const existing = fieldNames.get(field.name);
|
|
21
|
+
if (existing) {
|
|
22
|
+
existing.count++;
|
|
23
|
+
existing.paths.push(fieldPath);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
fieldNames.set(field.name, { count: 1, paths: [fieldPath] });
|
|
27
|
+
}
|
|
28
|
+
// Recurse into array items and object properties
|
|
29
|
+
if (field._field === "array") {
|
|
30
|
+
const arrayField = field;
|
|
31
|
+
visit(arrayField.items, `${fieldPath}[]`);
|
|
32
|
+
}
|
|
33
|
+
else if (field._field === "object") {
|
|
34
|
+
const objectField = field;
|
|
35
|
+
visit(objectField.properties, fieldPath);
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case "group": {
|
|
40
|
+
const group = element;
|
|
41
|
+
const groupPath = currentPath ? `${currentPath}.[${group.label}]` : `[${group.label}]`;
|
|
42
|
+
visit(group.elements, groupPath);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case "conditional": {
|
|
46
|
+
const conditional = element;
|
|
47
|
+
const conditionalPath = currentPath
|
|
48
|
+
? `${currentPath}.when(${conditional.field})`
|
|
49
|
+
: `when(${conditional.field})`;
|
|
50
|
+
visit(conditional.elements, conditionalPath);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
visit(elements, path);
|
|
57
|
+
return fieldNames;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Collects all field references from conditionals.
|
|
61
|
+
* Returns a list of { fieldName, path } for each reference.
|
|
62
|
+
*/
|
|
63
|
+
function collectConditionalReferences(elements, path = "") {
|
|
64
|
+
const references = [];
|
|
65
|
+
function visit(elements, currentPath) {
|
|
66
|
+
for (const element of elements) {
|
|
67
|
+
switch (element._type) {
|
|
68
|
+
case "field": {
|
|
69
|
+
const field = element;
|
|
70
|
+
const fieldPath = currentPath ? `${currentPath}.${field.name}` : field.name;
|
|
71
|
+
// Recurse into array items and object properties
|
|
72
|
+
if (field._field === "array") {
|
|
73
|
+
const arrayField = field;
|
|
74
|
+
visit(arrayField.items, `${fieldPath}[]`);
|
|
75
|
+
}
|
|
76
|
+
else if (field._field === "object") {
|
|
77
|
+
const objectField = field;
|
|
78
|
+
visit(objectField.properties, fieldPath);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "group": {
|
|
83
|
+
const group = element;
|
|
84
|
+
const groupPath = currentPath ? `${currentPath}.[${group.label}]` : `[${group.label}]`;
|
|
85
|
+
visit(group.elements, groupPath);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case "conditional": {
|
|
89
|
+
const conditional = element;
|
|
90
|
+
const conditionalPath = currentPath
|
|
91
|
+
? `${currentPath}.when(${conditional.field})`
|
|
92
|
+
: `when(${conditional.field})`;
|
|
93
|
+
// Record this reference
|
|
94
|
+
references.push({
|
|
95
|
+
fieldName: conditional.field,
|
|
96
|
+
path: conditionalPath,
|
|
97
|
+
});
|
|
98
|
+
// Continue visiting children
|
|
99
|
+
visit(conditional.elements, conditionalPath);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
visit(elements, path);
|
|
106
|
+
return references;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Validates a form specification for common issues.
|
|
110
|
+
*
|
|
111
|
+
* Checks for:
|
|
112
|
+
* - Duplicate field names at the root level (warning)
|
|
113
|
+
* - References to non-existent fields in conditionals (error)
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const form = formspec(
|
|
118
|
+
* field.text("name"),
|
|
119
|
+
* field.text("name"), // Duplicate!
|
|
120
|
+
* when("nonExistent", "value", // Reference to non-existent field!
|
|
121
|
+
* field.text("extra"),
|
|
122
|
+
* ),
|
|
123
|
+
* );
|
|
124
|
+
*
|
|
125
|
+
* const result = validateForm(form.elements);
|
|
126
|
+
* // result.valid === false
|
|
127
|
+
* // result.issues contains duplicate and reference errors
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @param elements - The form elements to validate
|
|
131
|
+
* @returns Validation result with any issues found
|
|
132
|
+
*/
|
|
133
|
+
export function validateForm(elements) {
|
|
134
|
+
const issues = [];
|
|
135
|
+
// Collect all field names
|
|
136
|
+
const fieldNames = collectFieldNames(elements);
|
|
137
|
+
// Check for duplicates at root level
|
|
138
|
+
for (const [name, info] of fieldNames) {
|
|
139
|
+
if (info.count > 1 && info.paths[0] !== undefined) {
|
|
140
|
+
issues.push({
|
|
141
|
+
severity: "warning",
|
|
142
|
+
message: `Duplicate field name "${name}" found ${info.count} times at: ${info.paths.join(", ")}`,
|
|
143
|
+
path: info.paths[0],
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Collect conditional references
|
|
148
|
+
const references = collectConditionalReferences(elements);
|
|
149
|
+
// Check that all referenced fields exist
|
|
150
|
+
for (const ref of references) {
|
|
151
|
+
if (!fieldNames.has(ref.fieldName)) {
|
|
152
|
+
issues.push({
|
|
153
|
+
severity: "error",
|
|
154
|
+
message: `Conditional references non-existent field "${ref.fieldName}"`,
|
|
155
|
+
path: ref.path,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
valid: issues.every((issue) => issue.severity !== "error"),
|
|
161
|
+
issues,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Logs validation issues to the console.
|
|
166
|
+
*
|
|
167
|
+
* @param result - The validation result to log
|
|
168
|
+
* @param formName - Optional name for the form (for better error messages)
|
|
169
|
+
*/
|
|
170
|
+
export function logValidationIssues(result, formName) {
|
|
171
|
+
if (result.issues.length === 0) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const prefix = formName ? `FormSpec "${formName}"` : "FormSpec";
|
|
175
|
+
for (const issue of result.issues) {
|
|
176
|
+
const location = issue.path ? ` at ${issue.path}` : "";
|
|
177
|
+
const message = `${prefix}: ${issue.message}${location}`;
|
|
178
|
+
if (issue.severity === "error") {
|
|
179
|
+
console.error(message);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
console.warn(message);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@formspec/dsl",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "DSL functions for defining FormSpec forms",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/dsl.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/dsl.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@formspec/core": "0.1.0-alpha.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"tsd": "^0.31.0",
|
|
22
|
+
"vitest": "^3.0.0"
|
|
23
|
+
},
|
|
24
|
+
"tsd": {
|
|
25
|
+
"directory": "src/__tests__"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [],
|
|
31
|
+
"license": "UNLICENSED",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"clean": "rm -rf dist temp",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:types": "tsd",
|
|
38
|
+
"api-extractor": "api-extractor run",
|
|
39
|
+
"api-extractor:local": "api-extractor run --local",
|
|
40
|
+
"api-documenter": "api-documenter markdown -i temp -o docs"
|
|
41
|
+
}
|
|
42
|
+
}
|