@formspec/dsl 0.1.0-alpha.2 → 0.1.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,186 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}