@formspec/eslint-plugin 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 +237 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/consistent-constraints.d.ts +22 -0
- package/dist/rules/consistent-constraints.d.ts.map +1 -0
- package/dist/rules/consistent-constraints.js +178 -0
- package/dist/rules/consistent-constraints.js.map +1 -0
- package/dist/rules/constraints/allowed-field-types.d.ts +16 -0
- package/dist/rules/constraints/allowed-field-types.d.ts.map +1 -0
- package/dist/rules/constraints/allowed-field-types.js +133 -0
- package/dist/rules/constraints/allowed-field-types.js.map +1 -0
- package/dist/rules/constraints/allowed-layouts.d.ts +17 -0
- package/dist/rules/constraints/allowed-layouts.d.ts.map +1 -0
- package/dist/rules/constraints/allowed-layouts.js +83 -0
- package/dist/rules/constraints/allowed-layouts.js.map +1 -0
- package/dist/rules/constraints/index.d.ts +9 -0
- package/dist/rules/constraints/index.d.ts.map +1 -0
- package/dist/rules/constraints/index.js +9 -0
- package/dist/rules/constraints/index.js.map +1 -0
- package/dist/rules/decorator-allowed-field-types.d.ts +17 -0
- package/dist/rules/decorator-allowed-field-types.d.ts.map +1 -0
- package/dist/rules/decorator-allowed-field-types.js +71 -0
- package/dist/rules/decorator-allowed-field-types.js.map +1 -0
- package/dist/rules/decorator-field-type-mismatch.d.ts +14 -0
- package/dist/rules/decorator-field-type-mismatch.d.ts.map +1 -0
- package/dist/rules/decorator-field-type-mismatch.js +116 -0
- package/dist/rules/decorator-field-type-mismatch.js.map +1 -0
- package/dist/rules/enum-options-match-type.d.ts +26 -0
- package/dist/rules/enum-options-match-type.d.ts.map +1 -0
- package/dist/rules/enum-options-match-type.js +115 -0
- package/dist/rules/enum-options-match-type.js.map +1 -0
- package/dist/rules/index.d.ts +13 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +13 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/no-conflicting-decorators.d.ts +15 -0
- package/dist/rules/no-conflicting-decorators.d.ts.map +1 -0
- package/dist/rules/no-conflicting-decorators.js +72 -0
- package/dist/rules/no-conflicting-decorators.js.map +1 -0
- package/dist/rules/no-duplicate-decorators.d.ts +19 -0
- package/dist/rules/no-duplicate-decorators.d.ts.map +1 -0
- package/dist/rules/no-duplicate-decorators.js +59 -0
- package/dist/rules/no-duplicate-decorators.js.map +1 -0
- package/dist/rules/prefer-custom-decorator.d.ts +22 -0
- package/dist/rules/prefer-custom-decorator.d.ts.map +1 -0
- package/dist/rules/prefer-custom-decorator.js +72 -0
- package/dist/rules/prefer-custom-decorator.js.map +1 -0
- package/dist/rules/showwhen-field-exists.d.ts +21 -0
- package/dist/rules/showwhen-field-exists.d.ts.map +1 -0
- package/dist/rules/showwhen-field-exists.js +68 -0
- package/dist/rules/showwhen-field-exists.js.map +1 -0
- package/dist/rules/showwhen-suggests-optional.d.ts +19 -0
- package/dist/rules/showwhen-suggests-optional.d.ts.map +1 -0
- package/dist/rules/showwhen-suggests-optional.js +53 -0
- package/dist/rules/showwhen-suggests-optional.js.map +1 -0
- package/dist/utils/decorator-utils.d.ts +105 -0
- package/dist/utils/decorator-utils.d.ts.map +1 -0
- package/dist/utils/decorator-utils.js +216 -0
- package/dist/utils/decorator-utils.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/jsdoc-utils.d.ts +31 -0
- package/dist/utils/jsdoc-utils.d.ts.map +1 -0
- package/dist/utils/jsdoc-utils.js +81 -0
- package/dist/utils/jsdoc-utils.js.map +1 -0
- package/dist/utils/type-utils.d.ts +82 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +216 -0
- package/dist/utils/type-utils.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# @your-org/eslint-plugin
|
|
2
|
+
|
|
3
|
+
ESLint rules for working with your schema/constraints.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
| Rule name | Description |
|
|
8
|
+
| ----------------------- | --------------------------------------------------------------- |
|
|
9
|
+
| `consistent-constraints` | Enforces consistent min/max and related constraints in schemas. |
|
|
10
|
+
|
|
11
|
+
## Rule details
|
|
12
|
+
|
|
13
|
+
### `consistent-constraints`
|
|
14
|
+
|
|
15
|
+
This rule validates that constraint-related properties (such as minimum and maximum
|
|
16
|
+
values, lengths, or ranges) are used consistently and do not contradict each other.
|
|
17
|
+
|
|
18
|
+
It is intended as a replacement for the now-removed `min-max-valid-range` rule and
|
|
19
|
+
should be enabled wherever constraint consistency needs to be enforced.
|
|
20
|
+
|
|
21
|
+
<!-- Add additional rules and documentation here as needed. -->
|
|
22
|
+
# @formspec/eslint-plugin
|
|
23
|
+
|
|
24
|
+
ESLint plugin for validating FormSpec decorator DSL usage in TypeScript projects. This plugin catches common mistakes by ensuring decorators match their field types and enforcing consistency rules.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install --save-dev @formspec/eslint-plugin
|
|
30
|
+
# or
|
|
31
|
+
pnpm add -D @formspec/eslint-plugin
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- ESLint v9+ (flat config)
|
|
37
|
+
- TypeScript v5+
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Recommended Configuration
|
|
42
|
+
|
|
43
|
+
Add the plugin to your `eslint.config.js`:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
import formspec from "@formspec/eslint-plugin";
|
|
47
|
+
|
|
48
|
+
export default [
|
|
49
|
+
// ... other configs
|
|
50
|
+
...formspec.configs.recommended,
|
|
51
|
+
];
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Manual Configuration
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import formspec from "@formspec/eslint-plugin";
|
|
58
|
+
|
|
59
|
+
export default [
|
|
60
|
+
{
|
|
61
|
+
plugins: {
|
|
62
|
+
"@formspec": formspec,
|
|
63
|
+
},
|
|
64
|
+
rules: {
|
|
65
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
66
|
+
"@formspec/enum-options-match-type": "error",
|
|
67
|
+
"@formspec/showwhen-field-exists": "error",
|
|
68
|
+
"@formspec/showwhen-suggests-optional": "warn",
|
|
69
|
+
"@formspec/min-max-valid-range": "error",
|
|
70
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
71
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Rules
|
|
78
|
+
|
|
79
|
+
| Rule | Description | Recommended | Strict |
|
|
80
|
+
| ----------------------------------------------------------------- | -------------------------------------------------------------- | ----------- | ------ |
|
|
81
|
+
| [`decorator-field-type-mismatch`](#decorator-field-type-mismatch) | Ensures decorators are applied to fields with compatible types | error | error |
|
|
82
|
+
| [`enum-options-match-type`](#enum-options-match-type) | Ensures @EnumOptions values match the field's union type | error | error |
|
|
83
|
+
| [`showwhen-field-exists`](#showwhen-field-exists) | Ensures @ShowWhen references a field that exists | error | error |
|
|
84
|
+
| [`showwhen-suggests-optional`](#showwhen-suggests-optional) | Suggests @ShowWhen fields should be optional | warn | error |
|
|
85
|
+
| [`min-max-valid-range`](#min-max-valid-range) | Ensures @Min/@Max have valid ranges | error | error |
|
|
86
|
+
| [`no-conflicting-decorators`](#no-conflicting-decorators) | Prevents decorators that imply conflicting types | error | error |
|
|
87
|
+
| [`no-duplicate-decorators`](#no-duplicate-decorators) | Prevents duplicate decorators on the same field | error | error |
|
|
88
|
+
|
|
89
|
+
### decorator-field-type-mismatch
|
|
90
|
+
|
|
91
|
+
Ensures FormSpec decorators are applied to fields with compatible types.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// Valid
|
|
95
|
+
@Min(0)
|
|
96
|
+
@Max(100)
|
|
97
|
+
age!: number;
|
|
98
|
+
|
|
99
|
+
@Placeholder("Enter name")
|
|
100
|
+
name!: string;
|
|
101
|
+
|
|
102
|
+
@MinItems(1)
|
|
103
|
+
@MaxItems(10)
|
|
104
|
+
items!: string[];
|
|
105
|
+
|
|
106
|
+
// Invalid - @Min requires number field
|
|
107
|
+
@Min(0)
|
|
108
|
+
name!: string; // Error: @Min can only be used on number fields
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### enum-options-match-type
|
|
112
|
+
|
|
113
|
+
Ensures @EnumOptions values match the field's TypeScript union type.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Valid - options match type
|
|
117
|
+
@EnumOptions(["draft", "published", "archived"])
|
|
118
|
+
status!: "draft" | "published" | "archived";
|
|
119
|
+
|
|
120
|
+
// Valid - object options with id property
|
|
121
|
+
@EnumOptions([{ id: "a", label: "Option A" }, { id: "b", label: "Option B" }])
|
|
122
|
+
type!: "a" | "b";
|
|
123
|
+
|
|
124
|
+
// Valid - string type accepts any options
|
|
125
|
+
@EnumOptions(["any", "options"])
|
|
126
|
+
value!: string;
|
|
127
|
+
|
|
128
|
+
// Invalid - missing option "archived"
|
|
129
|
+
@EnumOptions(["draft", "published"])
|
|
130
|
+
status!: "draft" | "published" | "archived"; // Error: missing "archived"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### showwhen-field-exists
|
|
134
|
+
|
|
135
|
+
Ensures @ShowWhen references a field that exists in the same class.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Valid
|
|
139
|
+
@EnumOptions(["a", "b"])
|
|
140
|
+
type!: "a" | "b";
|
|
141
|
+
|
|
142
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
143
|
+
conditionalField?: string;
|
|
144
|
+
|
|
145
|
+
// Invalid - "nonexistent" field doesn't exist
|
|
146
|
+
@ShowWhen({ _predicate: "equals", field: "nonexistent", value: "x" })
|
|
147
|
+
conditionalField?: string; // Error: field "nonexistent" does not exist
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### showwhen-suggests-optional
|
|
151
|
+
|
|
152
|
+
Suggests that fields with @ShowWhen should be marked as optional since they may not be present in the output.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Valid
|
|
156
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
157
|
+
conditionalField?: string; // Good - optional
|
|
158
|
+
|
|
159
|
+
// Warning
|
|
160
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
161
|
+
conditionalField!: string; // Warning: should be optional
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### min-max-valid-range
|
|
165
|
+
|
|
166
|
+
Ensures @Min value is less than or equal to @Max value.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// Valid
|
|
170
|
+
@Min(0)
|
|
171
|
+
@Max(100)
|
|
172
|
+
value!: number;
|
|
173
|
+
|
|
174
|
+
@Min(5)
|
|
175
|
+
@Max(5) // Equal is valid
|
|
176
|
+
exact!: number;
|
|
177
|
+
|
|
178
|
+
// Invalid
|
|
179
|
+
@Min(100)
|
|
180
|
+
@Max(50) // Error: @Min(100) > @Max(50)
|
|
181
|
+
invalid!: number;
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### no-conflicting-decorators
|
|
185
|
+
|
|
186
|
+
Prevents using decorators that imply conflicting field types.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Valid - both imply number
|
|
190
|
+
@Min(0)
|
|
191
|
+
@Max(100)
|
|
192
|
+
value!: number;
|
|
193
|
+
|
|
194
|
+
// Invalid - @Min implies number, @Placeholder implies string
|
|
195
|
+
@Min(0)
|
|
196
|
+
@Placeholder("Enter value") // Error: conflicting decorators
|
|
197
|
+
field!: string;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### no-duplicate-decorators
|
|
201
|
+
|
|
202
|
+
Prevents applying the same decorator multiple times to a field.
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Valid
|
|
206
|
+
@Label("Name")
|
|
207
|
+
@Placeholder("Enter name")
|
|
208
|
+
name!: string;
|
|
209
|
+
|
|
210
|
+
// Invalid
|
|
211
|
+
@Label("First")
|
|
212
|
+
@Label("Second") // Error: duplicate @Label
|
|
213
|
+
name!: string;
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Configurations
|
|
217
|
+
|
|
218
|
+
### Recommended
|
|
219
|
+
|
|
220
|
+
Sensible defaults for most projects:
|
|
221
|
+
|
|
222
|
+
- All type safety rules enabled as errors
|
|
223
|
+
- `showwhen-suggests-optional` as warning (not blocking)
|
|
224
|
+
|
|
225
|
+
### Strict
|
|
226
|
+
|
|
227
|
+
All rules enabled as errors for maximum type safety enforcement.
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
import formspec from "@formspec/eslint-plugin";
|
|
231
|
+
|
|
232
|
+
export default [...formspec.configs.strict];
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
UNLICENSED
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @formspec/eslint-plugin
|
|
3
|
+
*
|
|
4
|
+
* ESLint plugin for FormSpec type safety and constraint validation.
|
|
5
|
+
*
|
|
6
|
+
* Provides rules to:
|
|
7
|
+
* - Catch common mistakes when using FormSpec decorators
|
|
8
|
+
* - Validate Chain DSL usage against project constraints
|
|
9
|
+
* - Ensure forms comply with target environment capabilities
|
|
10
|
+
*/
|
|
11
|
+
import type { TSESLint } from "@typescript-eslint/utils";
|
|
12
|
+
import { decoratorFieldTypeMismatch } from "./rules/decorator-field-type-mismatch.js";
|
|
13
|
+
import { enumOptionsMatchType } from "./rules/enum-options-match-type.js";
|
|
14
|
+
import { showwhenFieldExists } from "./rules/showwhen-field-exists.js";
|
|
15
|
+
import { showwhenSuggestsOptional } from "./rules/showwhen-suggests-optional.js";
|
|
16
|
+
import { consistentConstraints } from "./rules/consistent-constraints.js";
|
|
17
|
+
import { noConflictingDecorators } from "./rules/no-conflicting-decorators.js";
|
|
18
|
+
import { noDuplicateDecorators } from "./rules/no-duplicate-decorators.js";
|
|
19
|
+
import { decoratorAllowedFieldTypes } from "./rules/decorator-allowed-field-types.js";
|
|
20
|
+
import { preferCustomDecorator } from "./rules/prefer-custom-decorator.js";
|
|
21
|
+
import { allowedFieldTypes, allowedLayouts } from "./rules/constraints/index.js";
|
|
22
|
+
/**
|
|
23
|
+
* The FormSpec ESLint plugin.
|
|
24
|
+
*/
|
|
25
|
+
declare const plugin: {
|
|
26
|
+
meta: {
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
rules: {
|
|
30
|
+
readonly "decorator-field-type-mismatch": TSESLint.RuleModule<"numericOnNonNumber" | "stringOnNonString", [], unknown, TSESLint.RuleListener> & {
|
|
31
|
+
name: string;
|
|
32
|
+
};
|
|
33
|
+
readonly "enum-options-match-type": TSESLint.RuleModule<"enumOptionsMismatch" | "enumOptionsMissing" | "enumOptionsExtra", [], unknown, TSESLint.RuleListener> & {
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
readonly "showwhen-field-exists": TSESLint.RuleModule<"fieldDoesNotExist", [], unknown, TSESLint.RuleListener> & {
|
|
37
|
+
name: string;
|
|
38
|
+
};
|
|
39
|
+
readonly "showwhen-suggests-optional": TSESLint.RuleModule<"shouldBeOptional", [], unknown, TSESLint.RuleListener> & {
|
|
40
|
+
name: string;
|
|
41
|
+
};
|
|
42
|
+
readonly "consistent-constraints": TSESLint.RuleModule<"minimumGreaterThanMaximum" | "exclusiveMinGreaterOrEqualMax" | "minLengthGreaterThanMaxLength" | "conflictingMinimumBounds" | "conflictingMaximumBounds" | "exclusiveMaxLessOrEqualMin" | "maximumLessOrEqualExclusiveMin" | "duplicateConstraintSource", [], unknown, TSESLint.RuleListener> & {
|
|
43
|
+
name: string;
|
|
44
|
+
};
|
|
45
|
+
readonly "no-conflicting-decorators": TSESLint.RuleModule<"conflictingDecorators", [], unknown, TSESLint.RuleListener> & {
|
|
46
|
+
name: string;
|
|
47
|
+
};
|
|
48
|
+
readonly "no-duplicate-decorators": TSESLint.RuleModule<"duplicateDecorator", [], unknown, TSESLint.RuleListener> & {
|
|
49
|
+
name: string;
|
|
50
|
+
};
|
|
51
|
+
readonly "decorator-allowed-field-types": TSESLint.RuleModule<"disallowedFieldType", [import("./rules/decorator-allowed-field-types.js").DecoratorAllowedFieldTypesOptions], unknown, TSESLint.RuleListener> & {
|
|
52
|
+
name: string;
|
|
53
|
+
};
|
|
54
|
+
readonly "prefer-custom-decorator": TSESLint.RuleModule<"preferCustomDecorator", [import("./rules/prefer-custom-decorator.js").PreferCustomDecoratorOptions], unknown, TSESLint.RuleListener> & {
|
|
55
|
+
name: string;
|
|
56
|
+
};
|
|
57
|
+
readonly "constraints-allowed-field-types": TSESLint.RuleModule<"disallowedFieldType", import("./rules/constraints/allowed-field-types.js").Options, unknown, TSESLint.RuleListener> & {
|
|
58
|
+
name: string;
|
|
59
|
+
};
|
|
60
|
+
readonly "constraints-allowed-layouts": TSESLint.RuleModule<"disallowedGroup" | "disallowedConditional", import("./rules/constraints/allowed-layouts.js").Options, unknown, TSESLint.RuleListener> & {
|
|
61
|
+
name: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
configs: {
|
|
65
|
+
recommended: TSESLint.FlatConfig.ConfigArray;
|
|
66
|
+
strict: TSESLint.FlatConfig.ConfigArray;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export default plugin;
|
|
70
|
+
export { decoratorFieldTypeMismatch, enumOptionsMatchType, showwhenFieldExists, showwhenSuggestsOptional, consistentConstraints, noConflictingDecorators, noDuplicateDecorators, decoratorAllowedFieldTypes, preferCustomDecorator, allowedFieldTypes, allowedLayouts, };
|
|
71
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAG3E,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAoFjF;;GAEG;AACH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOX,CAAC;AAEF,eAAe,MAAM,CAAC;AAGtB,OAAO,EAEL,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EAErB,iBAAiB,EACjB,cAAc,GACf,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @formspec/eslint-plugin
|
|
3
|
+
*
|
|
4
|
+
* ESLint plugin for FormSpec type safety and constraint validation.
|
|
5
|
+
*
|
|
6
|
+
* Provides rules to:
|
|
7
|
+
* - Catch common mistakes when using FormSpec decorators
|
|
8
|
+
* - Validate Chain DSL usage against project constraints
|
|
9
|
+
* - Ensure forms comply with target environment capabilities
|
|
10
|
+
*/
|
|
11
|
+
import { decoratorFieldTypeMismatch } from "./rules/decorator-field-type-mismatch.js";
|
|
12
|
+
import { enumOptionsMatchType } from "./rules/enum-options-match-type.js";
|
|
13
|
+
import { showwhenFieldExists } from "./rules/showwhen-field-exists.js";
|
|
14
|
+
import { showwhenSuggestsOptional } from "./rules/showwhen-suggests-optional.js";
|
|
15
|
+
import { consistentConstraints } from "./rules/consistent-constraints.js";
|
|
16
|
+
import { noConflictingDecorators } from "./rules/no-conflicting-decorators.js";
|
|
17
|
+
import { noDuplicateDecorators } from "./rules/no-duplicate-decorators.js";
|
|
18
|
+
import { decoratorAllowedFieldTypes } from "./rules/decorator-allowed-field-types.js";
|
|
19
|
+
import { preferCustomDecorator } from "./rules/prefer-custom-decorator.js";
|
|
20
|
+
// Constraint rules for Chain DSL
|
|
21
|
+
import { allowedFieldTypes, allowedLayouts } from "./rules/constraints/index.js";
|
|
22
|
+
/**
|
|
23
|
+
* All rules provided by this plugin.
|
|
24
|
+
*/
|
|
25
|
+
const rules = {
|
|
26
|
+
// Decorator DSL rules
|
|
27
|
+
"decorator-field-type-mismatch": decoratorFieldTypeMismatch,
|
|
28
|
+
"enum-options-match-type": enumOptionsMatchType,
|
|
29
|
+
"showwhen-field-exists": showwhenFieldExists,
|
|
30
|
+
"showwhen-suggests-optional": showwhenSuggestsOptional,
|
|
31
|
+
"consistent-constraints": consistentConstraints,
|
|
32
|
+
"no-conflicting-decorators": noConflictingDecorators,
|
|
33
|
+
"no-duplicate-decorators": noDuplicateDecorators,
|
|
34
|
+
"decorator-allowed-field-types": decoratorAllowedFieldTypes,
|
|
35
|
+
"prefer-custom-decorator": preferCustomDecorator,
|
|
36
|
+
// Constraint rules for Chain DSL
|
|
37
|
+
"constraints-allowed-field-types": allowedFieldTypes,
|
|
38
|
+
"constraints-allowed-layouts": allowedLayouts,
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Plugin metadata.
|
|
42
|
+
*/
|
|
43
|
+
const meta = {
|
|
44
|
+
name: "@formspec/eslint-plugin",
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Recommended configuration for FormSpec projects.
|
|
48
|
+
*
|
|
49
|
+
* Usage:
|
|
50
|
+
* ```javascript
|
|
51
|
+
* import formspec from "@formspec/eslint-plugin";
|
|
52
|
+
*
|
|
53
|
+
* export default [
|
|
54
|
+
* ...formspec.configs.recommended,
|
|
55
|
+
* ];
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
const recommendedConfig = [
|
|
59
|
+
{
|
|
60
|
+
plugins: {
|
|
61
|
+
"@formspec": {
|
|
62
|
+
meta,
|
|
63
|
+
rules,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
rules: {
|
|
67
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
68
|
+
"@formspec/enum-options-match-type": "error",
|
|
69
|
+
"@formspec/showwhen-field-exists": "error",
|
|
70
|
+
"@formspec/showwhen-suggests-optional": "warn",
|
|
71
|
+
"@formspec/consistent-constraints": "error",
|
|
72
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
73
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Strict configuration - all rules as errors.
|
|
79
|
+
*/
|
|
80
|
+
const strictConfig = [
|
|
81
|
+
{
|
|
82
|
+
plugins: {
|
|
83
|
+
"@formspec": {
|
|
84
|
+
meta,
|
|
85
|
+
rules,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
rules: {
|
|
89
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
90
|
+
"@formspec/enum-options-match-type": "error",
|
|
91
|
+
"@formspec/showwhen-field-exists": "error",
|
|
92
|
+
"@formspec/showwhen-suggests-optional": "error",
|
|
93
|
+
"@formspec/consistent-constraints": "error",
|
|
94
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
95
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
/**
|
|
100
|
+
* The FormSpec ESLint plugin.
|
|
101
|
+
*/
|
|
102
|
+
const plugin = {
|
|
103
|
+
meta,
|
|
104
|
+
rules,
|
|
105
|
+
configs: {
|
|
106
|
+
recommended: recommendedConfig,
|
|
107
|
+
strict: strictConfig,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
export default plugin;
|
|
111
|
+
// Named exports for individual rules
|
|
112
|
+
export {
|
|
113
|
+
// Decorator DSL rules
|
|
114
|
+
decoratorFieldTypeMismatch, enumOptionsMatchType, showwhenFieldExists, showwhenSuggestsOptional, consistentConstraints, noConflictingDecorators, noDuplicateDecorators, decoratorAllowedFieldTypes, preferCustomDecorator,
|
|
115
|
+
// Constraint rules for Chain DSL
|
|
116
|
+
allowedFieldTypes, allowedLayouts, };
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E,iCAAiC;AACjC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEjF;;GAEG;AACH,MAAM,KAAK,GAAG;IACZ,sBAAsB;IACtB,+BAA+B,EAAE,0BAA0B;IAC3D,yBAAyB,EAAE,oBAAoB;IAC/C,uBAAuB,EAAE,mBAAmB;IAC5C,4BAA4B,EAAE,wBAAwB;IACtD,wBAAwB,EAAE,qBAAqB;IAC/C,2BAA2B,EAAE,uBAAuB;IACpD,yBAAyB,EAAE,qBAAqB;IAChD,+BAA+B,EAAE,0BAA0B;IAC3D,yBAAyB,EAAE,qBAAqB;IAEhD,iCAAiC;IACjC,iCAAiC,EAAE,iBAAiB;IACpD,6BAA6B,EAAE,cAAc;CACrC,CAAC;AAEX;;GAEG;AACH,MAAM,IAAI,GAAG;IACX,IAAI,EAAE,yBAAyB;CAChC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,iBAAiB,GAAoC;IACzD;QACE,OAAO,EAAE;YACP,WAAW,EAAE;gBACX,IAAI;gBACJ,KAAK;aACN;SACF;QACD,KAAK,EAAE;YACL,yCAAyC,EAAE,OAAO;YAClD,mCAAmC,EAAE,OAAO;YAC5C,iCAAiC,EAAE,OAAO;YAC1C,sCAAsC,EAAE,MAAM;YAC9C,kCAAkC,EAAE,OAAO;YAC3C,qCAAqC,EAAE,OAAO;YAC9C,mCAAmC,EAAE,OAAO;SAC7C;KACF;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,YAAY,GAAoC;IACpD;QACE,OAAO,EAAE;YACP,WAAW,EAAE;gBACX,IAAI;gBACJ,KAAK;aACN;SACF;QACD,KAAK,EAAE;YACL,yCAAyC,EAAE,OAAO;YAClD,mCAAmC,EAAE,OAAO;YAC5C,iCAAiC,EAAE,OAAO;YAC1C,sCAAsC,EAAE,OAAO;YAC/C,kCAAkC,EAAE,OAAO;YAC3C,qCAAqC,EAAE,OAAO;YAC9C,mCAAmC,EAAE,OAAO;SAC7C;KACF;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,GAAG;IACb,IAAI;IACJ,KAAK;IACL,OAAO,EAAE;QACP,WAAW,EAAE,iBAAiB;QAC9B,MAAM,EAAE,YAAY;KACrB;CACF,CAAC;AAEF,eAAe,MAAM,CAAC;AAEtB,qCAAqC;AACrC,OAAO;AACL,sBAAsB;AACtB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB;AACrB,iCAAiC;AACjC,iBAAiB,EACjB,cAAc,GACf,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: consistent-constraints
|
|
3
|
+
*
|
|
4
|
+
* Ensures constraint decorator pairs have valid ranges and don't conflict:
|
|
5
|
+
* - @Minimum must be <= @Maximum
|
|
6
|
+
* - @ExclusiveMinimum must be < @ExclusiveMaximum
|
|
7
|
+
* - @MinLength must be <= @MaxLength
|
|
8
|
+
* - @Minimum and @ExclusiveMinimum must not both be present
|
|
9
|
+
* - @Maximum and @ExclusiveMaximum must not both be present
|
|
10
|
+
* - @Maximum(n) where n < @Minimum(m) is invalid
|
|
11
|
+
* - @ExclusiveMaximum(n) where n <= @Minimum(m) is invalid
|
|
12
|
+
*
|
|
13
|
+
* Constraints may come from decorators or JSDoc tags. If both a decorator
|
|
14
|
+
* and a JSDoc tag specify the same constraint, that is a lint error.
|
|
15
|
+
*/
|
|
16
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
17
|
+
type MessageIds = "minimumGreaterThanMaximum" | "exclusiveMinGreaterOrEqualMax" | "minLengthGreaterThanMaxLength" | "conflictingMinimumBounds" | "conflictingMaximumBounds" | "exclusiveMaxLessOrEqualMin" | "maximumLessOrEqualExclusiveMin" | "duplicateConstraintSource";
|
|
18
|
+
export declare const consistentConstraints: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=consistent-constraints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-constraints.d.ts","sourceRoot":"","sources":["../../src/rules/consistent-constraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAQvD,KAAK,UAAU,GACX,2BAA2B,GAC3B,+BAA+B,GAC/B,+BAA+B,GAC/B,0BAA0B,GAC1B,0BAA0B,GAC1B,4BAA4B,GAC5B,gCAAgC,GAChC,2BAA2B,CAAC;AAYhC,eAAO,MAAM,qBAAqB;;CAyLhC,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: consistent-constraints
|
|
3
|
+
*
|
|
4
|
+
* Ensures constraint decorator pairs have valid ranges and don't conflict:
|
|
5
|
+
* - @Minimum must be <= @Maximum
|
|
6
|
+
* - @ExclusiveMinimum must be < @ExclusiveMaximum
|
|
7
|
+
* - @MinLength must be <= @MaxLength
|
|
8
|
+
* - @Minimum and @ExclusiveMinimum must not both be present
|
|
9
|
+
* - @Maximum and @ExclusiveMaximum must not both be present
|
|
10
|
+
* - @Maximum(n) where n < @Minimum(m) is invalid
|
|
11
|
+
* - @ExclusiveMaximum(n) where n <= @Minimum(m) is invalid
|
|
12
|
+
*
|
|
13
|
+
* Constraints may come from decorators or JSDoc tags. If both a decorator
|
|
14
|
+
* and a JSDoc tag specify the same constraint, that is a lint error.
|
|
15
|
+
*/
|
|
16
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
17
|
+
import { findDecorator, getDecoratorLiteralArg } from "../utils/decorator-utils.js";
|
|
18
|
+
import { getJSDocConstraints, findJSDocConstraint } from "../utils/jsdoc-utils.js";
|
|
19
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://formspec.dev/eslint-plugin/rules/${name}`);
|
|
20
|
+
export const consistentConstraints = createRule({
|
|
21
|
+
name: "consistent-constraints",
|
|
22
|
+
meta: {
|
|
23
|
+
type: "problem",
|
|
24
|
+
docs: {
|
|
25
|
+
description: "Ensures constraint decorator pairs have valid ranges and don't conflict",
|
|
26
|
+
},
|
|
27
|
+
messages: {
|
|
28
|
+
minimumGreaterThanMaximum: "@Minimum({{min}}) is greater than @Maximum({{max}}). Minimum must be less than or equal to Maximum.",
|
|
29
|
+
exclusiveMinGreaterOrEqualMax: "@ExclusiveMinimum({{min}}) must be less than @ExclusiveMaximum({{max}}).",
|
|
30
|
+
minLengthGreaterThanMaxLength: "@MinLength({{min}}) is greater than @MaxLength({{max}}). MinLength must be less than or equal to MaxLength.",
|
|
31
|
+
conflictingMinimumBounds: "Field has both @Minimum and @ExclusiveMinimum. Use only one lower bound constraint.",
|
|
32
|
+
conflictingMaximumBounds: "Field has both @Maximum and @ExclusiveMaximum. Use only one upper bound constraint.",
|
|
33
|
+
exclusiveMaxLessOrEqualMin: "@ExclusiveMaximum({{max}}) must be greater than @Minimum({{min}}).",
|
|
34
|
+
maximumLessOrEqualExclusiveMin: "@Maximum({{max}}) must be greater than @ExclusiveMinimum({{min}}).",
|
|
35
|
+
duplicateConstraintSource: "Constraint '{{name}}' is specified via both a decorator and a TSDoc tag. Use one or the other.",
|
|
36
|
+
},
|
|
37
|
+
schema: [],
|
|
38
|
+
},
|
|
39
|
+
defaultOptions: [],
|
|
40
|
+
create(context) {
|
|
41
|
+
const sourceCode = context.sourceCode;
|
|
42
|
+
return {
|
|
43
|
+
PropertyDefinition(node) {
|
|
44
|
+
const jsdocConstraints = getJSDocConstraints(node, sourceCode);
|
|
45
|
+
// Track which constraints have already been reported as duplicates
|
|
46
|
+
const reportedDuplicates = new Set();
|
|
47
|
+
/**
|
|
48
|
+
* Gets a numeric constraint value from either a decorator or a JSDoc tag.
|
|
49
|
+
* Reports a conflict if both sources provide the same constraint.
|
|
50
|
+
* Returns null if the constraint is absent, ambiguous, or non-numeric.
|
|
51
|
+
*/
|
|
52
|
+
function getConstraintValue(name) {
|
|
53
|
+
const dec = findDecorator(node, name);
|
|
54
|
+
const jsdoc = findJSDocConstraint(jsdocConstraints, name);
|
|
55
|
+
// Conflict: same constraint from both sources
|
|
56
|
+
if (dec && jsdoc) {
|
|
57
|
+
reportedDuplicates.add(name);
|
|
58
|
+
context.report({
|
|
59
|
+
node: dec.node,
|
|
60
|
+
messageId: "duplicateConstraintSource",
|
|
61
|
+
data: { name },
|
|
62
|
+
});
|
|
63
|
+
return null; // Don't validate range when ambiguous
|
|
64
|
+
}
|
|
65
|
+
if (dec) {
|
|
66
|
+
const val = getDecoratorLiteralArg(dec);
|
|
67
|
+
return typeof val === "number" ? { value: val, loc: dec.node.loc } : null;
|
|
68
|
+
}
|
|
69
|
+
if (jsdoc && typeof jsdoc.value === "number") {
|
|
70
|
+
return { value: jsdoc.value, loc: jsdoc.comment.loc };
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Checks whether a constraint is present from either source.
|
|
76
|
+
* Only reports duplicate source if not already reported by getConstraintValue.
|
|
77
|
+
*/
|
|
78
|
+
function hasConstraint(name) {
|
|
79
|
+
const dec = findDecorator(node, name);
|
|
80
|
+
const jsdoc = findJSDocConstraint(jsdocConstraints, name);
|
|
81
|
+
if (dec && jsdoc && !reportedDuplicates.has(name)) {
|
|
82
|
+
reportedDuplicates.add(name);
|
|
83
|
+
context.report({
|
|
84
|
+
node: dec.node,
|
|
85
|
+
messageId: "duplicateConstraintSource",
|
|
86
|
+
data: { name },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (dec)
|
|
90
|
+
return { present: true, loc: dec.node.loc };
|
|
91
|
+
if (jsdoc)
|
|
92
|
+
return { present: true, loc: jsdoc.comment.loc };
|
|
93
|
+
return { present: false, loc: null };
|
|
94
|
+
}
|
|
95
|
+
// Check @Minimum/@Maximum range
|
|
96
|
+
const minimum = getConstraintValue("Minimum");
|
|
97
|
+
const maximum = getConstraintValue("Maximum");
|
|
98
|
+
if (minimum && maximum && minimum.value > maximum.value) {
|
|
99
|
+
context.report({
|
|
100
|
+
loc: minimum.loc,
|
|
101
|
+
messageId: "minimumGreaterThanMaximum",
|
|
102
|
+
data: {
|
|
103
|
+
min: String(minimum.value),
|
|
104
|
+
max: String(maximum.value),
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Check @ExclusiveMinimum/@ExclusiveMaximum range
|
|
109
|
+
const exclusiveMin = getConstraintValue("ExclusiveMinimum");
|
|
110
|
+
const exclusiveMax = getConstraintValue("ExclusiveMaximum");
|
|
111
|
+
if (exclusiveMin && exclusiveMax && exclusiveMin.value >= exclusiveMax.value) {
|
|
112
|
+
context.report({
|
|
113
|
+
loc: exclusiveMin.loc,
|
|
114
|
+
messageId: "exclusiveMinGreaterOrEqualMax",
|
|
115
|
+
data: {
|
|
116
|
+
min: String(exclusiveMin.value),
|
|
117
|
+
max: String(exclusiveMax.value),
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Check @MinLength/@MaxLength range
|
|
122
|
+
const minLength = getConstraintValue("MinLength");
|
|
123
|
+
const maxLength = getConstraintValue("MaxLength");
|
|
124
|
+
if (minLength && maxLength && minLength.value > maxLength.value) {
|
|
125
|
+
context.report({
|
|
126
|
+
loc: minLength.loc,
|
|
127
|
+
messageId: "minLengthGreaterThanMaxLength",
|
|
128
|
+
data: {
|
|
129
|
+
min: String(minLength.value),
|
|
130
|
+
max: String(maxLength.value),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// Check conflicting bound types: @Minimum + @ExclusiveMinimum
|
|
135
|
+
const hasMinimum = hasConstraint("Minimum");
|
|
136
|
+
const hasExclusiveMinimum = hasConstraint("ExclusiveMinimum");
|
|
137
|
+
if (hasMinimum.present && hasExclusiveMinimum.present) {
|
|
138
|
+
context.report({
|
|
139
|
+
loc: hasExclusiveMinimum.loc ?? node.loc,
|
|
140
|
+
messageId: "conflictingMinimumBounds",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Check conflicting bound types: @Maximum + @ExclusiveMaximum
|
|
144
|
+
const hasMaximum = hasConstraint("Maximum");
|
|
145
|
+
const hasExclusiveMaximum = hasConstraint("ExclusiveMaximum");
|
|
146
|
+
if (hasMaximum.present && hasExclusiveMaximum.present) {
|
|
147
|
+
context.report({
|
|
148
|
+
loc: hasExclusiveMaximum.loc ?? node.loc,
|
|
149
|
+
messageId: "conflictingMaximumBounds",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// Check @ExclusiveMinimum(m) + @Maximum(n) where n <= m
|
|
153
|
+
if (exclusiveMin && maximum && maximum.value <= exclusiveMin.value) {
|
|
154
|
+
context.report({
|
|
155
|
+
loc: maximum.loc,
|
|
156
|
+
messageId: "maximumLessOrEqualExclusiveMin",
|
|
157
|
+
data: {
|
|
158
|
+
min: String(exclusiveMin.value),
|
|
159
|
+
max: String(maximum.value),
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// Check @ExclusiveMaximum(n) where n <= @Minimum(m)
|
|
164
|
+
if (minimum && exclusiveMax && exclusiveMax.value <= minimum.value) {
|
|
165
|
+
context.report({
|
|
166
|
+
loc: exclusiveMax.loc,
|
|
167
|
+
messageId: "exclusiveMaxLessOrEqualMin",
|
|
168
|
+
data: {
|
|
169
|
+
min: String(minimum.value),
|
|
170
|
+
max: String(exclusiveMax.value),
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=consistent-constraints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-constraints.js","sourceRoot":"","sources":["../../src/rules/consistent-constraints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: constraints/allowed-field-types
|
|
3
|
+
*
|
|
4
|
+
* Validates that field types used in the Chain DSL are allowed by the
|
|
5
|
+
* project's constraint configuration.
|
|
6
|
+
*
|
|
7
|
+
* Works with: field.text(), field.number(), field.boolean(), field.enum(),
|
|
8
|
+
* field.dynamicEnum(), field.dynamicSchema(), field.array(), field.object()
|
|
9
|
+
*/
|
|
10
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
11
|
+
import { type FieldTypeConstraints } from "@formspec/constraints/browser";
|
|
12
|
+
export type Options = [FieldTypeConstraints];
|
|
13
|
+
export declare const allowedFieldTypes: ESLintUtils.RuleModule<"disallowedFieldType", Options, unknown, ESLintUtils.RuleListener> & {
|
|
14
|
+
name: string;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=allowed-field-types.d.ts.map
|