@formspec/constraints 0.1.0-alpha.21 → 0.1.0-alpha.26

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.
@@ -0,0 +1,925 @@
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
+ /**
39
+ * Union of all field types.
40
+ *
41
+ * @public
42
+ */
43
+ export declare type AnyField = TextField<string> | NumberField<string> | BooleanField<string> | StaticEnumField<string, readonly EnumOptionValue[]> | DynamicEnumField<string, string> | DynamicSchemaField<string> | ArrayField<string, readonly FormElement[]> | ObjectField<string, readonly FormElement[]>;
44
+
45
+ /**
46
+ * An array field containing repeating items.
47
+ *
48
+ * Use this for lists of values (e.g., multiple addresses, line items).
49
+ *
50
+ * @typeParam N - The field name (string literal type)
51
+ * @typeParam Items - The form elements that define each array item
52
+ *
53
+ * @public
54
+ */
55
+ export declare interface ArrayField<N extends string, Items extends readonly FormElement[]> {
56
+ /** Type discriminator for form elements */
57
+ readonly _type: "field";
58
+ /** Field type discriminator - identifies this as an array field */
59
+ readonly _field: "array";
60
+ /** Unique field identifier used as the schema key */
61
+ readonly name: N;
62
+ /** Form elements that define the schema for each array item */
63
+ readonly items: Items;
64
+ /** Display label for the field */
65
+ readonly label?: string;
66
+ /** Whether this field is required for form submission */
67
+ readonly required?: boolean;
68
+ /** Minimum number of items required */
69
+ readonly minItems?: number;
70
+ /** Maximum number of items allowed */
71
+ readonly maxItems?: number;
72
+ }
73
+
74
+ /**
75
+ * A boolean checkbox field.
76
+ *
77
+ * @typeParam N - The field name (string literal type)
78
+ *
79
+ * @public
80
+ */
81
+ export declare interface BooleanField<N extends string> {
82
+ /** Type discriminator for form elements */
83
+ readonly _type: "field";
84
+ /** Field type discriminator - identifies this as a boolean field */
85
+ readonly _field: "boolean";
86
+ /** Unique field identifier used as the schema key */
87
+ readonly name: N;
88
+ /** Display label for the field */
89
+ readonly label?: string;
90
+ /** Whether this field is required for form submission */
91
+ readonly required?: boolean;
92
+ }
93
+
94
+ /**
95
+ * A conditional wrapper that shows/hides elements based on another field's value.
96
+ *
97
+ * @typeParam FieldName - The field to check
98
+ * @typeParam Value - The value that triggers the condition
99
+ * @typeParam Elements - Tuple of contained form elements
100
+ *
101
+ * @public
102
+ */
103
+ export declare interface Conditional<FieldName extends string, Value, Elements extends readonly FormElement[]> {
104
+ /** Type discriminator - identifies this as a conditional element */
105
+ readonly _type: "conditional";
106
+ /** Name of the field whose value determines visibility */
107
+ readonly field: FieldName;
108
+ /** Value that triggers the condition (shows nested elements) */
109
+ readonly value: Value;
110
+ /** Form elements shown when condition is met */
111
+ readonly elements: Elements;
112
+ }
113
+
114
+ /**
115
+ * Complete constraint configuration for a FormSpec project.
116
+ *
117
+ * @public
118
+ */
119
+ export declare interface ConstraintConfig {
120
+ /** Field type constraints */
121
+ fieldTypes?: FieldTypeConstraints;
122
+ /** Layout and structure constraints */
123
+ layout?: LayoutConstraints;
124
+ /** UI Schema feature constraints */
125
+ uiSchema?: UISchemaConstraints;
126
+ /** Field configuration option constraints */
127
+ fieldOptions?: FieldOptionConstraints;
128
+ /** Control options constraints */
129
+ controlOptions?: ControlOptionConstraints;
130
+ }
131
+
132
+ /**
133
+ * Control options constraints - control which JSONForms Control.options are allowed.
134
+ * These are renderer-specific options that may not be universally supported.
135
+ *
136
+ * @public
137
+ */
138
+ export declare interface ControlOptionConstraints {
139
+ /** format - renderer format hint (e.g., "radio", "textarea") */
140
+ format?: Severity;
141
+ /** readonly - read-only mode */
142
+ readonly?: Severity;
143
+ /** multi - multi-select for enums */
144
+ multi?: Severity;
145
+ /** showUnfocusedDescription - show description when unfocused */
146
+ showUnfocusedDescription?: Severity;
147
+ /** hideRequiredAsterisk - hide required indicator */
148
+ hideRequiredAsterisk?: Severity;
149
+ /** Custom control options (extensible dictionary) */
150
+ custom?: Record<string, Severity>;
151
+ }
152
+
153
+ /**
154
+ * Default FormSpec configuration.
155
+ *
156
+ * @beta
157
+ */
158
+ export declare const DEFAULT_CONFIG: FormSpecConfig;
159
+
160
+ /**
161
+ * Default constraint configuration that allows all features.
162
+ * All constraints default to "off" (allowed).
163
+ *
164
+ * @beta
165
+ */
166
+ export declare const DEFAULT_CONSTRAINTS: ResolvedConstraintConfig;
167
+
168
+ /**
169
+ * Creates a constraint configuration directly from an object.
170
+ * Useful for programmatic configuration without YAML.
171
+ *
172
+ * @param config - Partial constraint configuration
173
+ * @returns Complete configuration with defaults applied
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * const config = defineConstraints({
178
+ * fieldTypes: {
179
+ * dynamicEnum: 'error',
180
+ * dynamicSchema: 'error',
181
+ * },
182
+ * layout: {
183
+ * group: 'error',
184
+ * },
185
+ * });
186
+ * ```
187
+ *
188
+ * @public
189
+ */
190
+ export declare function defineConstraints(config: ConstraintConfig): ResolvedConstraintConfig;
191
+
192
+ /**
193
+ * A field with dynamic enum options (fetched from a data source at runtime).
194
+ *
195
+ * @typeParam N - The field name (string literal type)
196
+ * @typeParam Source - The data source key (from DataSourceRegistry)
197
+ *
198
+ * @public
199
+ */
200
+ export declare interface DynamicEnumField<N extends string, Source extends string> {
201
+ /** Type discriminator for form elements */
202
+ readonly _type: "field";
203
+ /** Field type discriminator - identifies this as a dynamic enum field */
204
+ readonly _field: "dynamic_enum";
205
+ /** Unique field identifier used as the schema key */
206
+ readonly name: N;
207
+ /** Data source key for fetching options at runtime */
208
+ readonly source: Source;
209
+ /** Display label for the field */
210
+ readonly label?: string;
211
+ /** Whether this field is required for form submission */
212
+ readonly required?: boolean;
213
+ /** Field names whose values are needed to fetch options */
214
+ readonly params?: readonly string[];
215
+ }
216
+
217
+ /**
218
+ * A field that loads its schema dynamically (e.g., from an extension).
219
+ *
220
+ * @typeParam N - The field name (string literal type)
221
+ *
222
+ * @public
223
+ */
224
+ export declare interface DynamicSchemaField<N extends string> {
225
+ /** Type discriminator for form elements */
226
+ readonly _type: "field";
227
+ /** Field type discriminator - identifies this as a dynamic schema field */
228
+ readonly _field: "dynamic_schema";
229
+ /** Unique field identifier used as the schema key */
230
+ readonly name: N;
231
+ /** Identifier for the schema source */
232
+ readonly schemaSource: string;
233
+ /** Display label for the field */
234
+ readonly label?: string;
235
+ /** Whether this field is required for form submission */
236
+ readonly required?: boolean;
237
+ /** Field names whose values are needed to configure the schema */
238
+ readonly params?: readonly string[];
239
+ }
240
+
241
+ /**
242
+ * An enum option with a separate ID and display label.
243
+ *
244
+ * Use this when the stored value (id) should differ from the display text (label).
245
+ *
246
+ * @public
247
+ */
248
+ export declare interface EnumOption {
249
+ /** Stored enum value written into submitted data. */
250
+ readonly id: string;
251
+ /** Human-readable label shown to end users. */
252
+ readonly label: string;
253
+ }
254
+
255
+ /**
256
+ * Valid enum option types: either plain strings or objects with id/label.
257
+ *
258
+ * @public
259
+ */
260
+ export declare type EnumOptionValue = string | EnumOption;
261
+
262
+ /**
263
+ * Extracts which options are present on a field object.
264
+ * Works with FormSpec field types.
265
+ *
266
+ * @param field - A field object with potential options
267
+ * @returns Array of present option names
268
+ *
269
+ * @beta
270
+ */
271
+ export declare function extractFieldOptions(field: Record<string, unknown>): FieldOption[];
272
+
273
+ /**
274
+ * Known field options that can be validated.
275
+ *
276
+ * @beta
277
+ */
278
+ export declare type FieldOption = "label" | "placeholder" | "required" | "minValue" | "maxValue" | "minItems" | "maxItems";
279
+
280
+ /**
281
+ * Field configuration option constraints - control which field options are allowed.
282
+ *
283
+ * @public
284
+ */
285
+ export declare interface FieldOptionConstraints {
286
+ /** label - field label text */
287
+ label?: Severity;
288
+ /** placeholder - input placeholder text */
289
+ placeholder?: Severity;
290
+ /** required - whether field is required */
291
+ required?: Severity;
292
+ /** minValue - minimum value for numbers */
293
+ minValue?: Severity;
294
+ /** maxValue - maximum value for numbers */
295
+ maxValue?: Severity;
296
+ /** minItems - minimum array length */
297
+ minItems?: Severity;
298
+ /** maxItems - maximum array length */
299
+ maxItems?: Severity;
300
+ }
301
+
302
+ /**
303
+ * Context for field option validation.
304
+ *
305
+ * @beta
306
+ */
307
+ export declare interface FieldOptionsContext {
308
+ /** The field name */
309
+ fieldName: string;
310
+ /** Which options are present on this field */
311
+ presentOptions: FieldOption[];
312
+ /** Path to this field */
313
+ path?: string;
314
+ }
315
+
316
+ /**
317
+ * Field type constraints - control which field types are allowed.
318
+ * Fine-grained control over each DSL field builder.
319
+ *
320
+ * @public
321
+ */
322
+ export declare interface FieldTypeConstraints {
323
+ /** field.text() - basic text input */
324
+ text?: Severity;
325
+ /** field.number() - numeric input */
326
+ number?: Severity;
327
+ /** field.boolean() - checkbox/toggle */
328
+ boolean?: Severity;
329
+ /** field.enum() with literal options */
330
+ staticEnum?: Severity;
331
+ /** field.dynamicEnum() - runtime-fetched options */
332
+ dynamicEnum?: Severity;
333
+ /** field.dynamicSchema() - runtime-fetched schema */
334
+ dynamicSchema?: Severity;
335
+ /** field.array() / field.arrayWithConfig() */
336
+ array?: Severity;
337
+ /** field.object() / field.objectWithConfig() */
338
+ object?: Severity;
339
+ }
340
+
341
+ /**
342
+ * Context for field type validation.
343
+ *
344
+ * @beta
345
+ */
346
+ export declare interface FieldTypeContext {
347
+ /** The _field discriminator value (e.g., "text", "number", "enum") */
348
+ fieldType: string;
349
+ /** The field name */
350
+ fieldName: string;
351
+ /** Optional path for nested fields */
352
+ path?: string;
353
+ }
354
+
355
+ /**
356
+ * Union of all form element types (fields and structural elements).
357
+ *
358
+ * @public
359
+ */
360
+ export declare type FormElement = AnyField | Group<readonly FormElement[]> | Conditional<string, unknown, readonly FormElement[]>;
361
+
362
+ /**
363
+ * A complete form specification.
364
+ *
365
+ * @typeParam Elements - Tuple of top-level form elements
366
+ *
367
+ * @public
368
+ */
369
+ export declare interface FormSpec<Elements extends readonly FormElement[]> {
370
+ /** Top-level form elements */
371
+ readonly elements: Elements;
372
+ }
373
+
374
+ /**
375
+ * Top-level FormSpec configuration file structure.
376
+ * The .formspec.yml file uses this structure.
377
+ *
378
+ * @public
379
+ */
380
+ export declare interface FormSpecConfig {
381
+ /** Constraint configuration */
382
+ constraints?: ConstraintConfig;
383
+ }
384
+
385
+ /**
386
+ * Options for validating FormSpec elements.
387
+ *
388
+ * @public
389
+ */
390
+ export declare interface FormSpecValidationOptions {
391
+ /** Constraint configuration (will be merged with defaults) */
392
+ constraints?: ConstraintConfig;
393
+ }
394
+
395
+ /**
396
+ * Gets the severity level for a field option.
397
+ *
398
+ * @param option - The option to check
399
+ * @param constraints - Field option constraints
400
+ * @returns Severity level, or "off" if not constrained
401
+ *
402
+ * @beta
403
+ */
404
+ export declare function getFieldOptionSeverity(option: FieldOption, constraints: FieldOptionConstraints): Severity;
405
+
406
+ /**
407
+ * Gets the severity level for a field type.
408
+ *
409
+ * @param fieldType - The _field discriminator value
410
+ * @param constraints - Field type constraints
411
+ * @returns Severity level, or "off" if not constrained
412
+ *
413
+ * @beta
414
+ */
415
+ export declare function getFieldTypeSeverity(fieldType: string, constraints: FieldTypeConstraints): Severity;
416
+
417
+ /**
418
+ * A visual grouping of form elements.
419
+ *
420
+ * Groups provide visual organization and can be rendered as fieldsets or sections.
421
+ *
422
+ * @typeParam Elements - Tuple of contained form elements
423
+ *
424
+ * @public
425
+ */
426
+ export declare interface Group<Elements extends readonly FormElement[]> {
427
+ /** Type discriminator - identifies this as a group element */
428
+ readonly _type: "group";
429
+ /** Display label for the group */
430
+ readonly label: string;
431
+ /** Form elements contained within this group */
432
+ readonly elements: Elements;
433
+ }
434
+
435
+ /**
436
+ * Checks if a specific field option is allowed.
437
+ *
438
+ * @param option - The option to check
439
+ * @param constraints - Field option constraints
440
+ * @returns true if allowed, false if disallowed
441
+ *
442
+ * @beta
443
+ */
444
+ export declare function isFieldOptionAllowed(option: FieldOption, constraints: FieldOptionConstraints): boolean;
445
+
446
+ /**
447
+ * Checks if a field type is allowed by the constraints.
448
+ * Useful for quick checks without generating issues.
449
+ *
450
+ * @param fieldType - The _field discriminator value
451
+ * @param constraints - Field type constraints
452
+ * @returns true if allowed, false if disallowed
453
+ *
454
+ * @beta
455
+ */
456
+ export declare function isFieldTypeAllowed(fieldType: string, constraints: FieldTypeConstraints): boolean;
457
+
458
+ /**
459
+ * Checks if a layout type is allowed by the constraints.
460
+ *
461
+ * @param layoutType - The type of layout element
462
+ * @param constraints - Layout constraints
463
+ * @returns true if allowed, false if disallowed
464
+ *
465
+ * @beta
466
+ */
467
+ export declare function isLayoutTypeAllowed(layoutType: "group" | "conditional", constraints: LayoutConstraints): boolean;
468
+
469
+ /**
470
+ * Checks if a nesting depth is allowed.
471
+ *
472
+ * @param depth - Current nesting depth
473
+ * @param constraints - Layout constraints
474
+ * @returns true if allowed, false if exceeds limit
475
+ *
476
+ * @beta
477
+ */
478
+ export declare function isNestingDepthAllowed(depth: number, constraints: LayoutConstraints): boolean;
479
+
480
+ /**
481
+ * Layout and structure constraints - control grouping, conditionals, nesting.
482
+ *
483
+ * @public
484
+ */
485
+ export declare interface LayoutConstraints {
486
+ /** group() - visual grouping of fields */
487
+ group?: Severity;
488
+ /** when() - conditional field visibility */
489
+ conditionals?: Severity;
490
+ /** Maximum nesting depth for objects/arrays (0 = flat only) */
491
+ maxNestingDepth?: number;
492
+ }
493
+
494
+ /**
495
+ * Context for layout validation.
496
+ *
497
+ * @beta
498
+ */
499
+ export declare interface LayoutContext {
500
+ /** The type of layout element ("group" | "conditional") */
501
+ layoutType: "group" | "conditional";
502
+ /** Optional label for the element (for groups) */
503
+ label?: string;
504
+ /** Current nesting depth */
505
+ depth: number;
506
+ /** Path to this element */
507
+ path?: string;
508
+ }
509
+
510
+ /**
511
+ * JSONForms layout type constraints.
512
+ *
513
+ * @public
514
+ */
515
+ export declare interface LayoutTypeConstraints {
516
+ /** VerticalLayout - stack elements vertically */
517
+ VerticalLayout?: Severity;
518
+ /** HorizontalLayout - arrange elements horizontally */
519
+ HorizontalLayout?: Severity;
520
+ /** Group - visual grouping with label */
521
+ Group?: Severity;
522
+ /** Categorization - tabbed/wizard interface */
523
+ Categorization?: Severity;
524
+ /** Category - individual tab/step in Categorization */
525
+ Category?: Severity;
526
+ }
527
+
528
+ /**
529
+ * Loads FormSpec constraint configuration from a .formspec.yml file.
530
+ *
531
+ * @param options - Options for loading configuration
532
+ * @returns The loaded configuration with defaults applied
533
+ *
534
+ * @example
535
+ * ```ts
536
+ * // Load from current directory (searches for .formspec.yml)
537
+ * const result = await loadConfig();
538
+ *
539
+ * // Load from specific directory
540
+ * const result = await loadConfig({ cwd: '/path/to/project' });
541
+ *
542
+ * // Load from specific file
543
+ * const result = await loadConfig({ configPath: '/path/to/config.yml' });
544
+ * ```
545
+ *
546
+ * @public
547
+ */
548
+ export declare function loadConfig(options?: LoadConfigOptions): Promise<LoadConfigResult>;
549
+
550
+ /**
551
+ * Synchronously loads config from a pre-parsed YAML string.
552
+ * Useful for testing or when config is already available.
553
+ *
554
+ * @param yamlContent - The YAML content to parse
555
+ * @returns The parsed and merged configuration
556
+ *
557
+ * @public
558
+ */
559
+ export declare function loadConfigFromString(yamlContent: string): ResolvedConstraintConfig;
560
+
561
+ /**
562
+ * Options for loading configuration.
563
+ *
564
+ * @public
565
+ */
566
+ export declare interface LoadConfigOptions {
567
+ /**
568
+ * The directory to search for config files.
569
+ * Defaults to process.cwd().
570
+ */
571
+ cwd?: string;
572
+ /**
573
+ * Explicit path to a config file.
574
+ * If provided, skips searching for default config file names.
575
+ */
576
+ configPath?: string;
577
+ /**
578
+ * Whether to search parent directories for config files.
579
+ * Defaults to true.
580
+ */
581
+ searchParents?: boolean;
582
+ }
583
+
584
+ /**
585
+ * Result of loading configuration.
586
+ *
587
+ * @public
588
+ */
589
+ export declare interface LoadConfigResult {
590
+ /** The loaded and merged configuration */
591
+ config: ResolvedConstraintConfig;
592
+ /** The path to the config file that was loaded (if any) */
593
+ configPath: string | null;
594
+ /** Whether a config file was found */
595
+ found: boolean;
596
+ }
597
+
598
+ /**
599
+ * Merges user constraints with defaults, filling in any missing values.
600
+ *
601
+ * @beta
602
+ */
603
+ export declare function mergeWithDefaults(config: ConstraintConfig | undefined): ResolvedConstraintConfig;
604
+
605
+ /**
606
+ * A numeric input field.
607
+ *
608
+ * @typeParam N - The field name (string literal type)
609
+ *
610
+ * @public
611
+ */
612
+ export declare interface NumberField<N extends string> {
613
+ /** Type discriminator for form elements */
614
+ readonly _type: "field";
615
+ /** Field type discriminator - identifies this as a number field */
616
+ readonly _field: "number";
617
+ /** Unique field identifier used as the schema key */
618
+ readonly name: N;
619
+ /** Display label for the field */
620
+ readonly label?: string;
621
+ /** Minimum allowed value */
622
+ readonly min?: number;
623
+ /** Maximum allowed value */
624
+ readonly max?: number;
625
+ /** Whether this field is required for form submission */
626
+ readonly required?: boolean;
627
+ /** Value must be a multiple of this number (use 1 for integer semantics) */
628
+ readonly multipleOf?: number;
629
+ }
630
+
631
+ /**
632
+ * An object field containing nested properties.
633
+ *
634
+ * Use this for grouping related fields under a single key in the schema.
635
+ *
636
+ * @typeParam N - The field name (string literal type)
637
+ * @typeParam Properties - The form elements that define the object's properties
638
+ *
639
+ * @public
640
+ */
641
+ export declare interface ObjectField<N extends string, Properties extends readonly FormElement[]> {
642
+ /** Type discriminator for form elements */
643
+ readonly _type: "field";
644
+ /** Field type discriminator - identifies this as an object field */
645
+ readonly _field: "object";
646
+ /** Unique field identifier used as the schema key */
647
+ readonly name: N;
648
+ /** Form elements that define the properties of this object */
649
+ readonly properties: Properties;
650
+ /** Display label for the field */
651
+ readonly label?: string;
652
+ /** Whether this field is required for form submission */
653
+ readonly required?: boolean;
654
+ }
655
+
656
+ /**
657
+ * Fully resolved constraint configuration with all properties required.
658
+ * This is the type returned by mergeWithDefaults().
659
+ *
660
+ * @public
661
+ */
662
+ export declare interface ResolvedConstraintConfig {
663
+ /** Effective field-builder policy after defaults and overrides are merged. */
664
+ fieldTypes: Required<FieldTypeConstraints>;
665
+ /** Effective nesting and grouping policy after defaults are applied. */
666
+ layout: Required<LayoutConstraints>;
667
+ /** Effective UI-schema policy after defaults and overrides are merged. */
668
+ uiSchema: ResolvedUISchemaConstraints;
669
+ /** Effective policy for field-level builder options. */
670
+ fieldOptions: Required<FieldOptionConstraints>;
671
+ /** Effective policy for renderer-specific control options. */
672
+ controlOptions: Required<ControlOptionConstraints>;
673
+ }
674
+
675
+ /**
676
+ * Fully resolved rule constraints with all properties required.
677
+ *
678
+ * @public
679
+ */
680
+ export declare interface ResolvedRuleConstraints {
681
+ /** Effective severity controlling whether UI schema rules are allowed. */
682
+ enabled: Severity;
683
+ /** Effective severity for each supported JSON Forms rule effect. */
684
+ effects: Required<RuleEffectConstraints>;
685
+ }
686
+
687
+ /**
688
+ * Fully resolved UI schema constraints with all properties required.
689
+ *
690
+ * @public
691
+ */
692
+ export declare interface ResolvedUISchemaConstraints {
693
+ /** Effective severities for each supported JSON Forms layout type. */
694
+ layouts: Required<LayoutTypeConstraints>;
695
+ /** Effective rule policy after defaults have been applied. */
696
+ rules: ResolvedRuleConstraints;
697
+ }
698
+
699
+ /**
700
+ * JSONForms rule constraints.
701
+ *
702
+ * @public
703
+ */
704
+ export declare interface RuleConstraints {
705
+ /** Whether rules are enabled at all */
706
+ enabled?: Severity;
707
+ /** Fine-grained control over rule effects */
708
+ effects?: RuleEffectConstraints;
709
+ }
710
+
711
+ /**
712
+ * JSONForms rule effect constraints.
713
+ *
714
+ * @public
715
+ */
716
+ export declare interface RuleEffectConstraints {
717
+ /** SHOW - show element when condition is true */
718
+ SHOW?: Severity;
719
+ /** HIDE - hide element when condition is true */
720
+ HIDE?: Severity;
721
+ /** ENABLE - enable element when condition is true */
722
+ ENABLE?: Severity;
723
+ /** DISABLE - disable element when condition is true */
724
+ DISABLE?: Severity;
725
+ }
726
+
727
+ /**
728
+ * Severity level for constraint violations.
729
+ * - "error": Violation fails validation
730
+ * - "warn": Violation emits warning but passes
731
+ * - "off": Feature is allowed (no violation)
732
+ *
733
+ * @public
734
+ */
735
+ export declare type Severity = "error" | "warn" | "off";
736
+
737
+ /**
738
+ * A field with static enum options (known at compile time).
739
+ *
740
+ * Options can be plain strings or objects with `id` and `label` properties.
741
+ *
742
+ * @typeParam N - The field name (string literal type)
743
+ * @typeParam O - Tuple of option values (strings or EnumOption objects)
744
+ *
745
+ * @public
746
+ */
747
+ export declare interface StaticEnumField<N extends string, O extends readonly EnumOptionValue[]> {
748
+ /** Type discriminator for form elements */
749
+ readonly _type: "field";
750
+ /** Field type discriminator - identifies this as an enum field */
751
+ readonly _field: "enum";
752
+ /** Unique field identifier used as the schema key */
753
+ readonly name: N;
754
+ /** Array of allowed option values */
755
+ readonly options: O;
756
+ /** Display label for the field */
757
+ readonly label?: string;
758
+ /** Whether this field is required for form submission */
759
+ readonly required?: boolean;
760
+ }
761
+
762
+ /**
763
+ * Form element type definitions.
764
+ *
765
+ * These types define the structure of form specifications.
766
+ * The structure IS the definition - nesting implies layout and conditional logic.
767
+ */
768
+ /**
769
+ * A text input field.
770
+ *
771
+ * @typeParam N - The field name (string literal type)
772
+ *
773
+ * @public
774
+ */
775
+ export declare interface TextField<N extends string> {
776
+ /** Type discriminator for form elements */
777
+ readonly _type: "field";
778
+ /** Field type discriminator - identifies this as a text field */
779
+ readonly _field: "text";
780
+ /** Unique field identifier used as the schema key */
781
+ readonly name: N;
782
+ /** Display label for the field */
783
+ readonly label?: string;
784
+ /** Placeholder text shown when field is empty */
785
+ readonly placeholder?: string;
786
+ /** Whether this field is required for form submission */
787
+ readonly required?: boolean;
788
+ /** Minimum string length */
789
+ readonly minLength?: number;
790
+ /** Maximum string length */
791
+ readonly maxLength?: number;
792
+ /** Regular expression pattern the value must match */
793
+ readonly pattern?: string;
794
+ }
795
+
796
+ /**
797
+ * UI Schema feature constraints - control JSONForms-specific features.
798
+ *
799
+ * @public
800
+ */
801
+ export declare interface UISchemaConstraints {
802
+ /** Layout type constraints */
803
+ layouts?: LayoutTypeConstraints;
804
+ /** Rule (conditional) constraints */
805
+ rules?: RuleConstraints;
806
+ }
807
+
808
+ /**
809
+ * Validates field options against constraints.
810
+ *
811
+ * @param context - Information about the field and its options
812
+ * @param constraints - Field option constraints
813
+ * @returns Array of validation issues (empty if valid)
814
+ *
815
+ * @beta
816
+ */
817
+ export declare function validateFieldOptions(context: FieldOptionsContext, constraints: FieldOptionConstraints): ValidationIssue[];
818
+
819
+ /**
820
+ * Validates a field type against constraints.
821
+ *
822
+ * @param context - Information about the field being validated
823
+ * @param constraints - Field type constraints
824
+ * @returns Array of validation issues (empty if valid)
825
+ *
826
+ * @beta
827
+ */
828
+ export declare function validateFieldTypes(context: FieldTypeContext, constraints: FieldTypeConstraints): ValidationIssue[];
829
+
830
+ /**
831
+ * Validates a complete FormSpec against constraints.
832
+ *
833
+ * @param formSpec - The FormSpec to validate
834
+ * @param options - Validation options including constraints
835
+ * @returns Validation result with all issues found
836
+ *
837
+ * @public
838
+ */
839
+ export declare function validateFormSpec(formSpec: FormSpec<readonly FormElement[]>, options?: FormSpecValidationOptions): ValidationResult;
840
+
841
+ /**
842
+ * Validates FormSpec elements against constraints.
843
+ *
844
+ * This is the main entry point for validating a form specification
845
+ * against a constraint configuration. It walks through all elements
846
+ * and checks each one against the configured constraints.
847
+ *
848
+ * @param elements - FormSpec elements to validate
849
+ * @param options - Validation options including constraints
850
+ * @returns Validation result with all issues found
851
+ *
852
+ * @example
853
+ * ```ts
854
+ * import { formspec, field, group } from '@formspec/dsl';
855
+ * import { validateFormSpecElements, defineConstraints } from '@formspec/constraints';
856
+ *
857
+ * const form = formspec(
858
+ * group("Contact",
859
+ * field.text("name"),
860
+ * field.dynamicEnum("country", "countries"),
861
+ * ),
862
+ * );
863
+ *
864
+ * const result = validateFormSpecElements(form.elements, {
865
+ * constraints: {
866
+ * fieldTypes: { dynamicEnum: 'error' },
867
+ * layout: { group: 'error' },
868
+ * },
869
+ * });
870
+ *
871
+ * if (!result.valid) {
872
+ * console.error('Validation failed:', result.issues);
873
+ * }
874
+ * ```
875
+ *
876
+ * @public
877
+ */
878
+ export declare function validateFormSpecElements(elements: readonly FormElement[], options?: FormSpecValidationOptions): ValidationResult;
879
+
880
+ /**
881
+ * Validates a layout element against constraints.
882
+ *
883
+ * @param context - Information about the layout element
884
+ * @param constraints - Layout constraints
885
+ * @returns Array of validation issues (empty if valid)
886
+ *
887
+ * @beta
888
+ */
889
+ export declare function validateLayout(context: LayoutContext, constraints: LayoutConstraints): ValidationIssue[];
890
+
891
+ /**
892
+ * A single validation issue found during constraint checking.
893
+ *
894
+ * @public
895
+ */
896
+ export declare interface ValidationIssue {
897
+ /** Unique code identifying the issue type */
898
+ code: string;
899
+ /** Human-readable description of the issue */
900
+ message: string;
901
+ /** Severity level of this issue */
902
+ severity: "error" | "warning";
903
+ /** Which constraint category this issue belongs to */
904
+ category: "fieldTypes" | "layout" | "uiSchema" | "fieldOptions" | "controlOptions";
905
+ /** JSON pointer or field path to the issue location */
906
+ path?: string;
907
+ /** Name of the affected field (if applicable) */
908
+ fieldName?: string;
909
+ /** Type of the affected field (if applicable) */
910
+ fieldType?: string;
911
+ }
912
+
913
+ /**
914
+ * Result of validating a FormSpec or schema against constraints.
915
+ *
916
+ * @public
917
+ */
918
+ export declare interface ValidationResult {
919
+ /** Whether validation passed (no errors, warnings OK) */
920
+ valid: boolean;
921
+ /** List of all issues found */
922
+ issues: ValidationIssue[];
923
+ }
924
+
925
+ export { }