@formspec/constraints 0.1.0-alpha.16 → 0.1.0-alpha.19
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 +29 -233
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,263 +1,59 @@
|
|
|
1
1
|
# @formspec/constraints
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Constraint configuration and validation for FormSpec DSL usage.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use this package when you want project-level rules such as:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- disallowing certain field types
|
|
8
|
+
- limiting layout nesting
|
|
9
|
+
- restricting selected field options
|
|
10
|
+
- validating `.formspec.yml`-driven capability policies
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
- **Compatibility**: Restrict to features your renderer supports
|
|
11
|
-
- **Simplicity**: Keep forms simple by disallowing complex nesting or conditionals
|
|
12
|
-
- **Linting**: Catch constraint violations at development time via ESLint
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
12
|
+
## Install
|
|
15
13
|
|
|
16
14
|
```bash
|
|
17
|
-
npm install @formspec/constraints
|
|
18
|
-
# or
|
|
19
15
|
pnpm add @formspec/constraints
|
|
20
16
|
```
|
|
21
17
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
Create a `.formspec.yml` file in your project root:
|
|
18
|
+
## `.formspec.yml`
|
|
25
19
|
|
|
26
20
|
```yaml
|
|
27
21
|
constraints:
|
|
28
22
|
fieldTypes:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
boolean: off # Allow boolean fields
|
|
32
|
-
staticEnum: off # Allow static enums
|
|
33
|
-
dynamicEnum: warn # Warn on dynamic enums
|
|
34
|
-
dynamicSchema: error # Disallow dynamic schemas
|
|
35
|
-
array: off # Allow arrays
|
|
36
|
-
object: off # Allow objects
|
|
23
|
+
dynamicEnum: warn
|
|
24
|
+
dynamicSchema: error
|
|
37
25
|
|
|
38
26
|
layout:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
maxNestingDepth: 3 # Max nesting depth (0 = flat only)
|
|
27
|
+
conditionals: off
|
|
28
|
+
maxNestingDepth: 2
|
|
42
29
|
|
|
43
30
|
fieldOptions:
|
|
44
|
-
label: off
|
|
45
31
|
placeholder: off
|
|
46
|
-
|
|
47
|
-
minValue: off
|
|
48
|
-
maxValue: off
|
|
49
|
-
minItems: off
|
|
50
|
-
maxItems: off
|
|
32
|
+
minItems: warn
|
|
51
33
|
```
|
|
52
34
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Each constraint can be set to:
|
|
56
|
-
|
|
57
|
-
| Severity | Behavior |
|
|
58
|
-
| --------- | ---------------------------- |
|
|
59
|
-
| `"off"` | Feature is allowed (default) |
|
|
60
|
-
| `"warn"` | Emit warning but allow |
|
|
61
|
-
| `"error"` | Disallow - fail validation |
|
|
62
|
-
|
|
63
|
-
## Constraint Categories
|
|
64
|
-
|
|
65
|
-
### Field Types (`fieldTypes`)
|
|
66
|
-
|
|
67
|
-
Control which DSL field builders are allowed:
|
|
35
|
+
## Programmatic Use
|
|
68
36
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
| `number` | `field.number()` |
|
|
73
|
-
| `boolean` | `field.boolean()` |
|
|
74
|
-
| `staticEnum` | `field.enum()` |
|
|
75
|
-
| `dynamicEnum` | `field.dynamicEnum()` |
|
|
76
|
-
| `dynamicSchema` | `field.dynamicSchema()` |
|
|
77
|
-
| `array` | `field.array()`, `field.arrayWithConfig()` |
|
|
78
|
-
| `object` | `field.object()`, `field.objectWithConfig()` |
|
|
37
|
+
```ts
|
|
38
|
+
import { loadConfig, mergeWithDefaults, validateFormSpecElements } from "@formspec/constraints";
|
|
39
|
+
import { field, formspec } from "@formspec/dsl";
|
|
79
40
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Control structure and nesting:
|
|
83
|
-
|
|
84
|
-
| Constraint | Description |
|
|
85
|
-
| ----------------- | --------------------------------------- |
|
|
86
|
-
| `group` | `group()` visual grouping |
|
|
87
|
-
| `conditionals` | `when()` conditional visibility |
|
|
88
|
-
| `maxNestingDepth` | Maximum depth for nested objects/arrays |
|
|
89
|
-
|
|
90
|
-
### Field Options (`fieldOptions`)
|
|
91
|
-
|
|
92
|
-
Control which field configuration options are allowed:
|
|
93
|
-
|
|
94
|
-
| Constraint | Description |
|
|
95
|
-
| ---------------------- | ------------------------- |
|
|
96
|
-
| `label` | Field label text |
|
|
97
|
-
| `placeholder` | Input placeholder |
|
|
98
|
-
| `required` | Required field validation |
|
|
99
|
-
| `minValue`, `maxValue` | Number field constraints |
|
|
100
|
-
| `minItems`, `maxItems` | Array length constraints |
|
|
101
|
-
|
|
102
|
-
### UI Schema (`uiSchema`)
|
|
103
|
-
|
|
104
|
-
Control JSON Forms-specific features:
|
|
105
|
-
|
|
106
|
-
```yaml
|
|
107
|
-
constraints:
|
|
108
|
-
uiSchema:
|
|
109
|
-
layouts:
|
|
110
|
-
VerticalLayout: off
|
|
111
|
-
HorizontalLayout: off
|
|
112
|
-
Group: off
|
|
113
|
-
Categorization: error # Disallow tabbed interfaces
|
|
114
|
-
Category: error
|
|
115
|
-
rules:
|
|
116
|
-
enabled: off
|
|
117
|
-
effects:
|
|
118
|
-
SHOW: off
|
|
119
|
-
HIDE: off
|
|
120
|
-
ENABLE: warn
|
|
121
|
-
DISABLE: warn
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Programmatic Usage
|
|
125
|
-
|
|
126
|
-
### Loading Configuration
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
import { loadConfig, mergeWithDefaults } from "@formspec/constraints";
|
|
130
|
-
|
|
131
|
-
// Load from .formspec.yml (searches up directory tree)
|
|
132
|
-
const config = await loadConfig();
|
|
133
|
-
|
|
134
|
-
// Or load from specific path
|
|
135
|
-
const config = await loadConfig("/path/to/.formspec.yml");
|
|
136
|
-
|
|
137
|
-
// Merge with defaults to get fully resolved config
|
|
41
|
+
const { config } = await loadConfig();
|
|
138
42
|
const resolved = mergeWithDefaults(config.constraints);
|
|
139
|
-
```
|
|
140
43
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
import { validateFormSpec } from "@formspec/constraints";
|
|
145
|
-
import { formspec, field, when, is } from "@formspec/dsl";
|
|
146
|
-
|
|
147
|
-
const form = formspec(
|
|
148
|
-
field.text("name"),
|
|
149
|
-
field.dynamicEnum("country", "fetch_countries"),
|
|
150
|
-
when(is("country", "US"), field.text("state"))
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const result = validateFormSpec(form, resolved);
|
|
154
|
-
|
|
155
|
-
if (!result.valid) {
|
|
156
|
-
for (const issue of result.issues) {
|
|
157
|
-
console.log(`${issue.severity}: ${issue.message}`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
44
|
+
const form = formspec(field.text("name"), field.dynamicEnum("country", "countries"));
|
|
45
|
+
const result = validateFormSpecElements(form.elements, { constraints: resolved });
|
|
160
46
|
```
|
|
161
47
|
|
|
162
|
-
|
|
48
|
+
## Main Exports
|
|
163
49
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
50
|
+
- `loadConfig`
|
|
51
|
+
- `loadConfigFromString`
|
|
52
|
+
- `defineConstraints`
|
|
53
|
+
- `mergeWithDefaults`
|
|
54
|
+
- `validateFormSpecElements`
|
|
55
|
+
- `validateFormSpec`
|
|
169
56
|
|
|
170
|
-
|
|
171
|
-
code: string; // e.g., "FIELD_TYPE_NOT_ALLOWED"
|
|
172
|
-
message: string; // Human-readable description
|
|
173
|
-
severity: "error" | "warning";
|
|
174
|
-
category: "fieldTypes" | "layout" | "uiSchema" | "fieldOptions" | "controlOptions";
|
|
175
|
-
path?: string; // JSON pointer to issue location
|
|
176
|
-
fieldName?: string; // Affected field name
|
|
177
|
-
fieldType?: string; // Affected field type
|
|
178
|
-
}
|
|
179
|
-
```
|
|
57
|
+
## License
|
|
180
58
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
Use `@formspec/eslint-plugin` to catch constraint violations at development time:
|
|
184
|
-
|
|
185
|
-
```javascript
|
|
186
|
-
// eslint.config.js
|
|
187
|
-
import formspec from "@formspec/eslint-plugin";
|
|
188
|
-
|
|
189
|
-
export default [
|
|
190
|
-
{
|
|
191
|
-
plugins: { formspec },
|
|
192
|
-
rules: {
|
|
193
|
-
// Enforce allowed field types from .formspec.yml
|
|
194
|
-
"formspec/constraints-allowed-field-types": "error",
|
|
195
|
-
// Enforce allowed layouts from .formspec.yml
|
|
196
|
-
"formspec/constraints-allowed-layouts": "error",
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
];
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The ESLint rules automatically load constraints from your `.formspec.yml` file.
|
|
203
|
-
|
|
204
|
-
## Example Configurations
|
|
205
|
-
|
|
206
|
-
### Simple Forms Only
|
|
207
|
-
|
|
208
|
-
Restrict to flat forms with basic field types:
|
|
209
|
-
|
|
210
|
-
```yaml
|
|
211
|
-
constraints:
|
|
212
|
-
fieldTypes:
|
|
213
|
-
array: error
|
|
214
|
-
object: error
|
|
215
|
-
dynamicEnum: error
|
|
216
|
-
dynamicSchema: error
|
|
217
|
-
layout:
|
|
218
|
-
conditionals: error
|
|
219
|
-
maxNestingDepth: 0
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### JSON Forms Compatible
|
|
223
|
-
|
|
224
|
-
Restrict to features supported by standard JSON Forms renderers:
|
|
225
|
-
|
|
226
|
-
```yaml
|
|
227
|
-
constraints:
|
|
228
|
-
fieldTypes:
|
|
229
|
-
dynamicSchema: error # Not supported by JSON Forms
|
|
230
|
-
uiSchema:
|
|
231
|
-
layouts:
|
|
232
|
-
Categorization: warn # May not be supported by all renderers
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Warn on Advanced Features
|
|
236
|
-
|
|
237
|
-
Allow all features but warn on complex ones:
|
|
238
|
-
|
|
239
|
-
```yaml
|
|
240
|
-
constraints:
|
|
241
|
-
fieldTypes:
|
|
242
|
-
dynamicEnum: warn
|
|
243
|
-
dynamicSchema: warn
|
|
244
|
-
array: warn
|
|
245
|
-
object: warn
|
|
246
|
-
layout:
|
|
247
|
-
conditionals: warn
|
|
248
|
-
maxNestingDepth: 2
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## JSON Schema
|
|
252
|
-
|
|
253
|
-
A JSON Schema for `.formspec.yml` is available for editor autocompletion:
|
|
254
|
-
|
|
255
|
-
```yaml
|
|
256
|
-
# .formspec.yml
|
|
257
|
-
# yaml-language-server: $schema=node_modules/@formspec/constraints/formspec.schema.json
|
|
258
|
-
|
|
259
|
-
constraints:
|
|
260
|
-
fieldTypes:
|
|
261
|
-
text: off
|
|
262
|
-
# ... autocomplete available
|
|
263
|
-
```
|
|
59
|
+
UNLICENSED
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formspec/constraints",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.19",
|
|
4
4
|
"description": "Constraint validation for FormSpec - restrict features based on target environment capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"yaml": "^2.7.0",
|
|
29
|
-
"@formspec/core": "0.1.0-alpha.
|
|
29
|
+
"@formspec/core": "0.1.0-alpha.19"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"tsd": "^0.31.0",
|
|
33
33
|
"vitest": "^3.0.0",
|
|
34
|
-
"@formspec/dsl": "0.1.0-alpha.
|
|
34
|
+
"@formspec/dsl": "0.1.0-alpha.19"
|
|
35
35
|
},
|
|
36
36
|
"tsd": {
|
|
37
37
|
"directory": "src/__tests__"
|