@formspec/eslint-plugin 0.1.0-alpha.3
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 +217 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/decorator-field-type-mismatch.d.ts +15 -0
- package/dist/rules/decorator-field-type-mismatch.d.ts.map +1 -0
- package/dist/rules/decorator-field-type-mismatch.js +87 -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 +11 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +11 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/min-max-valid-range.d.ts +26 -0
- package/dist/rules/min-max-valid-range.d.ts.map +1 -0
- package/dist/rules/min-max-valid-range.js +82 -0
- package/dist/rules/min-max-valid-range.js.map +1 -0
- package/dist/rules/no-conflicting-decorators.d.ts +19 -0
- package/dist/rules/no-conflicting-decorators.d.ts.map +1 -0
- package/dist/rules/no-conflicting-decorators.js +76 -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 +74 -0
- package/dist/rules/no-duplicate-decorators.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 +103 -0
- package/dist/utils/decorator-utils.d.ts.map +1 -0
- package/dist/utils/decorator-utils.js +222 -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/type-utils.d.ts +82 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +192 -0
- package/dist/utils/type-utils.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# @formspec/eslint-plugin
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @formspec/eslint-plugin
|
|
9
|
+
# or
|
|
10
|
+
pnpm add -D @formspec/eslint-plugin
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- ESLint v9+ (flat config)
|
|
16
|
+
- TypeScript v5+
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Recommended Configuration
|
|
21
|
+
|
|
22
|
+
Add the plugin to your `eslint.config.js`:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import formspec from "@formspec/eslint-plugin";
|
|
26
|
+
|
|
27
|
+
export default [
|
|
28
|
+
// ... other configs
|
|
29
|
+
...formspec.configs.recommended,
|
|
30
|
+
];
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Manual Configuration
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import formspec from "@formspec/eslint-plugin";
|
|
37
|
+
|
|
38
|
+
export default [
|
|
39
|
+
{
|
|
40
|
+
plugins: {
|
|
41
|
+
"@formspec": formspec,
|
|
42
|
+
},
|
|
43
|
+
rules: {
|
|
44
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
45
|
+
"@formspec/enum-options-match-type": "error",
|
|
46
|
+
"@formspec/showwhen-field-exists": "error",
|
|
47
|
+
"@formspec/showwhen-suggests-optional": "warn",
|
|
48
|
+
"@formspec/min-max-valid-range": "error",
|
|
49
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
50
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
|
|
58
|
+
| Rule | Description | Recommended | Strict |
|
|
59
|
+
|------|-------------|-------------|--------|
|
|
60
|
+
| [`decorator-field-type-mismatch`](#decorator-field-type-mismatch) | Ensures decorators are applied to fields with compatible types | error | error |
|
|
61
|
+
| [`enum-options-match-type`](#enum-options-match-type) | Ensures @EnumOptions values match the field's union type | error | error |
|
|
62
|
+
| [`showwhen-field-exists`](#showwhen-field-exists) | Ensures @ShowWhen references a field that exists | error | error |
|
|
63
|
+
| [`showwhen-suggests-optional`](#showwhen-suggests-optional) | Suggests @ShowWhen fields should be optional | warn | error |
|
|
64
|
+
| [`min-max-valid-range`](#min-max-valid-range) | Ensures @Min/@Max have valid ranges | error | error |
|
|
65
|
+
| [`no-conflicting-decorators`](#no-conflicting-decorators) | Prevents decorators that imply conflicting types | error | error |
|
|
66
|
+
| [`no-duplicate-decorators`](#no-duplicate-decorators) | Prevents duplicate decorators on the same field | error | error |
|
|
67
|
+
|
|
68
|
+
### decorator-field-type-mismatch
|
|
69
|
+
|
|
70
|
+
Ensures FormSpec decorators are applied to fields with compatible types.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Valid
|
|
74
|
+
@Min(0)
|
|
75
|
+
@Max(100)
|
|
76
|
+
age!: number;
|
|
77
|
+
|
|
78
|
+
@Placeholder("Enter name")
|
|
79
|
+
name!: string;
|
|
80
|
+
|
|
81
|
+
@MinItems(1)
|
|
82
|
+
@MaxItems(10)
|
|
83
|
+
items!: string[];
|
|
84
|
+
|
|
85
|
+
// Invalid - @Min requires number field
|
|
86
|
+
@Min(0)
|
|
87
|
+
name!: string; // Error: @Min can only be used on number fields
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### enum-options-match-type
|
|
91
|
+
|
|
92
|
+
Ensures @EnumOptions values match the field's TypeScript union type.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Valid - options match type
|
|
96
|
+
@EnumOptions(["draft", "published", "archived"])
|
|
97
|
+
status!: "draft" | "published" | "archived";
|
|
98
|
+
|
|
99
|
+
// Valid - object options with id property
|
|
100
|
+
@EnumOptions([{ id: "a", label: "Option A" }, { id: "b", label: "Option B" }])
|
|
101
|
+
type!: "a" | "b";
|
|
102
|
+
|
|
103
|
+
// Valid - string type accepts any options
|
|
104
|
+
@EnumOptions(["any", "options"])
|
|
105
|
+
value!: string;
|
|
106
|
+
|
|
107
|
+
// Invalid - missing option "archived"
|
|
108
|
+
@EnumOptions(["draft", "published"])
|
|
109
|
+
status!: "draft" | "published" | "archived"; // Error: missing "archived"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### showwhen-field-exists
|
|
113
|
+
|
|
114
|
+
Ensures @ShowWhen references a field that exists in the same class.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Valid
|
|
118
|
+
@EnumOptions(["a", "b"])
|
|
119
|
+
type!: "a" | "b";
|
|
120
|
+
|
|
121
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
122
|
+
conditionalField?: string;
|
|
123
|
+
|
|
124
|
+
// Invalid - "nonexistent" field doesn't exist
|
|
125
|
+
@ShowWhen({ _predicate: "equals", field: "nonexistent", value: "x" })
|
|
126
|
+
conditionalField?: string; // Error: field "nonexistent" does not exist
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### showwhen-suggests-optional
|
|
130
|
+
|
|
131
|
+
Suggests that fields with @ShowWhen should be marked as optional since they may not be present in the output.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// Valid
|
|
135
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
136
|
+
conditionalField?: string; // Good - optional
|
|
137
|
+
|
|
138
|
+
// Warning
|
|
139
|
+
@ShowWhen({ _predicate: "equals", field: "type", value: "a" })
|
|
140
|
+
conditionalField!: string; // Warning: should be optional
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### min-max-valid-range
|
|
144
|
+
|
|
145
|
+
Ensures @Min value is less than or equal to @Max value.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// Valid
|
|
149
|
+
@Min(0)
|
|
150
|
+
@Max(100)
|
|
151
|
+
value!: number;
|
|
152
|
+
|
|
153
|
+
@Min(5)
|
|
154
|
+
@Max(5) // Equal is valid
|
|
155
|
+
exact!: number;
|
|
156
|
+
|
|
157
|
+
// Invalid
|
|
158
|
+
@Min(100)
|
|
159
|
+
@Max(50) // Error: @Min(100) > @Max(50)
|
|
160
|
+
invalid!: number;
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### no-conflicting-decorators
|
|
164
|
+
|
|
165
|
+
Prevents using decorators that imply conflicting field types.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Valid - both imply number
|
|
169
|
+
@Min(0)
|
|
170
|
+
@Max(100)
|
|
171
|
+
value!: number;
|
|
172
|
+
|
|
173
|
+
// Invalid - @Min implies number, @Placeholder implies string
|
|
174
|
+
@Min(0)
|
|
175
|
+
@Placeholder("Enter value") // Error: conflicting decorators
|
|
176
|
+
field!: string;
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### no-duplicate-decorators
|
|
180
|
+
|
|
181
|
+
Prevents applying the same decorator multiple times to a field.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// Valid
|
|
185
|
+
@Label("Name")
|
|
186
|
+
@Placeholder("Enter name")
|
|
187
|
+
name!: string;
|
|
188
|
+
|
|
189
|
+
// Invalid
|
|
190
|
+
@Label("First")
|
|
191
|
+
@Label("Second") // Error: duplicate @Label
|
|
192
|
+
name!: string;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Configurations
|
|
196
|
+
|
|
197
|
+
### Recommended
|
|
198
|
+
|
|
199
|
+
Sensible defaults for most projects:
|
|
200
|
+
- All type safety rules enabled as errors
|
|
201
|
+
- `showwhen-suggests-optional` as warning (not blocking)
|
|
202
|
+
|
|
203
|
+
### Strict
|
|
204
|
+
|
|
205
|
+
All rules enabled as errors for maximum type safety enforcement.
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
import formspec from "@formspec/eslint-plugin";
|
|
209
|
+
|
|
210
|
+
export default [
|
|
211
|
+
...formspec.configs.strict,
|
|
212
|
+
];
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
UNLICENSED
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @formspec/eslint-plugin
|
|
3
|
+
*
|
|
4
|
+
* ESLint plugin for FormSpec decorator DSL type safety.
|
|
5
|
+
*
|
|
6
|
+
* Provides rules to catch common mistakes when using FormSpec decorators:
|
|
7
|
+
* - Type mismatches between decorators and field types
|
|
8
|
+
* - Invalid enum option configurations
|
|
9
|
+
* - Missing or invalid @ShowWhen references
|
|
10
|
+
* - Conflicting or duplicate decorators
|
|
11
|
+
*/
|
|
12
|
+
import type { TSESLint } from "@typescript-eslint/utils";
|
|
13
|
+
import { decoratorFieldTypeMismatch } from "./rules/decorator-field-type-mismatch.js";
|
|
14
|
+
import { enumOptionsMatchType } from "./rules/enum-options-match-type.js";
|
|
15
|
+
import { showwhenFieldExists } from "./rules/showwhen-field-exists.js";
|
|
16
|
+
import { showwhenSuggestsOptional } from "./rules/showwhen-suggests-optional.js";
|
|
17
|
+
import { minMaxValidRange } from "./rules/min-max-valid-range.js";
|
|
18
|
+
import { noConflictingDecorators } from "./rules/no-conflicting-decorators.js";
|
|
19
|
+
import { noDuplicateDecorators } from "./rules/no-duplicate-decorators.js";
|
|
20
|
+
/**
|
|
21
|
+
* The FormSpec ESLint plugin.
|
|
22
|
+
*/
|
|
23
|
+
declare const plugin: {
|
|
24
|
+
meta: {
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
rules: {
|
|
28
|
+
readonly "decorator-field-type-mismatch": TSESLint.RuleModule<"minMaxOnNonNumber" | "minMaxItemsOnNonArray" | "placeholderOnNonString", [], unknown, TSESLint.RuleListener> & {
|
|
29
|
+
name: string;
|
|
30
|
+
};
|
|
31
|
+
readonly "enum-options-match-type": TSESLint.RuleModule<"enumOptionsMismatch" | "enumOptionsMissing" | "enumOptionsExtra", [], unknown, TSESLint.RuleListener> & {
|
|
32
|
+
name: string;
|
|
33
|
+
};
|
|
34
|
+
readonly "showwhen-field-exists": TSESLint.RuleModule<"fieldDoesNotExist", [], unknown, TSESLint.RuleListener> & {
|
|
35
|
+
name: string;
|
|
36
|
+
};
|
|
37
|
+
readonly "showwhen-suggests-optional": TSESLint.RuleModule<"shouldBeOptional", [], unknown, TSESLint.RuleListener> & {
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
40
|
+
readonly "min-max-valid-range": TSESLint.RuleModule<"minGreaterThanMax" | "minItemsGreaterThanMaxItems", [], unknown, TSESLint.RuleListener> & {
|
|
41
|
+
name: string;
|
|
42
|
+
};
|
|
43
|
+
readonly "no-conflicting-decorators": TSESLint.RuleModule<"conflictingDecorators", [], unknown, TSESLint.RuleListener> & {
|
|
44
|
+
name: string;
|
|
45
|
+
};
|
|
46
|
+
readonly "no-duplicate-decorators": TSESLint.RuleModule<"duplicateDecorator", [], unknown, TSESLint.RuleListener> & {
|
|
47
|
+
name: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
configs: {
|
|
51
|
+
recommended: TSESLint.FlatConfig.ConfigArray;
|
|
52
|
+
strict: TSESLint.FlatConfig.ConfigArray;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export default plugin;
|
|
56
|
+
export { decoratorFieldTypeMismatch, enumOptionsMatchType, showwhenFieldExists, showwhenSuggestsOptional, minMaxValidRange, noConflictingDecorators, noDuplicateDecorators, };
|
|
57
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;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,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AA6E3E;;GAEG;AACH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOX,CAAC;AAEF,eAAe,MAAM,CAAC;AAGtB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,GACtB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @formspec/eslint-plugin
|
|
3
|
+
*
|
|
4
|
+
* ESLint plugin for FormSpec decorator DSL type safety.
|
|
5
|
+
*
|
|
6
|
+
* Provides rules to catch common mistakes when using FormSpec decorators:
|
|
7
|
+
* - Type mismatches between decorators and field types
|
|
8
|
+
* - Invalid enum option configurations
|
|
9
|
+
* - Missing or invalid @ShowWhen references
|
|
10
|
+
* - Conflicting or duplicate decorators
|
|
11
|
+
*/
|
|
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 { minMaxValidRange } from "./rules/min-max-valid-range.js";
|
|
17
|
+
import { noConflictingDecorators } from "./rules/no-conflicting-decorators.js";
|
|
18
|
+
import { noDuplicateDecorators } from "./rules/no-duplicate-decorators.js";
|
|
19
|
+
/**
|
|
20
|
+
* All rules provided by this plugin.
|
|
21
|
+
*/
|
|
22
|
+
const rules = {
|
|
23
|
+
"decorator-field-type-mismatch": decoratorFieldTypeMismatch,
|
|
24
|
+
"enum-options-match-type": enumOptionsMatchType,
|
|
25
|
+
"showwhen-field-exists": showwhenFieldExists,
|
|
26
|
+
"showwhen-suggests-optional": showwhenSuggestsOptional,
|
|
27
|
+
"min-max-valid-range": minMaxValidRange,
|
|
28
|
+
"no-conflicting-decorators": noConflictingDecorators,
|
|
29
|
+
"no-duplicate-decorators": noDuplicateDecorators,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Plugin metadata.
|
|
33
|
+
*/
|
|
34
|
+
const meta = {
|
|
35
|
+
name: "@formspec/eslint-plugin",
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Recommended configuration for FormSpec projects.
|
|
39
|
+
*
|
|
40
|
+
* Usage:
|
|
41
|
+
* ```javascript
|
|
42
|
+
* import formspec from "@formspec/eslint-plugin";
|
|
43
|
+
*
|
|
44
|
+
* export default [
|
|
45
|
+
* ...formspec.configs.recommended,
|
|
46
|
+
* ];
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
const recommendedConfig = [
|
|
50
|
+
{
|
|
51
|
+
plugins: {
|
|
52
|
+
"@formspec": {
|
|
53
|
+
meta,
|
|
54
|
+
rules,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
rules: {
|
|
58
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
59
|
+
"@formspec/enum-options-match-type": "error",
|
|
60
|
+
"@formspec/showwhen-field-exists": "error",
|
|
61
|
+
"@formspec/showwhen-suggests-optional": "warn",
|
|
62
|
+
"@formspec/min-max-valid-range": "error",
|
|
63
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
64
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Strict configuration - all rules as errors.
|
|
70
|
+
*/
|
|
71
|
+
const strictConfig = [
|
|
72
|
+
{
|
|
73
|
+
plugins: {
|
|
74
|
+
"@formspec": {
|
|
75
|
+
meta,
|
|
76
|
+
rules,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
rules: {
|
|
80
|
+
"@formspec/decorator-field-type-mismatch": "error",
|
|
81
|
+
"@formspec/enum-options-match-type": "error",
|
|
82
|
+
"@formspec/showwhen-field-exists": "error",
|
|
83
|
+
"@formspec/showwhen-suggests-optional": "error",
|
|
84
|
+
"@formspec/min-max-valid-range": "error",
|
|
85
|
+
"@formspec/no-conflicting-decorators": "error",
|
|
86
|
+
"@formspec/no-duplicate-decorators": "error",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
/**
|
|
91
|
+
* The FormSpec ESLint plugin.
|
|
92
|
+
*/
|
|
93
|
+
const plugin = {
|
|
94
|
+
meta,
|
|
95
|
+
rules,
|
|
96
|
+
configs: {
|
|
97
|
+
recommended: recommendedConfig,
|
|
98
|
+
strict: strictConfig,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
export default plugin;
|
|
102
|
+
// Named exports for individual rules
|
|
103
|
+
export { decoratorFieldTypeMismatch, enumOptionsMatchType, showwhenFieldExists, showwhenSuggestsOptional, minMaxValidRange, noConflictingDecorators, noDuplicateDecorators, };
|
|
104
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;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,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E;;GAEG;AACH,MAAM,KAAK,GAAG;IACZ,+BAA+B,EAAE,0BAA0B;IAC3D,yBAAyB,EAAE,oBAAoB;IAC/C,uBAAuB,EAAE,mBAAmB;IAC5C,4BAA4B,EAAE,wBAAwB;IACtD,qBAAqB,EAAE,gBAAgB;IACvC,2BAA2B,EAAE,uBAAuB;IACpD,yBAAyB,EAAE,qBAAqB;CACxC,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,+BAA+B,EAAE,OAAO;YACxC,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,+BAA+B,EAAE,OAAO;YACxC,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,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,GACtB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: decorator-field-type-mismatch
|
|
3
|
+
*
|
|
4
|
+
* Ensures FormSpec decorators are applied to fields with compatible types:
|
|
5
|
+
* - @Min/@Max only on number fields
|
|
6
|
+
* - @MinItems/@MaxItems only on array fields
|
|
7
|
+
* - @Placeholder only on string fields
|
|
8
|
+
*/
|
|
9
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
10
|
+
type MessageIds = "minMaxOnNonNumber" | "minMaxItemsOnNonArray" | "placeholderOnNonString";
|
|
11
|
+
export declare const decoratorFieldTypeMismatch: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=decorator-field-type-mismatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-field-type-mismatch.d.ts","sourceRoot":"","sources":["../../src/rules/decorator-field-type-mismatch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,0BAA0B,CAAC;AAgBvE,KAAK,UAAU,GACX,mBAAmB,GACnB,uBAAuB,GACvB,wBAAwB,CAAC;AAmB7B,eAAO,MAAM,0BAA0B;;CAoErC,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: decorator-field-type-mismatch
|
|
3
|
+
*
|
|
4
|
+
* Ensures FormSpec decorators are applied to fields with compatible types:
|
|
5
|
+
* - @Min/@Max only on number fields
|
|
6
|
+
* - @MinItems/@MaxItems only on array fields
|
|
7
|
+
* - @Placeholder only on string fields
|
|
8
|
+
*/
|
|
9
|
+
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
10
|
+
import { getFormSpecDecorators, DECORATOR_TYPE_HINTS, } from "../utils/decorator-utils.js";
|
|
11
|
+
import { getPropertyType, getFieldTypeCategory, } from "../utils/type-utils.js";
|
|
12
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://formspec.dev/eslint-plugin/rules/${name}`);
|
|
13
|
+
const EXPECTED_TYPES = {
|
|
14
|
+
Min: ["number"],
|
|
15
|
+
Max: ["number"],
|
|
16
|
+
Placeholder: ["string"],
|
|
17
|
+
MinItems: ["array"],
|
|
18
|
+
MaxItems: ["array"],
|
|
19
|
+
EnumOptions: ["string", "union"], // Handled by separate rule
|
|
20
|
+
};
|
|
21
|
+
const DECORATOR_MESSAGE_IDS = {
|
|
22
|
+
Min: "minMaxOnNonNumber",
|
|
23
|
+
Max: "minMaxOnNonNumber",
|
|
24
|
+
Placeholder: "placeholderOnNonString",
|
|
25
|
+
MinItems: "minMaxItemsOnNonArray",
|
|
26
|
+
MaxItems: "minMaxItemsOnNonArray",
|
|
27
|
+
};
|
|
28
|
+
export const decoratorFieldTypeMismatch = createRule({
|
|
29
|
+
name: "decorator-field-type-mismatch",
|
|
30
|
+
meta: {
|
|
31
|
+
type: "problem",
|
|
32
|
+
docs: {
|
|
33
|
+
description: "Ensures FormSpec decorators are applied to fields with compatible types",
|
|
34
|
+
},
|
|
35
|
+
messages: {
|
|
36
|
+
minMaxOnNonNumber: "@{{decorator}} can only be used on number fields, but field '{{field}}' has type '{{actualType}}'",
|
|
37
|
+
minMaxItemsOnNonArray: "@{{decorator}} can only be used on array fields, but field '{{field}}' has type '{{actualType}}'",
|
|
38
|
+
placeholderOnNonString: "@Placeholder can only be used on string fields, but field '{{field}}' has type '{{actualType}}'",
|
|
39
|
+
},
|
|
40
|
+
schema: [],
|
|
41
|
+
},
|
|
42
|
+
defaultOptions: [],
|
|
43
|
+
create(context) {
|
|
44
|
+
const services = ESLintUtils.getParserServices(context);
|
|
45
|
+
const checker = services.program.getTypeChecker();
|
|
46
|
+
return {
|
|
47
|
+
PropertyDefinition(node) {
|
|
48
|
+
const decorators = getFormSpecDecorators(node);
|
|
49
|
+
if (decorators.length === 0)
|
|
50
|
+
return;
|
|
51
|
+
const type = getPropertyType(node, services);
|
|
52
|
+
if (!type)
|
|
53
|
+
return;
|
|
54
|
+
const fieldTypeCategory = getFieldTypeCategory(type, checker);
|
|
55
|
+
const fieldName = node.key.type === AST_NODE_TYPES.Identifier ? node.key.name : "<computed>";
|
|
56
|
+
const actualType = checker.typeToString(type);
|
|
57
|
+
for (const decorator of decorators) {
|
|
58
|
+
const decoratorName = decorator.name;
|
|
59
|
+
// Skip decorators that don't have type hints
|
|
60
|
+
if (!(decoratorName in DECORATOR_TYPE_HINTS))
|
|
61
|
+
continue;
|
|
62
|
+
// Skip EnumOptions - handled by separate rule
|
|
63
|
+
if (decoratorName === "EnumOptions")
|
|
64
|
+
continue;
|
|
65
|
+
const expectedTypes = EXPECTED_TYPES[decoratorName];
|
|
66
|
+
// Check if field type matches any expected type
|
|
67
|
+
const isCompatible = expectedTypes.includes(fieldTypeCategory);
|
|
68
|
+
if (!isCompatible) {
|
|
69
|
+
const messageId = DECORATOR_MESSAGE_IDS[decoratorName];
|
|
70
|
+
if (!messageId)
|
|
71
|
+
continue;
|
|
72
|
+
context.report({
|
|
73
|
+
node: decorator.node,
|
|
74
|
+
messageId,
|
|
75
|
+
data: {
|
|
76
|
+
decorator: decoratorName,
|
|
77
|
+
field: fieldName,
|
|
78
|
+
actualType,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=decorator-field-type-mismatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-field-type-mismatch.js","sourceRoot":"","sources":["../../src/rules/decorator-field-type-mismatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: enum-options-match-type
|
|
3
|
+
*
|
|
4
|
+
* Ensures @EnumOptions values match the field's TypeScript type.
|
|
5
|
+
*
|
|
6
|
+
* Valid:
|
|
7
|
+
* @EnumOptions(["a", "b", "c"])
|
|
8
|
+
* field!: "a" | "b" | "c";
|
|
9
|
+
*
|
|
10
|
+
* @EnumOptions([{ id: "x", label: "X" }])
|
|
11
|
+
* field!: "x";
|
|
12
|
+
*
|
|
13
|
+
* @EnumOptions(["a", "b"])
|
|
14
|
+
* field!: string; // Permissive - string accepts any enum
|
|
15
|
+
*
|
|
16
|
+
* Invalid:
|
|
17
|
+
* @EnumOptions(["a", "b", "c"])
|
|
18
|
+
* field!: "x" | "y"; // Mismatch
|
|
19
|
+
*/
|
|
20
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
21
|
+
type MessageIds = "enumOptionsMismatch" | "enumOptionsMissing" | "enumOptionsExtra";
|
|
22
|
+
export declare const enumOptionsMatchType: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
|
|
23
|
+
name: string;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=enum-options-match-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-options-match-type.d.ts","sourceRoot":"","sources":["../../src/rules/enum-options-match-type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAevD,KAAK,UAAU,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;AAEpF,eAAO,MAAM,oBAAoB;;CAqG/B,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: enum-options-match-type
|
|
3
|
+
*
|
|
4
|
+
* Ensures @EnumOptions values match the field's TypeScript type.
|
|
5
|
+
*
|
|
6
|
+
* Valid:
|
|
7
|
+
* @EnumOptions(["a", "b", "c"])
|
|
8
|
+
* field!: "a" | "b" | "c";
|
|
9
|
+
*
|
|
10
|
+
* @EnumOptions([{ id: "x", label: "X" }])
|
|
11
|
+
* field!: "x";
|
|
12
|
+
*
|
|
13
|
+
* @EnumOptions(["a", "b"])
|
|
14
|
+
* field!: string; // Permissive - string accepts any enum
|
|
15
|
+
*
|
|
16
|
+
* Invalid:
|
|
17
|
+
* @EnumOptions(["a", "b", "c"])
|
|
18
|
+
* field!: "x" | "y"; // Mismatch
|
|
19
|
+
*/
|
|
20
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
21
|
+
import { findDecorator, getDecoratorArrayArg, } from "../utils/decorator-utils.js";
|
|
22
|
+
import { getPropertyType, getStringLiteralUnionValues, isStringType, } from "../utils/type-utils.js";
|
|
23
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://formspec.dev/eslint-plugin/rules/${name}`);
|
|
24
|
+
export const enumOptionsMatchType = createRule({
|
|
25
|
+
name: "enum-options-match-type",
|
|
26
|
+
meta: {
|
|
27
|
+
type: "problem",
|
|
28
|
+
docs: {
|
|
29
|
+
description: "Ensures @EnumOptions values match the field's TypeScript union type",
|
|
30
|
+
},
|
|
31
|
+
messages: {
|
|
32
|
+
enumOptionsMismatch: "@EnumOptions values don't match field type. Options: [{{options}}], Type: {{fieldType}}",
|
|
33
|
+
enumOptionsMissing: "@EnumOptions is missing values that are in the field type: [{{missing}}]",
|
|
34
|
+
enumOptionsExtra: "@EnumOptions has values not in the field type: [{{extra}}]",
|
|
35
|
+
},
|
|
36
|
+
schema: [],
|
|
37
|
+
},
|
|
38
|
+
defaultOptions: [],
|
|
39
|
+
create(context) {
|
|
40
|
+
const services = ESLintUtils.getParserServices(context);
|
|
41
|
+
const checker = services.program.getTypeChecker();
|
|
42
|
+
return {
|
|
43
|
+
PropertyDefinition(node) {
|
|
44
|
+
const enumOptionsDecorator = findDecorator(node, "EnumOptions");
|
|
45
|
+
if (!enumOptionsDecorator)
|
|
46
|
+
return;
|
|
47
|
+
const type = getPropertyType(node, services);
|
|
48
|
+
if (!type)
|
|
49
|
+
return;
|
|
50
|
+
// If field type is plain `string`, any enum options are valid
|
|
51
|
+
if (isStringType(type, checker) && !type.isUnion()) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Get the enum option values from the decorator
|
|
55
|
+
const decoratorValues = getDecoratorArrayArg(enumOptionsDecorator);
|
|
56
|
+
if (!decoratorValues)
|
|
57
|
+
return;
|
|
58
|
+
// Extract IDs from decorator options
|
|
59
|
+
const optionIds = new Set();
|
|
60
|
+
for (const value of decoratorValues) {
|
|
61
|
+
if (typeof value === "string") {
|
|
62
|
+
optionIds.add(value);
|
|
63
|
+
}
|
|
64
|
+
else if (typeof value === "object" && value !== null && "id" in value) {
|
|
65
|
+
const id = value.id;
|
|
66
|
+
if (typeof id === "string") {
|
|
67
|
+
optionIds.add(id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Get the union type values from the field type
|
|
72
|
+
const typeValues = getStringLiteralUnionValues(type, checker);
|
|
73
|
+
if (!typeValues) {
|
|
74
|
+
// Field type is not a string literal union - can't compare
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const typeSet = new Set(typeValues);
|
|
78
|
+
// Find missing values (in type but not in options)
|
|
79
|
+
const missing = [];
|
|
80
|
+
for (const v of typeValues) {
|
|
81
|
+
if (!optionIds.has(v)) {
|
|
82
|
+
missing.push(v);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Find extra values (in options but not in type)
|
|
86
|
+
const extra = [];
|
|
87
|
+
for (const v of optionIds) {
|
|
88
|
+
if (!typeSet.has(v)) {
|
|
89
|
+
extra.push(v);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Report specific issues
|
|
93
|
+
if (missing.length > 0) {
|
|
94
|
+
context.report({
|
|
95
|
+
node: enumOptionsDecorator.node,
|
|
96
|
+
messageId: "enumOptionsMissing",
|
|
97
|
+
data: {
|
|
98
|
+
missing: missing.map((v) => `"${v}"`).join(", "),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (extra.length > 0) {
|
|
103
|
+
context.report({
|
|
104
|
+
node: enumOptionsDecorator.node,
|
|
105
|
+
messageId: "enumOptionsExtra",
|
|
106
|
+
data: {
|
|
107
|
+
extra: extra.map((v) => `"${v}"`).join(", "),
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=enum-options-match-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-options-match-type.js","sourceRoot":"","sources":["../../src/rules/enum-options-match-type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* All FormSpec ESLint rules.
|
|
3
|
+
*/
|
|
4
|
+
export { decoratorFieldTypeMismatch } from "./decorator-field-type-mismatch.js";
|
|
5
|
+
export { enumOptionsMatchType } from "./enum-options-match-type.js";
|
|
6
|
+
export { showwhenFieldExists } from "./showwhen-field-exists.js";
|
|
7
|
+
export { showwhenSuggestsOptional } from "./showwhen-suggests-optional.js";
|
|
8
|
+
export { minMaxValidRange } from "./min-max-valid-range.js";
|
|
9
|
+
export { noConflictingDecorators } from "./no-conflicting-decorators.js";
|
|
10
|
+
export { noDuplicateDecorators } from "./no-duplicate-decorators.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC"}
|