@formspec/constraints 0.1.0-alpha.10
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 +263 -0
- package/dist/__tests__/loader.test.d.ts +2 -0
- package/dist/__tests__/loader.test.d.ts.map +1 -0
- package/dist/__tests__/loader.test.js +133 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/__tests__/validators.test.d.ts +2 -0
- package/dist/__tests__/validators.test.d.ts.map +1 -0
- package/dist/__tests__/validators.test.js +404 -0
- package/dist/__tests__/validators.test.js.map +1 -0
- package/dist/browser.d.ts +51 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +65 -0
- package/dist/browser.js.map +1 -0
- package/dist/constraints.d.ts +544 -0
- package/dist/defaults.d.ts +15 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +106 -0
- package/dist/defaults.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +81 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +140 -0
- package/dist/loader.js.map +1 -0
- package/dist/types.d.ts +200 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validators/field-options.d.ts +49 -0
- package/dist/validators/field-options.d.ts.map +1 -0
- package/dist/validators/field-options.js +79 -0
- package/dist/validators/field-options.js.map +1 -0
- package/dist/validators/field-types.d.ts +38 -0
- package/dist/validators/field-types.d.ts.map +1 -0
- package/dist/validators/field-types.js +93 -0
- package/dist/validators/field-types.js.map +1 -0
- package/dist/validators/formspec.d.ts +54 -0
- package/dist/validators/formspec.d.ts.map +1 -0
- package/dist/validators/formspec.js +152 -0
- package/dist/validators/formspec.js.map +1 -0
- package/dist/validators/index.d.ts +5 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/index.js +5 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/validators/layout.d.ts +39 -0
- package/dist/validators/layout.d.ts.map +1 -0
- package/dist/validators/layout.js +107 -0
- package/dist/validators/layout.js.map +1 -0
- package/formspec.schema.json +245 -0
- package/package.json +57 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates field options against constraints.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Information about the field and its options
|
|
5
|
+
* @param constraints - Field option constraints
|
|
6
|
+
* @returns Array of validation issues (empty if valid)
|
|
7
|
+
*/
|
|
8
|
+
export function validateFieldOptions(context, constraints) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
for (const option of context.presentOptions) {
|
|
11
|
+
const severity = constraints[option];
|
|
12
|
+
if (severity && severity !== "off") {
|
|
13
|
+
issues.push(createFieldOptionIssue(context, option, severity));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return issues;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a validation issue for a disallowed field option.
|
|
20
|
+
*/
|
|
21
|
+
function createFieldOptionIssue(context, option, severity) {
|
|
22
|
+
const path = context.path ?? context.fieldName;
|
|
23
|
+
return {
|
|
24
|
+
code: "DISALLOWED_FIELD_OPTION",
|
|
25
|
+
message: `Field "${context.fieldName}" uses the "${option}" option, which is not allowed in this project`,
|
|
26
|
+
severity: severity === "error" ? "error" : "warning",
|
|
27
|
+
category: "fieldOptions",
|
|
28
|
+
path,
|
|
29
|
+
fieldName: context.fieldName,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extracts which options are present on a field object.
|
|
34
|
+
* Works with FormSpec field types.
|
|
35
|
+
*
|
|
36
|
+
* @param field - A field object with potential options
|
|
37
|
+
* @returns Array of present option names
|
|
38
|
+
*/
|
|
39
|
+
export function extractFieldOptions(field) {
|
|
40
|
+
const options = [];
|
|
41
|
+
if (field["label"] !== undefined)
|
|
42
|
+
options.push("label");
|
|
43
|
+
if (field["placeholder"] !== undefined)
|
|
44
|
+
options.push("placeholder");
|
|
45
|
+
if (field["required"] !== undefined)
|
|
46
|
+
options.push("required");
|
|
47
|
+
// NumberField uses "min"/"max" in core types, map to "minValue"/"maxValue" constraints
|
|
48
|
+
if (field["min"] !== undefined || field["minValue"] !== undefined)
|
|
49
|
+
options.push("minValue");
|
|
50
|
+
if (field["max"] !== undefined || field["maxValue"] !== undefined)
|
|
51
|
+
options.push("maxValue");
|
|
52
|
+
if (field["minItems"] !== undefined)
|
|
53
|
+
options.push("minItems");
|
|
54
|
+
if (field["maxItems"] !== undefined)
|
|
55
|
+
options.push("maxItems");
|
|
56
|
+
return options;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Checks if a specific field option is allowed.
|
|
60
|
+
*
|
|
61
|
+
* @param option - The option to check
|
|
62
|
+
* @param constraints - Field option constraints
|
|
63
|
+
* @returns true if allowed, false if disallowed
|
|
64
|
+
*/
|
|
65
|
+
export function isFieldOptionAllowed(option, constraints) {
|
|
66
|
+
const severity = constraints[option];
|
|
67
|
+
return !severity || severity === "off";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets the severity level for a field option.
|
|
71
|
+
*
|
|
72
|
+
* @param option - The option to check
|
|
73
|
+
* @param constraints - Field option constraints
|
|
74
|
+
* @returns Severity level, or "off" if not constrained
|
|
75
|
+
*/
|
|
76
|
+
export function getFieldOptionSeverity(option, constraints) {
|
|
77
|
+
return constraints[option] ?? "off";
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=field-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-options.js","sourceRoot":"","sources":["../../src/validators/field-options.ts"],"names":[],"mappings":"AA0BA;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA4B,EAC5B,WAAmC;IAEnC,MAAM,MAAM,GAAsB,EAAE,CAAC;IAErC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAC7B,OAA4B,EAC5B,MAAmB,EACnB,QAAkB;IAElB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,CAAC;IAC/C,OAAO;QACL,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,UAAU,OAAO,CAAC,SAAS,eAAe,MAAM,gDAAgD;QACzG,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACpD,QAAQ,EAAE,cAAc;QACxB,IAAI;QACJ,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA8B;IAChE,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpE,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,uFAAuF;IACvF,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5F,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5F,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE9D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAmB,EACnB,WAAmC;IAEnC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,IAAI,QAAQ,KAAK,KAAK,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAmB,EACnB,WAAmC;IAEnC,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { FieldTypeConstraints, Severity, ValidationIssue } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Context for field type validation.
|
|
4
|
+
*/
|
|
5
|
+
export interface FieldTypeContext {
|
|
6
|
+
/** The _field discriminator value (e.g., "text", "number", "enum") */
|
|
7
|
+
fieldType: string;
|
|
8
|
+
/** The field name */
|
|
9
|
+
fieldName: string;
|
|
10
|
+
/** Optional path for nested fields */
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Validates a field type against constraints.
|
|
15
|
+
*
|
|
16
|
+
* @param context - Information about the field being validated
|
|
17
|
+
* @param constraints - Field type constraints
|
|
18
|
+
* @returns Array of validation issues (empty if valid)
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateFieldTypes(context: FieldTypeContext, constraints: FieldTypeConstraints): ValidationIssue[];
|
|
21
|
+
/**
|
|
22
|
+
* Checks if a field type is allowed by the constraints.
|
|
23
|
+
* Useful for quick checks without generating issues.
|
|
24
|
+
*
|
|
25
|
+
* @param fieldType - The _field discriminator value
|
|
26
|
+
* @param constraints - Field type constraints
|
|
27
|
+
* @returns true if allowed, false if disallowed
|
|
28
|
+
*/
|
|
29
|
+
export declare function isFieldTypeAllowed(fieldType: string, constraints: FieldTypeConstraints): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the severity level for a field type.
|
|
32
|
+
*
|
|
33
|
+
* @param fieldType - The _field discriminator value
|
|
34
|
+
* @param constraints - Field type constraints
|
|
35
|
+
* @returns Severity level, or "off" if not constrained
|
|
36
|
+
*/
|
|
37
|
+
export declare function getFieldTypeSeverity(fieldType: string, constraints: FieldTypeConstraints): Severity;
|
|
38
|
+
//# sourceMappingURL=field-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-types.d.ts","sourceRoot":"","sources":["../../src/validators/field-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA8BnF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,gBAAgB,EACzB,WAAW,EAAE,oBAAoB,GAChC,eAAe,EAAE,CAgBnB;AAsBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,oBAAoB,GAAG,OAAO,CAQhG;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,oBAAoB,GAChC,QAAQ,CAOV"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps FormSpec field._field values to constraint config keys.
|
|
3
|
+
*/
|
|
4
|
+
const FIELD_TYPE_MAP = {
|
|
5
|
+
text: "text",
|
|
6
|
+
number: "number",
|
|
7
|
+
boolean: "boolean",
|
|
8
|
+
enum: "staticEnum",
|
|
9
|
+
dynamic_enum: "dynamicEnum",
|
|
10
|
+
dynamic_schema: "dynamicSchema",
|
|
11
|
+
array: "array",
|
|
12
|
+
object: "object",
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Human-readable names for field types.
|
|
16
|
+
*/
|
|
17
|
+
const FIELD_TYPE_NAMES = {
|
|
18
|
+
text: "text field",
|
|
19
|
+
number: "number field",
|
|
20
|
+
boolean: "boolean field",
|
|
21
|
+
enum: "static enum field",
|
|
22
|
+
dynamic_enum: "dynamic enum field",
|
|
23
|
+
dynamic_schema: "dynamic schema field",
|
|
24
|
+
array: "array field",
|
|
25
|
+
object: "object field",
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Validates a field type against constraints.
|
|
29
|
+
*
|
|
30
|
+
* @param context - Information about the field being validated
|
|
31
|
+
* @param constraints - Field type constraints
|
|
32
|
+
* @returns Array of validation issues (empty if valid)
|
|
33
|
+
*/
|
|
34
|
+
export function validateFieldTypes(context, constraints) {
|
|
35
|
+
const issues = [];
|
|
36
|
+
const constraintKey = FIELD_TYPE_MAP[context.fieldType];
|
|
37
|
+
if (!constraintKey) {
|
|
38
|
+
// Unknown field type, skip validation
|
|
39
|
+
return issues;
|
|
40
|
+
}
|
|
41
|
+
const severity = constraints[constraintKey];
|
|
42
|
+
if (severity && severity !== "off") {
|
|
43
|
+
const fieldTypeName = FIELD_TYPE_NAMES[context.fieldType] ?? context.fieldType;
|
|
44
|
+
issues.push(createFieldTypeIssue(context, fieldTypeName, severity));
|
|
45
|
+
}
|
|
46
|
+
return issues;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a validation issue for a disallowed field type.
|
|
50
|
+
*/
|
|
51
|
+
function createFieldTypeIssue(context, fieldTypeName, severity) {
|
|
52
|
+
const path = context.path ?? context.fieldName;
|
|
53
|
+
return {
|
|
54
|
+
code: "DISALLOWED_FIELD_TYPE",
|
|
55
|
+
message: `Field "${context.fieldName}" uses ${fieldTypeName}, which is not allowed in this project`,
|
|
56
|
+
severity: severity === "error" ? "error" : "warning",
|
|
57
|
+
category: "fieldTypes",
|
|
58
|
+
path,
|
|
59
|
+
fieldName: context.fieldName,
|
|
60
|
+
fieldType: context.fieldType,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Checks if a field type is allowed by the constraints.
|
|
65
|
+
* Useful for quick checks without generating issues.
|
|
66
|
+
*
|
|
67
|
+
* @param fieldType - The _field discriminator value
|
|
68
|
+
* @param constraints - Field type constraints
|
|
69
|
+
* @returns true if allowed, false if disallowed
|
|
70
|
+
*/
|
|
71
|
+
export function isFieldTypeAllowed(fieldType, constraints) {
|
|
72
|
+
const constraintKey = FIELD_TYPE_MAP[fieldType];
|
|
73
|
+
if (!constraintKey) {
|
|
74
|
+
return true; // Unknown types are allowed by default
|
|
75
|
+
}
|
|
76
|
+
const severity = constraints[constraintKey];
|
|
77
|
+
return !severity || severity === "off";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Gets the severity level for a field type.
|
|
81
|
+
*
|
|
82
|
+
* @param fieldType - The _field discriminator value
|
|
83
|
+
* @param constraints - Field type constraints
|
|
84
|
+
* @returns Severity level, or "off" if not constrained
|
|
85
|
+
*/
|
|
86
|
+
export function getFieldTypeSeverity(fieldType, constraints) {
|
|
87
|
+
const constraintKey = FIELD_TYPE_MAP[fieldType];
|
|
88
|
+
if (!constraintKey) {
|
|
89
|
+
return "off";
|
|
90
|
+
}
|
|
91
|
+
return constraints[constraintKey] ?? "off";
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=field-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-types.js","sourceRoot":"","sources":["../../src/validators/field-types.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,cAAc,GAA+C;IACjE,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,YAAY;IAClB,YAAY,EAAE,aAAa;IAC3B,cAAc,EAAE,eAAe;IAC/B,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,gBAAgB,GAA2B;IAC/C,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,eAAe;IACxB,IAAI,EAAE,mBAAmB;IACzB,YAAY,EAAE,oBAAoB;IAClC,cAAc,EAAE,sBAAsB;IACtC,KAAK,EAAE,aAAa;IACpB,MAAM,EAAE,cAAc;CACvB,CAAC;AAcF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAyB,EACzB,WAAiC;IAEjC,MAAM,MAAM,GAAsB,EAAE,CAAC;IAErC,MAAM,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,sCAAsC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,OAAyB,EACzB,aAAqB,EACrB,QAAkB;IAElB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,CAAC;IAC/C,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,UAAU,OAAO,CAAC,SAAS,UAAU,aAAa,wCAAwC;QACnG,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACpD,QAAQ,EAAE,YAAY;QACtB,IAAI;QACJ,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,WAAiC;IACrF,MAAM,aAAa,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,CAAC,uCAAuC;IACtD,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC5C,OAAO,CAAC,QAAQ,IAAI,QAAQ,KAAK,KAAK,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAAiB,EACjB,WAAiC;IAEjC,MAAM,aAAa,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,WAAW,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { FormElement, FormSpec } from "@formspec/core";
|
|
2
|
+
import type { ConstraintConfig, ValidationResult } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for validating FormSpec elements.
|
|
5
|
+
*/
|
|
6
|
+
export interface FormSpecValidationOptions {
|
|
7
|
+
/** Constraint configuration (will be merged with defaults) */
|
|
8
|
+
constraints?: ConstraintConfig;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validates FormSpec elements against constraints.
|
|
12
|
+
*
|
|
13
|
+
* This is the main entry point for validating a form specification
|
|
14
|
+
* against a constraint configuration. It walks through all elements
|
|
15
|
+
* and checks each one against the configured constraints.
|
|
16
|
+
*
|
|
17
|
+
* @param elements - FormSpec elements to validate
|
|
18
|
+
* @param options - Validation options including constraints
|
|
19
|
+
* @returns Validation result with all issues found
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { formspec, field, group } from '@formspec/dsl';
|
|
24
|
+
* import { validateFormSpecElements, defineConstraints } from '@formspec/constraints';
|
|
25
|
+
*
|
|
26
|
+
* const form = formspec(
|
|
27
|
+
* group("Contact",
|
|
28
|
+
* field.text("name"),
|
|
29
|
+
* field.dynamicEnum("country", "countries"),
|
|
30
|
+
* ),
|
|
31
|
+
* );
|
|
32
|
+
*
|
|
33
|
+
* const result = validateFormSpecElements(form.elements, {
|
|
34
|
+
* constraints: {
|
|
35
|
+
* fieldTypes: { dynamicEnum: 'error' },
|
|
36
|
+
* layout: { group: 'error' },
|
|
37
|
+
* },
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* if (!result.valid) {
|
|
41
|
+
* console.error('Validation failed:', result.issues);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateFormSpecElements(elements: readonly FormElement[], options?: FormSpecValidationOptions): ValidationResult;
|
|
46
|
+
/**
|
|
47
|
+
* Validates a complete FormSpec against constraints.
|
|
48
|
+
*
|
|
49
|
+
* @param formSpec - The FormSpec to validate
|
|
50
|
+
* @param options - Validation options including constraints
|
|
51
|
+
* @returns Validation result with all issues found
|
|
52
|
+
*/
|
|
53
|
+
export declare function validateFormSpec(formSpec: FormSpec<readonly FormElement[]>, options?: FormSpecValidationOptions): ValidationResult;
|
|
54
|
+
//# sourceMappingURL=formspec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formspec.d.ts","sourceRoot":"","sources":["../../src/validators/formspec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EACV,gBAAgB,EAGhB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,OAAO,GAAE,yBAA8B,GACtC,gBAAgB,CAWlB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,SAAS,WAAW,EAAE,CAAC,EAC1C,OAAO,GAAE,yBAA8B,GACtC,gBAAgB,CAElB"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { mergeWithDefaults } from "../defaults.js";
|
|
2
|
+
import { validateFieldTypes } from "./field-types.js";
|
|
3
|
+
import { validateLayout } from "./layout.js";
|
|
4
|
+
import { validateFieldOptions, extractFieldOptions } from "./field-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Validates FormSpec elements against constraints.
|
|
7
|
+
*
|
|
8
|
+
* This is the main entry point for validating a form specification
|
|
9
|
+
* against a constraint configuration. It walks through all elements
|
|
10
|
+
* and checks each one against the configured constraints.
|
|
11
|
+
*
|
|
12
|
+
* @param elements - FormSpec elements to validate
|
|
13
|
+
* @param options - Validation options including constraints
|
|
14
|
+
* @returns Validation result with all issues found
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { formspec, field, group } from '@formspec/dsl';
|
|
19
|
+
* import { validateFormSpecElements, defineConstraints } from '@formspec/constraints';
|
|
20
|
+
*
|
|
21
|
+
* const form = formspec(
|
|
22
|
+
* group("Contact",
|
|
23
|
+
* field.text("name"),
|
|
24
|
+
* field.dynamicEnum("country", "countries"),
|
|
25
|
+
* ),
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* const result = validateFormSpecElements(form.elements, {
|
|
29
|
+
* constraints: {
|
|
30
|
+
* fieldTypes: { dynamicEnum: 'error' },
|
|
31
|
+
* layout: { group: 'error' },
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* if (!result.valid) {
|
|
36
|
+
* console.error('Validation failed:', result.issues);
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function validateFormSpecElements(elements, options = {}) {
|
|
41
|
+
const constraints = mergeWithDefaults(options.constraints);
|
|
42
|
+
const issues = [];
|
|
43
|
+
// Walk through all elements
|
|
44
|
+
walkElements(elements, constraints, issues, "", 0);
|
|
45
|
+
return {
|
|
46
|
+
valid: !issues.some((issue) => issue.severity === "error"),
|
|
47
|
+
issues,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Validates a complete FormSpec against constraints.
|
|
52
|
+
*
|
|
53
|
+
* @param formSpec - The FormSpec to validate
|
|
54
|
+
* @param options - Validation options including constraints
|
|
55
|
+
* @returns Validation result with all issues found
|
|
56
|
+
*/
|
|
57
|
+
export function validateFormSpec(formSpec, options = {}) {
|
|
58
|
+
return validateFormSpecElements(formSpec.elements, options);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Recursively walks through FormSpec elements and validates each one.
|
|
62
|
+
*/
|
|
63
|
+
function walkElements(elements, constraints, issues, pathPrefix, depth) {
|
|
64
|
+
for (const element of elements) {
|
|
65
|
+
const elementPath = pathPrefix;
|
|
66
|
+
if (element._type === "field") {
|
|
67
|
+
validateField(element, constraints, issues, elementPath, depth);
|
|
68
|
+
}
|
|
69
|
+
else if (element._type === "group") {
|
|
70
|
+
validateGroup(element, constraints, issues, elementPath, depth);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// element._type === "conditional"
|
|
74
|
+
validateConditional(element, constraints, issues, elementPath, depth);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Validates a field element.
|
|
80
|
+
*/
|
|
81
|
+
function validateField(field, constraints, issues, pathPrefix, depth) {
|
|
82
|
+
const fieldPath = pathPrefix ? `${pathPrefix}/${field.name}` : field.name;
|
|
83
|
+
// Validate field type
|
|
84
|
+
const fieldTypeIssues = validateFieldTypes({
|
|
85
|
+
fieldType: field._field,
|
|
86
|
+
fieldName: field.name,
|
|
87
|
+
path: fieldPath,
|
|
88
|
+
}, constraints.fieldTypes);
|
|
89
|
+
issues.push(...fieldTypeIssues);
|
|
90
|
+
// Validate field options
|
|
91
|
+
const presentOptions = extractFieldOptions(field);
|
|
92
|
+
if (presentOptions.length > 0) {
|
|
93
|
+
const optionIssues = validateFieldOptions({
|
|
94
|
+
fieldName: field.name,
|
|
95
|
+
presentOptions,
|
|
96
|
+
path: fieldPath,
|
|
97
|
+
}, constraints.fieldOptions);
|
|
98
|
+
issues.push(...optionIssues);
|
|
99
|
+
}
|
|
100
|
+
// Check nesting depth for array/object fields
|
|
101
|
+
if (field._field === "array" || field._field === "object") {
|
|
102
|
+
const layoutIssues = validateLayout({
|
|
103
|
+
layoutType: "group", // Arrays/objects contribute to nesting depth
|
|
104
|
+
depth: depth + 1,
|
|
105
|
+
path: fieldPath,
|
|
106
|
+
}, constraints.layout);
|
|
107
|
+
// Only add nesting depth issues, not group issues
|
|
108
|
+
issues.push(...layoutIssues.filter((issue) => issue.code === "EXCEEDED_NESTING_DEPTH"));
|
|
109
|
+
// Recursively validate nested elements
|
|
110
|
+
if (field._field === "array" && "items" in field) {
|
|
111
|
+
walkElements(field.items, constraints, issues, `${fieldPath}[]`, depth + 1);
|
|
112
|
+
}
|
|
113
|
+
else if ("properties" in field) {
|
|
114
|
+
// field._field === "object"
|
|
115
|
+
walkElements(field.properties, constraints, issues, fieldPath, depth + 1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validates a group element.
|
|
121
|
+
*/
|
|
122
|
+
function validateGroup(group, constraints, issues, pathPrefix, depth) {
|
|
123
|
+
const groupPath = pathPrefix ? `${pathPrefix}/[group:${group.label}]` : `[group:${group.label}]`;
|
|
124
|
+
// Validate group usage
|
|
125
|
+
const layoutIssues = validateLayout({
|
|
126
|
+
layoutType: "group",
|
|
127
|
+
label: group.label,
|
|
128
|
+
depth,
|
|
129
|
+
path: groupPath,
|
|
130
|
+
}, constraints.layout);
|
|
131
|
+
issues.push(...layoutIssues);
|
|
132
|
+
// Recursively validate nested elements (groups don't increase nesting depth for schema)
|
|
133
|
+
walkElements(group.elements, constraints, issues, pathPrefix, depth);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validates a conditional element.
|
|
137
|
+
*/
|
|
138
|
+
function validateConditional(conditional, constraints, issues, pathPrefix, depth) {
|
|
139
|
+
const condPath = pathPrefix
|
|
140
|
+
? `${pathPrefix}/[when:${conditional.field}=${String(conditional.value)}]`
|
|
141
|
+
: `[when:${conditional.field}=${String(conditional.value)}]`;
|
|
142
|
+
// Validate conditional usage
|
|
143
|
+
const layoutIssues = validateLayout({
|
|
144
|
+
layoutType: "conditional",
|
|
145
|
+
depth,
|
|
146
|
+
path: condPath,
|
|
147
|
+
}, constraints.layout);
|
|
148
|
+
issues.push(...layoutIssues);
|
|
149
|
+
// Recursively validate nested elements
|
|
150
|
+
walkElements(conditional.elements, constraints, issues, pathPrefix, depth);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=formspec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formspec.js","sourceRoot":"","sources":["../../src/validators/formspec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { validateFieldTypes, type FieldTypeContext } from "./field-types.js";
|
|
2
|
+
export { validateLayout, type LayoutContext } from "./layout.js";
|
|
3
|
+
export { validateFieldOptions, type FieldOptionsContext } from "./field-options.js";
|
|
4
|
+
export { validateFormSpecElements, type FormSpecValidationOptions } from "./formspec.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,KAAK,yBAAyB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAyB,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAsB,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAA4B,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAkC,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { LayoutConstraints, ValidationIssue } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Context for layout validation.
|
|
4
|
+
*/
|
|
5
|
+
export interface LayoutContext {
|
|
6
|
+
/** The type of layout element ("group" | "conditional") */
|
|
7
|
+
layoutType: "group" | "conditional";
|
|
8
|
+
/** Optional label for the element (for groups) */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Current nesting depth */
|
|
11
|
+
depth: number;
|
|
12
|
+
/** Path to this element */
|
|
13
|
+
path?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validates a layout element against constraints.
|
|
17
|
+
*
|
|
18
|
+
* @param context - Information about the layout element
|
|
19
|
+
* @param constraints - Layout constraints
|
|
20
|
+
* @returns Array of validation issues (empty if valid)
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateLayout(context: LayoutContext, constraints: LayoutConstraints): ValidationIssue[];
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a layout type is allowed by the constraints.
|
|
25
|
+
*
|
|
26
|
+
* @param layoutType - The type of layout element
|
|
27
|
+
* @param constraints - Layout constraints
|
|
28
|
+
* @returns true if allowed, false if disallowed
|
|
29
|
+
*/
|
|
30
|
+
export declare function isLayoutTypeAllowed(layoutType: "group" | "conditional", constraints: LayoutConstraints): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a nesting depth is allowed.
|
|
33
|
+
*
|
|
34
|
+
* @param depth - Current nesting depth
|
|
35
|
+
* @param constraints - Layout constraints
|
|
36
|
+
* @returns true if allowed, false if exceeds limit
|
|
37
|
+
*/
|
|
38
|
+
export declare function isNestingDepthAllowed(depth: number, constraints: LayoutConstraints): boolean;
|
|
39
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/validators/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAY,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,UAAU,EAAE,OAAO,GAAG,aAAa,CAAC;IACpC,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,iBAAiB,GAC7B,eAAe,EAAE,CA0BnB;AAmDD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,OAAO,GAAG,aAAa,EACnC,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAST;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAM5F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a layout element against constraints.
|
|
3
|
+
*
|
|
4
|
+
* @param context - Information about the layout element
|
|
5
|
+
* @param constraints - Layout constraints
|
|
6
|
+
* @returns Array of validation issues (empty if valid)
|
|
7
|
+
*/
|
|
8
|
+
export function validateLayout(context, constraints) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
// Check if groups are allowed
|
|
11
|
+
if (context.layoutType === "group") {
|
|
12
|
+
const groupSeverity = constraints.group;
|
|
13
|
+
if (groupSeverity && groupSeverity !== "off") {
|
|
14
|
+
issues.push(createGroupIssue(context, groupSeverity));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Check if conditionals are allowed
|
|
18
|
+
if (context.layoutType === "conditional") {
|
|
19
|
+
const conditionalSeverity = constraints.conditionals;
|
|
20
|
+
if (conditionalSeverity && conditionalSeverity !== "off") {
|
|
21
|
+
issues.push(createConditionalIssue(context, conditionalSeverity));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Check nesting depth (applies to both groups and fields within nested structures)
|
|
25
|
+
const maxDepth = constraints.maxNestingDepth;
|
|
26
|
+
if (maxDepth !== undefined && context.depth > maxDepth) {
|
|
27
|
+
issues.push(createNestingDepthIssue(context, maxDepth));
|
|
28
|
+
}
|
|
29
|
+
return issues;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a validation issue for a disallowed group.
|
|
33
|
+
*/
|
|
34
|
+
function createGroupIssue(context, severity) {
|
|
35
|
+
const labelInfo = context.label ? ` "${context.label}"` : "";
|
|
36
|
+
const issue = {
|
|
37
|
+
code: "DISALLOWED_GROUP",
|
|
38
|
+
message: `Group${labelInfo} is not allowed - visual grouping is not supported in this project`,
|
|
39
|
+
severity: severity === "error" ? "error" : "warning",
|
|
40
|
+
category: "layout",
|
|
41
|
+
};
|
|
42
|
+
if (context.path !== undefined) {
|
|
43
|
+
issue.path = context.path;
|
|
44
|
+
}
|
|
45
|
+
return issue;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a validation issue for a disallowed conditional.
|
|
49
|
+
*/
|
|
50
|
+
function createConditionalIssue(context, severity) {
|
|
51
|
+
const issue = {
|
|
52
|
+
code: "DISALLOWED_CONDITIONAL",
|
|
53
|
+
message: `Conditional visibility (when/is) is not allowed in this project`,
|
|
54
|
+
severity: severity === "error" ? "error" : "warning",
|
|
55
|
+
category: "layout",
|
|
56
|
+
};
|
|
57
|
+
if (context.path !== undefined) {
|
|
58
|
+
issue.path = context.path;
|
|
59
|
+
}
|
|
60
|
+
return issue;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Creates a validation issue for exceeding nesting depth.
|
|
64
|
+
*/
|
|
65
|
+
function createNestingDepthIssue(context, maxDepth) {
|
|
66
|
+
const issue = {
|
|
67
|
+
code: "EXCEEDED_NESTING_DEPTH",
|
|
68
|
+
message: `Nesting depth ${String(context.depth)} exceeds maximum allowed depth of ${String(maxDepth)}`,
|
|
69
|
+
severity: "error",
|
|
70
|
+
category: "layout",
|
|
71
|
+
};
|
|
72
|
+
if (context.path !== undefined) {
|
|
73
|
+
issue.path = context.path;
|
|
74
|
+
}
|
|
75
|
+
return issue;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Checks if a layout type is allowed by the constraints.
|
|
79
|
+
*
|
|
80
|
+
* @param layoutType - The type of layout element
|
|
81
|
+
* @param constraints - Layout constraints
|
|
82
|
+
* @returns true if allowed, false if disallowed
|
|
83
|
+
*/
|
|
84
|
+
export function isLayoutTypeAllowed(layoutType, constraints) {
|
|
85
|
+
if (layoutType === "group") {
|
|
86
|
+
const severity = constraints.group;
|
|
87
|
+
return !severity || severity === "off";
|
|
88
|
+
}
|
|
89
|
+
// layoutType === "conditional"
|
|
90
|
+
const severity = constraints.conditionals;
|
|
91
|
+
return !severity || severity === "off";
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Checks if a nesting depth is allowed.
|
|
95
|
+
*
|
|
96
|
+
* @param depth - Current nesting depth
|
|
97
|
+
* @param constraints - Layout constraints
|
|
98
|
+
* @returns true if allowed, false if exceeds limit
|
|
99
|
+
*/
|
|
100
|
+
export function isNestingDepthAllowed(depth, constraints) {
|
|
101
|
+
const maxDepth = constraints.maxNestingDepth;
|
|
102
|
+
if (maxDepth === undefined) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return depth <= maxDepth;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/validators/layout.ts"],"names":[],"mappings":"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"}
|