@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.
- package/README.md +61 -0
- package/dist/dsl.d.ts +665 -0
- package/dist/field.d.ts +15 -1
- package/dist/field.d.ts.map +1 -1
- package/dist/index.cjs +446 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +411 -38
- package/dist/index.js.map +1 -1
- package/dist/inference.d.ts +122 -1
- package/dist/inference.d.ts.map +1 -1
- package/dist/predicate.d.ts +1 -0
- package/dist/predicate.d.ts.map +1 -1
- package/dist/structure.d.ts +10 -0
- package/dist/structure.d.ts.map +1 -1
- package/dist/validation.d.ts +10 -0
- package/dist/validation.d.ts.map +1 -1
- package/package.json +9 -6
- package/dist/__tests__/builders.test.js +0 -193
- package/dist/__tests__/builders.test.js.map +0 -1
- package/dist/__tests__/inference.test-d.js +0 -83
- package/dist/__tests__/inference.test-d.js.map +0 -1
- package/dist/__tests__/validation.test.js +0 -180
- package/dist/__tests__/validation.test.js.map +0 -1
- package/dist/field.js +0 -221
- package/dist/field.js.map +0 -1
- package/dist/inference.js +0 -8
- package/dist/inference.js.map +0 -1
- package/dist/predicate.js +0 -40
- package/dist/predicate.js.map +0 -1
- package/dist/structure.js +0 -129
- package/dist/structure.js.map +0 -1
- package/dist/validation.js +0 -186
- package/dist/validation.js.map +0 -1
package/dist/validation.js
DELETED
|
@@ -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
|
package/dist/validation.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|