@formspec/constraints 0.1.0-alpha.7
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 +265 -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,544 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @formspec/constraints
|
|
3
|
+
*
|
|
4
|
+
* Constraint validation for FormSpec - restrict features based on target
|
|
5
|
+
* environment capabilities.
|
|
6
|
+
*
|
|
7
|
+
* This package provides:
|
|
8
|
+
* - Type definitions for constraint configuration
|
|
9
|
+
* - YAML/TypeScript config file loading
|
|
10
|
+
* - Core validation logic for FormSpec elements
|
|
11
|
+
* - JSON Schema for .formspec.yml validation
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { loadConfig, validateFormSpecElements } from '@formspec/constraints';
|
|
16
|
+
* import { formspec, field } from '@formspec/dsl';
|
|
17
|
+
*
|
|
18
|
+
* // Load constraints from .formspec.yml
|
|
19
|
+
* const { config } = await loadConfig();
|
|
20
|
+
*
|
|
21
|
+
* // Create a form
|
|
22
|
+
* const form = formspec(
|
|
23
|
+
* field.text("name"),
|
|
24
|
+
* field.dynamicEnum("country", "countries"),
|
|
25
|
+
* );
|
|
26
|
+
*
|
|
27
|
+
* // Validate against constraints
|
|
28
|
+
* const result = validateFormSpecElements(form.elements, { constraints: config });
|
|
29
|
+
*
|
|
30
|
+
* if (!result.valid) {
|
|
31
|
+
* console.error('Validation failed:', result.issues);
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @packageDocumentation
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { FormElement } from '@formspec/core';
|
|
39
|
+
import type { FormSpec } from '@formspec/core';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Complete constraint configuration for a FormSpec project.
|
|
43
|
+
*/
|
|
44
|
+
export declare interface ConstraintConfig {
|
|
45
|
+
/** Field type constraints */
|
|
46
|
+
fieldTypes?: FieldTypeConstraints;
|
|
47
|
+
/** Layout and structure constraints */
|
|
48
|
+
layout?: LayoutConstraints;
|
|
49
|
+
/** UI Schema feature constraints */
|
|
50
|
+
uiSchema?: UISchemaConstraints;
|
|
51
|
+
/** Field configuration option constraints */
|
|
52
|
+
fieldOptions?: FieldOptionConstraints;
|
|
53
|
+
/** Control options constraints */
|
|
54
|
+
controlOptions?: ControlOptionConstraints;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Control options constraints - control which JSONForms Control.options are allowed.
|
|
59
|
+
* These are renderer-specific options that may not be universally supported.
|
|
60
|
+
*/
|
|
61
|
+
export declare interface ControlOptionConstraints {
|
|
62
|
+
/** format - renderer format hint (e.g., "radio", "textarea") */
|
|
63
|
+
format?: Severity;
|
|
64
|
+
/** readonly - read-only mode */
|
|
65
|
+
readonly?: Severity;
|
|
66
|
+
/** multi - multi-select for enums */
|
|
67
|
+
multi?: Severity;
|
|
68
|
+
/** showUnfocusedDescription - show description when unfocused */
|
|
69
|
+
showUnfocusedDescription?: Severity;
|
|
70
|
+
/** hideRequiredAsterisk - hide required indicator */
|
|
71
|
+
hideRequiredAsterisk?: Severity;
|
|
72
|
+
/** Custom control options (extensible dictionary) */
|
|
73
|
+
custom?: Record<string, Severity>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Default FormSpec configuration.
|
|
78
|
+
*/
|
|
79
|
+
export declare const DEFAULT_CONFIG: FormSpecConfig;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Default constraint configuration that allows all features.
|
|
83
|
+
* All constraints default to "off" (allowed).
|
|
84
|
+
*/
|
|
85
|
+
export declare const DEFAULT_CONSTRAINTS: ResolvedConstraintConfig;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates a constraint configuration directly from an object.
|
|
89
|
+
* Useful for programmatic configuration without YAML.
|
|
90
|
+
*
|
|
91
|
+
* @param config - Partial constraint configuration
|
|
92
|
+
* @returns Complete configuration with defaults applied
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const config = defineConstraints({
|
|
97
|
+
* fieldTypes: {
|
|
98
|
+
* dynamicEnum: 'error',
|
|
99
|
+
* dynamicSchema: 'error',
|
|
100
|
+
* },
|
|
101
|
+
* layout: {
|
|
102
|
+
* group: 'error',
|
|
103
|
+
* },
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function defineConstraints(config: ConstraintConfig): ResolvedConstraintConfig;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Extracts which options are present on a field object.
|
|
111
|
+
* Works with FormSpec field types.
|
|
112
|
+
*
|
|
113
|
+
* @param field - A field object with potential options
|
|
114
|
+
* @returns Array of present option names
|
|
115
|
+
*/
|
|
116
|
+
export declare function extractFieldOptions(field: Record<string, unknown>): FieldOption[];
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Known field options that can be validated.
|
|
120
|
+
*/
|
|
121
|
+
export declare type FieldOption = "label" | "placeholder" | "required" | "minValue" | "maxValue" | "minItems" | "maxItems";
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Field configuration option constraints - control which field options are allowed.
|
|
125
|
+
*/
|
|
126
|
+
export declare interface FieldOptionConstraints {
|
|
127
|
+
/** label - field label text */
|
|
128
|
+
label?: Severity;
|
|
129
|
+
/** placeholder - input placeholder text */
|
|
130
|
+
placeholder?: Severity;
|
|
131
|
+
/** required - whether field is required */
|
|
132
|
+
required?: Severity;
|
|
133
|
+
/** minValue - minimum value for numbers */
|
|
134
|
+
minValue?: Severity;
|
|
135
|
+
/** maxValue - maximum value for numbers */
|
|
136
|
+
maxValue?: Severity;
|
|
137
|
+
/** minItems - minimum array length */
|
|
138
|
+
minItems?: Severity;
|
|
139
|
+
/** maxItems - maximum array length */
|
|
140
|
+
maxItems?: Severity;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Context for field option validation.
|
|
145
|
+
*/
|
|
146
|
+
export declare interface FieldOptionsContext {
|
|
147
|
+
/** The field name */
|
|
148
|
+
fieldName: string;
|
|
149
|
+
/** Which options are present on this field */
|
|
150
|
+
presentOptions: FieldOption[];
|
|
151
|
+
/** Path to this field */
|
|
152
|
+
path?: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Field type constraints - control which field types are allowed.
|
|
157
|
+
* Fine-grained control over each DSL field builder.
|
|
158
|
+
*/
|
|
159
|
+
export declare interface FieldTypeConstraints {
|
|
160
|
+
/** field.text() - basic text input */
|
|
161
|
+
text?: Severity;
|
|
162
|
+
/** field.number() - numeric input */
|
|
163
|
+
number?: Severity;
|
|
164
|
+
/** field.boolean() - checkbox/toggle */
|
|
165
|
+
boolean?: Severity;
|
|
166
|
+
/** field.enum() with literal options */
|
|
167
|
+
staticEnum?: Severity;
|
|
168
|
+
/** field.dynamicEnum() - runtime-fetched options */
|
|
169
|
+
dynamicEnum?: Severity;
|
|
170
|
+
/** field.dynamicSchema() - runtime-fetched schema */
|
|
171
|
+
dynamicSchema?: Severity;
|
|
172
|
+
/** field.array() / field.arrayWithConfig() */
|
|
173
|
+
array?: Severity;
|
|
174
|
+
/** field.object() / field.objectWithConfig() */
|
|
175
|
+
object?: Severity;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Context for field type validation.
|
|
180
|
+
*/
|
|
181
|
+
export declare interface FieldTypeContext {
|
|
182
|
+
/** The _field discriminator value (e.g., "text", "number", "enum") */
|
|
183
|
+
fieldType: string;
|
|
184
|
+
/** The field name */
|
|
185
|
+
fieldName: string;
|
|
186
|
+
/** Optional path for nested fields */
|
|
187
|
+
path?: string;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Top-level FormSpec configuration file structure.
|
|
192
|
+
* The .formspec.yml file uses this structure.
|
|
193
|
+
*/
|
|
194
|
+
export declare interface FormSpecConfig {
|
|
195
|
+
/** Constraint configuration */
|
|
196
|
+
constraints?: ConstraintConfig;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Options for validating FormSpec elements.
|
|
201
|
+
*/
|
|
202
|
+
export declare interface FormSpecValidationOptions {
|
|
203
|
+
/** Constraint configuration (will be merged with defaults) */
|
|
204
|
+
constraints?: ConstraintConfig;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Gets the severity level for a field option.
|
|
209
|
+
*
|
|
210
|
+
* @param option - The option to check
|
|
211
|
+
* @param constraints - Field option constraints
|
|
212
|
+
* @returns Severity level, or "off" if not constrained
|
|
213
|
+
*/
|
|
214
|
+
export declare function getFieldOptionSeverity(option: FieldOption, constraints: FieldOptionConstraints): Severity;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Gets the severity level for a field type.
|
|
218
|
+
*
|
|
219
|
+
* @param fieldType - The _field discriminator value
|
|
220
|
+
* @param constraints - Field type constraints
|
|
221
|
+
* @returns Severity level, or "off" if not constrained
|
|
222
|
+
*/
|
|
223
|
+
export declare function getFieldTypeSeverity(fieldType: string, constraints: FieldTypeConstraints): Severity;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Checks if a specific field option is allowed.
|
|
227
|
+
*
|
|
228
|
+
* @param option - The option to check
|
|
229
|
+
* @param constraints - Field option constraints
|
|
230
|
+
* @returns true if allowed, false if disallowed
|
|
231
|
+
*/
|
|
232
|
+
export declare function isFieldOptionAllowed(option: FieldOption, constraints: FieldOptionConstraints): boolean;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Checks if a field type is allowed by the constraints.
|
|
236
|
+
* Useful for quick checks without generating issues.
|
|
237
|
+
*
|
|
238
|
+
* @param fieldType - The _field discriminator value
|
|
239
|
+
* @param constraints - Field type constraints
|
|
240
|
+
* @returns true if allowed, false if disallowed
|
|
241
|
+
*/
|
|
242
|
+
export declare function isFieldTypeAllowed(fieldType: string, constraints: FieldTypeConstraints): boolean;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Checks if a layout type is allowed by the constraints.
|
|
246
|
+
*
|
|
247
|
+
* @param layoutType - The type of layout element
|
|
248
|
+
* @param constraints - Layout constraints
|
|
249
|
+
* @returns true if allowed, false if disallowed
|
|
250
|
+
*/
|
|
251
|
+
export declare function isLayoutTypeAllowed(layoutType: "group" | "conditional", constraints: LayoutConstraints): boolean;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Checks if a nesting depth is allowed.
|
|
255
|
+
*
|
|
256
|
+
* @param depth - Current nesting depth
|
|
257
|
+
* @param constraints - Layout constraints
|
|
258
|
+
* @returns true if allowed, false if exceeds limit
|
|
259
|
+
*/
|
|
260
|
+
export declare function isNestingDepthAllowed(depth: number, constraints: LayoutConstraints): boolean;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Layout and structure constraints - control grouping, conditionals, nesting.
|
|
264
|
+
*/
|
|
265
|
+
export declare interface LayoutConstraints {
|
|
266
|
+
/** group() - visual grouping of fields */
|
|
267
|
+
group?: Severity;
|
|
268
|
+
/** when() - conditional field visibility */
|
|
269
|
+
conditionals?: Severity;
|
|
270
|
+
/** Maximum nesting depth for objects/arrays (0 = flat only) */
|
|
271
|
+
maxNestingDepth?: number;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Context for layout validation.
|
|
276
|
+
*/
|
|
277
|
+
export declare interface LayoutContext {
|
|
278
|
+
/** The type of layout element ("group" | "conditional") */
|
|
279
|
+
layoutType: "group" | "conditional";
|
|
280
|
+
/** Optional label for the element (for groups) */
|
|
281
|
+
label?: string;
|
|
282
|
+
/** Current nesting depth */
|
|
283
|
+
depth: number;
|
|
284
|
+
/** Path to this element */
|
|
285
|
+
path?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* JSONForms layout type constraints.
|
|
290
|
+
*/
|
|
291
|
+
export declare interface LayoutTypeConstraints {
|
|
292
|
+
/** VerticalLayout - stack elements vertically */
|
|
293
|
+
VerticalLayout?: Severity;
|
|
294
|
+
/** HorizontalLayout - arrange elements horizontally */
|
|
295
|
+
HorizontalLayout?: Severity;
|
|
296
|
+
/** Group - visual grouping with label */
|
|
297
|
+
Group?: Severity;
|
|
298
|
+
/** Categorization - tabbed/wizard interface */
|
|
299
|
+
Categorization?: Severity;
|
|
300
|
+
/** Category - individual tab/step in Categorization */
|
|
301
|
+
Category?: Severity;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Loads FormSpec constraint configuration from a .formspec.yml file.
|
|
306
|
+
*
|
|
307
|
+
* @param options - Options for loading configuration
|
|
308
|
+
* @returns The loaded configuration with defaults applied
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```ts
|
|
312
|
+
* // Load from current directory (searches for .formspec.yml)
|
|
313
|
+
* const result = await loadConfig();
|
|
314
|
+
*
|
|
315
|
+
* // Load from specific directory
|
|
316
|
+
* const result = await loadConfig({ cwd: '/path/to/project' });
|
|
317
|
+
*
|
|
318
|
+
* // Load from specific file
|
|
319
|
+
* const result = await loadConfig({ configPath: '/path/to/config.yml' });
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
export declare function loadConfig(options?: LoadConfigOptions): Promise<LoadConfigResult>;
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Synchronously loads config from a pre-parsed YAML string.
|
|
326
|
+
* Useful for testing or when config is already available.
|
|
327
|
+
*
|
|
328
|
+
* @param yamlContent - The YAML content to parse
|
|
329
|
+
* @returns The parsed and merged configuration
|
|
330
|
+
*/
|
|
331
|
+
export declare function loadConfigFromString(yamlContent: string): ResolvedConstraintConfig;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Options for loading configuration.
|
|
335
|
+
*/
|
|
336
|
+
export declare interface LoadConfigOptions {
|
|
337
|
+
/**
|
|
338
|
+
* The directory to search for config files.
|
|
339
|
+
* Defaults to process.cwd().
|
|
340
|
+
*/
|
|
341
|
+
cwd?: string;
|
|
342
|
+
/**
|
|
343
|
+
* Explicit path to a config file.
|
|
344
|
+
* If provided, skips searching for default config file names.
|
|
345
|
+
*/
|
|
346
|
+
configPath?: string;
|
|
347
|
+
/**
|
|
348
|
+
* Whether to search parent directories for config files.
|
|
349
|
+
* Defaults to true.
|
|
350
|
+
*/
|
|
351
|
+
searchParents?: boolean;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Result of loading configuration.
|
|
356
|
+
*/
|
|
357
|
+
export declare interface LoadConfigResult {
|
|
358
|
+
/** The loaded and merged configuration */
|
|
359
|
+
config: ResolvedConstraintConfig;
|
|
360
|
+
/** The path to the config file that was loaded (if any) */
|
|
361
|
+
configPath: string | null;
|
|
362
|
+
/** Whether a config file was found */
|
|
363
|
+
found: boolean;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Merges user constraints with defaults, filling in any missing values.
|
|
368
|
+
*/
|
|
369
|
+
export declare function mergeWithDefaults(config: ConstraintConfig | undefined): ResolvedConstraintConfig;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Fully resolved constraint configuration with all properties required.
|
|
373
|
+
* This is the type returned by mergeWithDefaults().
|
|
374
|
+
*/
|
|
375
|
+
export declare interface ResolvedConstraintConfig {
|
|
376
|
+
fieldTypes: Required<FieldTypeConstraints>;
|
|
377
|
+
layout: Required<LayoutConstraints>;
|
|
378
|
+
uiSchema: ResolvedUISchemaConstraints;
|
|
379
|
+
fieldOptions: Required<FieldOptionConstraints>;
|
|
380
|
+
controlOptions: Required<ControlOptionConstraints>;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Fully resolved rule constraints with all properties required.
|
|
385
|
+
*/
|
|
386
|
+
export declare interface ResolvedRuleConstraints {
|
|
387
|
+
enabled: Severity;
|
|
388
|
+
effects: Required<RuleEffectConstraints>;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Fully resolved UI schema constraints with all properties required.
|
|
393
|
+
*/
|
|
394
|
+
export declare interface ResolvedUISchemaConstraints {
|
|
395
|
+
layouts: Required<LayoutTypeConstraints>;
|
|
396
|
+
rules: ResolvedRuleConstraints;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* JSONForms rule constraints.
|
|
401
|
+
*/
|
|
402
|
+
export declare interface RuleConstraints {
|
|
403
|
+
/** Whether rules are enabled at all */
|
|
404
|
+
enabled?: Severity;
|
|
405
|
+
/** Fine-grained control over rule effects */
|
|
406
|
+
effects?: RuleEffectConstraints;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* JSONForms rule effect constraints.
|
|
411
|
+
*/
|
|
412
|
+
export declare interface RuleEffectConstraints {
|
|
413
|
+
/** SHOW - show element when condition is true */
|
|
414
|
+
SHOW?: Severity;
|
|
415
|
+
/** HIDE - hide element when condition is true */
|
|
416
|
+
HIDE?: Severity;
|
|
417
|
+
/** ENABLE - enable element when condition is true */
|
|
418
|
+
ENABLE?: Severity;
|
|
419
|
+
/** DISABLE - disable element when condition is true */
|
|
420
|
+
DISABLE?: Severity;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Severity level for constraint violations.
|
|
425
|
+
* - "error": Violation fails validation
|
|
426
|
+
* - "warn": Violation emits warning but passes
|
|
427
|
+
* - "off": Feature is allowed (no violation)
|
|
428
|
+
*/
|
|
429
|
+
export declare type Severity = "error" | "warn" | "off";
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* UI Schema feature constraints - control JSONForms-specific features.
|
|
433
|
+
*/
|
|
434
|
+
export declare interface UISchemaConstraints {
|
|
435
|
+
/** Layout type constraints */
|
|
436
|
+
layouts?: LayoutTypeConstraints;
|
|
437
|
+
/** Rule (conditional) constraints */
|
|
438
|
+
rules?: RuleConstraints;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Validates field options against constraints.
|
|
443
|
+
*
|
|
444
|
+
* @param context - Information about the field and its options
|
|
445
|
+
* @param constraints - Field option constraints
|
|
446
|
+
* @returns Array of validation issues (empty if valid)
|
|
447
|
+
*/
|
|
448
|
+
export declare function validateFieldOptions(context: FieldOptionsContext, constraints: FieldOptionConstraints): ValidationIssue[];
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Validates a field type against constraints.
|
|
452
|
+
*
|
|
453
|
+
* @param context - Information about the field being validated
|
|
454
|
+
* @param constraints - Field type constraints
|
|
455
|
+
* @returns Array of validation issues (empty if valid)
|
|
456
|
+
*/
|
|
457
|
+
export declare function validateFieldTypes(context: FieldTypeContext, constraints: FieldTypeConstraints): ValidationIssue[];
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Validates a complete FormSpec against constraints.
|
|
461
|
+
*
|
|
462
|
+
* @param formSpec - The FormSpec to validate
|
|
463
|
+
* @param options - Validation options including constraints
|
|
464
|
+
* @returns Validation result with all issues found
|
|
465
|
+
*/
|
|
466
|
+
export declare function validateFormSpec(formSpec: FormSpec<readonly FormElement[]>, options?: FormSpecValidationOptions): ValidationResult;
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Validates FormSpec elements against constraints.
|
|
470
|
+
*
|
|
471
|
+
* This is the main entry point for validating a form specification
|
|
472
|
+
* against a constraint configuration. It walks through all elements
|
|
473
|
+
* and checks each one against the configured constraints.
|
|
474
|
+
*
|
|
475
|
+
* @param elements - FormSpec elements to validate
|
|
476
|
+
* @param options - Validation options including constraints
|
|
477
|
+
* @returns Validation result with all issues found
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```ts
|
|
481
|
+
* import { formspec, field, group } from '@formspec/dsl';
|
|
482
|
+
* import { validateFormSpecElements, defineConstraints } from '@formspec/constraints';
|
|
483
|
+
*
|
|
484
|
+
* const form = formspec(
|
|
485
|
+
* group("Contact",
|
|
486
|
+
* field.text("name"),
|
|
487
|
+
* field.dynamicEnum("country", "countries"),
|
|
488
|
+
* ),
|
|
489
|
+
* );
|
|
490
|
+
*
|
|
491
|
+
* const result = validateFormSpecElements(form.elements, {
|
|
492
|
+
* constraints: {
|
|
493
|
+
* fieldTypes: { dynamicEnum: 'error' },
|
|
494
|
+
* layout: { group: 'error' },
|
|
495
|
+
* },
|
|
496
|
+
* });
|
|
497
|
+
*
|
|
498
|
+
* if (!result.valid) {
|
|
499
|
+
* console.error('Validation failed:', result.issues);
|
|
500
|
+
* }
|
|
501
|
+
* ```
|
|
502
|
+
*/
|
|
503
|
+
export declare function validateFormSpecElements(elements: readonly FormElement[], options?: FormSpecValidationOptions): ValidationResult;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Validates a layout element against constraints.
|
|
507
|
+
*
|
|
508
|
+
* @param context - Information about the layout element
|
|
509
|
+
* @param constraints - Layout constraints
|
|
510
|
+
* @returns Array of validation issues (empty if valid)
|
|
511
|
+
*/
|
|
512
|
+
export declare function validateLayout(context: LayoutContext, constraints: LayoutConstraints): ValidationIssue[];
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* A single validation issue found during constraint checking.
|
|
516
|
+
*/
|
|
517
|
+
export declare interface ValidationIssue {
|
|
518
|
+
/** Unique code identifying the issue type */
|
|
519
|
+
code: string;
|
|
520
|
+
/** Human-readable description of the issue */
|
|
521
|
+
message: string;
|
|
522
|
+
/** Severity level of this issue */
|
|
523
|
+
severity: "error" | "warning";
|
|
524
|
+
/** Which constraint category this issue belongs to */
|
|
525
|
+
category: "fieldTypes" | "layout" | "uiSchema" | "fieldOptions" | "controlOptions";
|
|
526
|
+
/** JSON pointer or field path to the issue location */
|
|
527
|
+
path?: string;
|
|
528
|
+
/** Name of the affected field (if applicable) */
|
|
529
|
+
fieldName?: string;
|
|
530
|
+
/** Type of the affected field (if applicable) */
|
|
531
|
+
fieldType?: string;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Result of validating a FormSpec or schema against constraints.
|
|
536
|
+
*/
|
|
537
|
+
export declare interface ValidationResult {
|
|
538
|
+
/** Whether validation passed (no errors, warnings OK) */
|
|
539
|
+
valid: boolean;
|
|
540
|
+
/** List of all issues found */
|
|
541
|
+
issues: ValidationIssue[];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export { }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConstraintConfig, FormSpecConfig, ResolvedConstraintConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default constraint configuration that allows all features.
|
|
4
|
+
* All constraints default to "off" (allowed).
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_CONSTRAINTS: ResolvedConstraintConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Default FormSpec configuration.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_CONFIG: FormSpecConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Merges user constraints with defaults, filling in any missing values.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeWithDefaults(config: ConstraintConfig | undefined): ResolvedConstraintConfig;
|
|
15
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE7F;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,wBAmDjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAE5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,wBAAwB,CAwC1B"}
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default constraint configuration that allows all features.
|
|
3
|
+
* All constraints default to "off" (allowed).
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_CONSTRAINTS = {
|
|
6
|
+
fieldTypes: {
|
|
7
|
+
text: "off",
|
|
8
|
+
number: "off",
|
|
9
|
+
boolean: "off",
|
|
10
|
+
staticEnum: "off",
|
|
11
|
+
dynamicEnum: "off",
|
|
12
|
+
dynamicSchema: "off",
|
|
13
|
+
array: "off",
|
|
14
|
+
object: "off",
|
|
15
|
+
},
|
|
16
|
+
layout: {
|
|
17
|
+
group: "off",
|
|
18
|
+
conditionals: "off",
|
|
19
|
+
maxNestingDepth: Infinity,
|
|
20
|
+
},
|
|
21
|
+
uiSchema: {
|
|
22
|
+
layouts: {
|
|
23
|
+
VerticalLayout: "off",
|
|
24
|
+
HorizontalLayout: "off",
|
|
25
|
+
Group: "off",
|
|
26
|
+
Categorization: "off",
|
|
27
|
+
Category: "off",
|
|
28
|
+
},
|
|
29
|
+
rules: {
|
|
30
|
+
enabled: "off",
|
|
31
|
+
effects: {
|
|
32
|
+
SHOW: "off",
|
|
33
|
+
HIDE: "off",
|
|
34
|
+
ENABLE: "off",
|
|
35
|
+
DISABLE: "off",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
fieldOptions: {
|
|
40
|
+
label: "off",
|
|
41
|
+
placeholder: "off",
|
|
42
|
+
required: "off",
|
|
43
|
+
minValue: "off",
|
|
44
|
+
maxValue: "off",
|
|
45
|
+
minItems: "off",
|
|
46
|
+
maxItems: "off",
|
|
47
|
+
},
|
|
48
|
+
controlOptions: {
|
|
49
|
+
format: "off",
|
|
50
|
+
readonly: "off",
|
|
51
|
+
multi: "off",
|
|
52
|
+
showUnfocusedDescription: "off",
|
|
53
|
+
hideRequiredAsterisk: "off",
|
|
54
|
+
custom: {},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Default FormSpec configuration.
|
|
59
|
+
*/
|
|
60
|
+
export const DEFAULT_CONFIG = {
|
|
61
|
+
constraints: DEFAULT_CONSTRAINTS,
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Merges user constraints with defaults, filling in any missing values.
|
|
65
|
+
*/
|
|
66
|
+
export function mergeWithDefaults(config) {
|
|
67
|
+
if (!config) {
|
|
68
|
+
return DEFAULT_CONSTRAINTS;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
fieldTypes: {
|
|
72
|
+
...DEFAULT_CONSTRAINTS.fieldTypes,
|
|
73
|
+
...config.fieldTypes,
|
|
74
|
+
},
|
|
75
|
+
layout: {
|
|
76
|
+
...DEFAULT_CONSTRAINTS.layout,
|
|
77
|
+
...config.layout,
|
|
78
|
+
},
|
|
79
|
+
uiSchema: {
|
|
80
|
+
layouts: {
|
|
81
|
+
...DEFAULT_CONSTRAINTS.uiSchema.layouts,
|
|
82
|
+
...config.uiSchema?.layouts,
|
|
83
|
+
},
|
|
84
|
+
rules: {
|
|
85
|
+
enabled: config.uiSchema?.rules?.enabled ?? DEFAULT_CONSTRAINTS.uiSchema.rules.enabled,
|
|
86
|
+
effects: {
|
|
87
|
+
...DEFAULT_CONSTRAINTS.uiSchema.rules.effects,
|
|
88
|
+
...config.uiSchema?.rules?.effects,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
fieldOptions: {
|
|
93
|
+
...DEFAULT_CONSTRAINTS.fieldOptions,
|
|
94
|
+
...config.fieldOptions,
|
|
95
|
+
},
|
|
96
|
+
controlOptions: {
|
|
97
|
+
...DEFAULT_CONSTRAINTS.controlOptions,
|
|
98
|
+
...config.controlOptions,
|
|
99
|
+
custom: {
|
|
100
|
+
...DEFAULT_CONSTRAINTS.controlOptions.custom,
|
|
101
|
+
...config.controlOptions?.custom,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA6B;IAC3D,UAAU,EAAE;QACV,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,KAAK;QACpB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;KACd;IACD,MAAM,EAAE;QACN,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,QAAQ;KAC1B;IACD,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,cAAc,EAAE,KAAK;YACrB,gBAAgB,EAAE,KAAK;YACvB,KAAK,EAAE,KAAK;YACZ,cAAc,EAAE,KAAK;YACrB,QAAQ,EAAE,KAAK;SAChB;QACD,KAAK,EAAE;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACP,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,KAAK;gBACX,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,KAAK;aACf;SACF;KACF;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,KAAK;KAChB;IACD,cAAc,EAAE;QACd,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,KAAK;QACZ,wBAAwB,EAAE,KAAK;QAC/B,oBAAoB,EAAE,KAAK;QAC3B,MAAM,EAAE,EAAE;KACX;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,WAAW,EAAE,mBAAmB;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoC;IAEpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,UAAU,EAAE;YACV,GAAG,mBAAmB,CAAC,UAAU;YACjC,GAAG,MAAM,CAAC,UAAU;SACrB;QACD,MAAM,EAAE;YACN,GAAG,mBAAmB,CAAC,MAAM;YAC7B,GAAG,MAAM,CAAC,MAAM;SACjB;QACD,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,GAAG,mBAAmB,CAAC,QAAQ,CAAC,OAAO;gBACvC,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO;aAC5B;YACD,KAAK,EAAE;gBACL,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,IAAI,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO;gBACtF,OAAO,EAAE;oBACP,GAAG,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO;oBAC7C,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO;iBACnC;aACF;SACF;QACD,YAAY,EAAE;YACZ,GAAG,mBAAmB,CAAC,YAAY;YACnC,GAAG,MAAM,CAAC,YAAY;SACvB;QACD,cAAc,EAAE;YACd,GAAG,mBAAmB,CAAC,cAAc;YACrC,GAAG,MAAM,CAAC,cAAc;YACxB,MAAM,EAAE;gBACN,GAAG,mBAAmB,CAAC,cAAc,CAAC,MAAM;gBAC5C,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM;aACjC;SACF;KACF,CAAC;AACJ,CAAC"}
|