lint-suite 1.2.3 → 1.3.1
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 +72 -43
- package/index.cjs +175 -27
- package/index.cjs.map +4 -4
- package/index.d.ts +2 -1
- package/index.d.ts.map +1 -1
- package/index.js +174 -27
- package/index.js.map +4 -4
- package/lib/angular-template.d.ts.map +1 -1
- package/lib/angular.d.ts.map +1 -1
- package/lib/base.d.ts.map +1 -1
- package/lib/jest.d.ts.map +1 -1
- package/lib/json.d.ts.map +1 -1
- package/lib/playwright.d.ts.map +1 -1
- package/lib/prettier.d.ts +2 -0
- package/lib/prettier.d.ts.map +1 -0
- package/lib/rules/explicit-accessibility.d.ts +3 -1
- package/lib/rules/explicit-accessibility.d.ts.map +1 -1
- package/lib/rxjs.d.ts.map +1 -1
- package/lib/storybook.d.ts.map +1 -1
- package/lib/typescript.d.ts.map +1 -1
- package/lib/vitest.d.ts.map +1 -1
- package/package.json +17 -16
package/README.md
CHANGED
|
@@ -4,61 +4,76 @@ A comprehensive collection of ESLint Flat configurations for modern web applicat
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **TypeScript Linting**: Strict typing rules, consistent imports, and code organization
|
|
8
|
-
- **Angular Support**: Component best practices (including Signals), template
|
|
9
|
-
- **RxJS Guidelines**: Observable patterns, Finnish notation, and operator safety
|
|
7
|
+
- **TypeScript Linting**: Strict typing rules, v8 type-safety replacements, consistent imports, and code organization
|
|
8
|
+
- **Angular Support**: Component best practices (including Signals), Angular 21+ template rules, and modern control flow
|
|
9
|
+
- **RxJS Guidelines**: Observable patterns, Finnish notation, subject encapsulation, and operator safety
|
|
10
10
|
- **Code Style**: Formatting rules, line limits, and structural consistency
|
|
11
11
|
- **Accessibility**: ARIA validation, keyboard events, and semantic HTML
|
|
12
|
-
- **Testing**: Jest
|
|
13
|
-
- **
|
|
12
|
+
- **Testing**: Jest, Vitest, and Playwright configurations with best-practice rules
|
|
13
|
+
- **Prettier**: Automatic disabling of formatting rules that conflict with Prettier
|
|
14
|
+
- **Architecture**: Module boundary enforcement with `eslint-plugin-boundaries`
|
|
15
|
+
- **Additional Support**: JSON (with comment support for tsconfig), Storybook CSF enforcement
|
|
14
16
|
|
|
15
17
|
## Installation
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
|
-
|
|
20
|
+
pnpm add -D lint-suite
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
## Dependencies
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
|
-
|
|
26
|
+
pnpm add -D eslint typescript-eslint eslint-config-prettier
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
## Usage
|
|
28
30
|
|
|
29
|
-
Create
|
|
31
|
+
Create an `eslint.config.mjs` file in your project root:
|
|
30
32
|
|
|
31
33
|
```js
|
|
32
|
-
import {
|
|
34
|
+
import { recommended } from 'lint-suite';
|
|
35
|
+
|
|
36
|
+
export default [...recommended];
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or selectively include configurations:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import { base, javascript, typescript, prettier } from 'lint-suite';
|
|
33
43
|
|
|
34
44
|
export default [
|
|
35
45
|
...base,
|
|
36
46
|
...javascript,
|
|
37
|
-
...typescript
|
|
38
|
-
//
|
|
47
|
+
...typescript,
|
|
48
|
+
...prettier // Must be last to disable conflicting formatting rules
|
|
39
49
|
];
|
|
40
50
|
```
|
|
41
51
|
|
|
42
|
-
You can selectively include configurations you need.
|
|
43
|
-
|
|
44
52
|
## Available Configurations
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
| Configuration | Description |
|
|
55
|
+
| ------------------- | -------------------------------------------------------- |
|
|
56
|
+
| `base` | Core JavaScript rules, formatting, and complexity limits |
|
|
57
|
+
| `javascript` | JavaScript-specific rules via `@nx/eslint-plugin` |
|
|
58
|
+
| `typescript` | TypeScript strict typing, imports, and naming conventions |
|
|
59
|
+
| `angular` | Angular component best practices with Signal support |
|
|
60
|
+
| `angularTemplate` | HTML template rules with accessibility and performance |
|
|
61
|
+
| `rxjs` | Observable patterns, operator safety, and subscriptions |
|
|
62
|
+
| `jest` | Jest testing best practices and matchers |
|
|
63
|
+
| `vitest` | Vitest testing rules and matcher improvements |
|
|
64
|
+
| `playwright` | Playwright e2e locator and matcher best practices |
|
|
65
|
+
| `json` | JSON linting with comment support for tsconfig/vscode |
|
|
66
|
+
| `storybook` | Storybook CSF enforcement |
|
|
67
|
+
| `boundaries` | Module boundary rules (feature, data-access, ui, etc.) |
|
|
68
|
+
| `prettier` | Disables rules that conflict with Prettier (use last) |
|
|
69
|
+
| **`recommended`** | **All of the above combined in the correct order** |
|
|
55
70
|
|
|
56
71
|
## Customization
|
|
57
72
|
|
|
58
73
|
You can override any rules by adding a `rules` section to your ESLint config:
|
|
59
74
|
|
|
60
75
|
```js
|
|
61
|
-
import { typescript } from 'lint-suite';
|
|
76
|
+
import { typescript, prettier } from 'lint-suite';
|
|
62
77
|
|
|
63
78
|
export default [
|
|
64
79
|
...typescript,
|
|
@@ -66,7 +81,8 @@ export default [
|
|
|
66
81
|
rules: {
|
|
67
82
|
'@typescript-eslint/explicit-function-return-type': 'off'
|
|
68
83
|
}
|
|
69
|
-
}
|
|
84
|
+
},
|
|
85
|
+
...prettier
|
|
70
86
|
];
|
|
71
87
|
```
|
|
72
88
|
|
|
@@ -80,9 +96,24 @@ export default [
|
|
|
80
96
|
|
|
81
97
|
### eslint-plugin-jest
|
|
82
98
|
|
|
83
|
-
- `jest/
|
|
84
|
-
- `jest/
|
|
85
|
-
- `jest/
|
|
99
|
+
- `jest/consistent-test-it`: Enforces consistent test function usage (`it`)
|
|
100
|
+
- `jest/prefer-comparison-matcher`: Enforces comparison matchers
|
|
101
|
+
- `jest/prefer-hooks-on-top`: Ensures hooks are at the top of describe blocks
|
|
102
|
+
- `jest/no-conditional-in-test`: Warns against conditionals in tests
|
|
103
|
+
- ...
|
|
104
|
+
|
|
105
|
+
### @vitest/eslint-plugin
|
|
106
|
+
|
|
107
|
+
- `vitest/max-nested-describe`: Limits describe nesting depth
|
|
108
|
+
- `vitest/prefer-to-be`: Enforces `toBe` matcher usage
|
|
109
|
+
- `vitest/no-conditional-in-test`: Disallows conditionals in tests
|
|
110
|
+
- ...
|
|
111
|
+
|
|
112
|
+
### eslint-plugin-playwright
|
|
113
|
+
|
|
114
|
+
- `playwright/prefer-locator`: Enforces modern locator API
|
|
115
|
+
- `playwright/prefer-native-locators`: Prefers native locator methods
|
|
116
|
+
- `playwright/prefer-to-be`: Enforces `toBe` matcher usage
|
|
86
117
|
- ...
|
|
87
118
|
|
|
88
119
|
### eslint-plugin-json
|
|
@@ -94,22 +125,23 @@ export default [
|
|
|
94
125
|
### @smarttools/eslint-plugin-rxjs
|
|
95
126
|
|
|
96
127
|
- `@rxjs/finnish`: Enforces Finnish notation for observables
|
|
97
|
-
- `@rxjs/no-
|
|
128
|
+
- `@rxjs/no-exposed-subjects`: Enforces subject encapsulation
|
|
129
|
+
- `@rxjs/no-cyclic-action`: Prevents infinite loops in NgRx effects
|
|
98
130
|
- `@rxjs/no-unsafe-takeuntil`: Ensures proper usage of takeUntil operator
|
|
99
131
|
- ...
|
|
100
132
|
|
|
101
133
|
### eslint-plugin-storybook
|
|
102
134
|
|
|
103
|
-
- `storybook/
|
|
104
|
-
- `storybook/
|
|
105
|
-
- `storybook/hierarchy-separator`: Enforces story hierarchy separators
|
|
135
|
+
- `storybook/csf-component`: Enforces component property in stories
|
|
136
|
+
- `storybook/no-stories-of`: Prevents deprecated `storiesOf` API
|
|
106
137
|
- ...
|
|
107
138
|
|
|
108
|
-
### eslint-plugin-import
|
|
139
|
+
### eslint-plugin-import-x
|
|
109
140
|
|
|
110
|
-
- `import/no-
|
|
111
|
-
- `import/
|
|
112
|
-
- `import/
|
|
141
|
+
- `import-x/no-cycle`: Detects circular dependencies
|
|
142
|
+
- `import-x/no-self-import`: Prevents modules importing themselves
|
|
143
|
+
- `import-x/order`: Enforces a consistent order of import statements
|
|
144
|
+
- `import-x/consistent-type-specifier-style`: Consistent type import style
|
|
113
145
|
- ...
|
|
114
146
|
|
|
115
147
|
### @stylistic/eslint-plugin
|
|
@@ -119,6 +151,11 @@ export default [
|
|
|
119
151
|
- `@stylistic/quotes`: Enforces consistent quote style
|
|
120
152
|
- ...
|
|
121
153
|
|
|
154
|
+
### eslint-config-prettier
|
|
155
|
+
|
|
156
|
+
- Automatically disables all ESLint rules that conflict with Prettier
|
|
157
|
+
- Must be the last configuration in the array
|
|
158
|
+
|
|
122
159
|
## Contributing
|
|
123
160
|
|
|
124
161
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
|
|
@@ -128,11 +165,3 @@ See [RELEASE_NOTES.md](./RELEASE_NOTES.md) for detailed release notes.
|
|
|
128
165
|
## License
|
|
129
166
|
|
|
130
167
|
MIT
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
```
|
package/index.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(index_exports, {
|
|
|
38
38
|
jest: () => jest,
|
|
39
39
|
json: () => json,
|
|
40
40
|
playwright: () => playwright,
|
|
41
|
+
prettier: () => prettier,
|
|
41
42
|
recommended: () => recommended,
|
|
42
43
|
rxjs: () => rxjs,
|
|
43
44
|
storybook: () => storybook,
|
|
@@ -78,6 +79,23 @@ var angularTemplate = (0, import_config.defineConfig)([
|
|
|
78
79
|
"@angular-eslint/template/no-nested-tags": "error",
|
|
79
80
|
"@angular-eslint/template/use-track-by-function": "error",
|
|
80
81
|
"@angular-eslint/template/label-has-associated-control": "error",
|
|
82
|
+
"@angular-eslint/template/prefer-at-else": "error",
|
|
83
|
+
// v21: @if/@else syntax
|
|
84
|
+
"@angular-eslint/template/prefer-at-empty": "error",
|
|
85
|
+
// v21: @for/@empty syntax
|
|
86
|
+
"@angular-eslint/template/prefer-contextual-for-variables": "error",
|
|
87
|
+
// v21: Use $index, $first, etc.
|
|
88
|
+
"@angular-eslint/template/no-empty-control-flow": "error",
|
|
89
|
+
// v21: Catch incomplete refactoring
|
|
90
|
+
"@angular-eslint/template/prefer-class-binding": "error",
|
|
91
|
+
// v21.2.0: Prefer [class] over ngClass
|
|
92
|
+
"@angular-eslint/template/prefer-static-string-properties": "error",
|
|
93
|
+
// Reduce change detection
|
|
94
|
+
"@angular-eslint/template/conditional-complexity": [
|
|
95
|
+
"warn",
|
|
96
|
+
{ maxComplexity: 5 }
|
|
97
|
+
],
|
|
98
|
+
// Template readability
|
|
81
99
|
"@angular-eslint/template/attributes-order": [
|
|
82
100
|
"error",
|
|
83
101
|
{
|
|
@@ -124,7 +142,17 @@ var angular = (0, import_config2.defineConfig)([
|
|
|
124
142
|
"@angular-eslint/use-injectable-provided-in": "error",
|
|
125
143
|
"@angular-eslint/prefer-signal-model": "error",
|
|
126
144
|
"@angular-eslint/no-uncalled-signals": "error",
|
|
127
|
-
"@angular-eslint/prefer-host-metadata-property": "error"
|
|
145
|
+
"@angular-eslint/prefer-host-metadata-property": "error",
|
|
146
|
+
"@angular-eslint/no-implicit-take-until-destroyed": "error",
|
|
147
|
+
// v21.2.0: Enforce explicit DestroyRef
|
|
148
|
+
"@angular-eslint/no-async-lifecycle-method": "error",
|
|
149
|
+
// Prevent async lifecycle hooks
|
|
150
|
+
"@angular-eslint/prefer-output-readonly": "warn",
|
|
151
|
+
// Prevent accidental reassignment
|
|
152
|
+
"@angular-eslint/prefer-output-emitter-ref": "warn",
|
|
153
|
+
// Modern output() function over @Output()
|
|
154
|
+
"@angular-eslint/sort-lifecycle-methods": "warn"
|
|
155
|
+
// Consistent lifecycle method ordering
|
|
128
156
|
}
|
|
129
157
|
}
|
|
130
158
|
]);
|
|
@@ -187,7 +215,10 @@ var base = (0, import_config3.defineConfig)([
|
|
|
187
215
|
"no-useless-concat": "error",
|
|
188
216
|
"prefer-template": "error",
|
|
189
217
|
"no-nested-ternary": "error",
|
|
190
|
-
"no-
|
|
218
|
+
"no-useless-assignment": "error",
|
|
219
|
+
// NEW: Catch unused assignments (ESLint v9)
|
|
220
|
+
"no-object-constructor": "error",
|
|
221
|
+
// Disallow new Object() without arguments
|
|
191
222
|
"no-else-return": ["error", { allowElseIf: false }],
|
|
192
223
|
// Prefer early returns
|
|
193
224
|
"no-multi-assign": "error",
|
|
@@ -369,9 +400,29 @@ var import_config5 = require("eslint/config");
|
|
|
369
400
|
var jest = (0, import_config5.defineConfig)([
|
|
370
401
|
{
|
|
371
402
|
files: ["**/*.spec.ts", "**/*.spec.js"],
|
|
372
|
-
extends: [import_eslint_plugin_jest.default.configs["flat/
|
|
403
|
+
extends: [import_eslint_plugin_jest.default.configs["flat/recommended"]],
|
|
373
404
|
rules: {
|
|
374
|
-
"jest/no-done-callback": "off"
|
|
405
|
+
"jest/no-done-callback": "off",
|
|
406
|
+
// Elevated from recommended defaults
|
|
407
|
+
"jest/no-focused-tests": "error",
|
|
408
|
+
"jest/no-identical-title": "error",
|
|
409
|
+
"jest/valid-expect": "error",
|
|
410
|
+
// Style rules (selective additions from flat/style)
|
|
411
|
+
"jest/prefer-to-be": "warn",
|
|
412
|
+
"jest/prefer-to-contain": "warn",
|
|
413
|
+
"jest/prefer-to-have-length": "warn",
|
|
414
|
+
// Best practice additions
|
|
415
|
+
"jest/consistent-test-it": ["error", { fn: "it" }],
|
|
416
|
+
"jest/prefer-comparison-matcher": "error",
|
|
417
|
+
"jest/prefer-equality-matcher": "error",
|
|
418
|
+
"jest/prefer-hooks-on-top": "error",
|
|
419
|
+
"jest/prefer-spy-on": "error",
|
|
420
|
+
"jest/prefer-strict-equal": "warn",
|
|
421
|
+
"jest/prefer-mock-promise-shorthand": "error",
|
|
422
|
+
"jest/no-conditional-in-test": "warn",
|
|
423
|
+
"jest/no-duplicate-hooks": "error",
|
|
424
|
+
"jest/no-test-return-statement": "error",
|
|
425
|
+
"jest/require-to-throw-message": "warn"
|
|
375
426
|
}
|
|
376
427
|
}
|
|
377
428
|
]);
|
|
@@ -383,13 +434,22 @@ var json = (0, import_config6.defineConfig)([
|
|
|
383
434
|
{
|
|
384
435
|
files: ["**/*.json"],
|
|
385
436
|
extends: [import_eslint_plugin_json.default.configs.recommended]
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
files: ["**/tsconfig*.json", "**/.vscode/*.json"],
|
|
440
|
+
extends: [import_eslint_plugin_json.default.configs["recommended-with-comments"]]
|
|
386
441
|
}
|
|
387
442
|
]);
|
|
388
443
|
|
|
444
|
+
// packages/lint-suite/src/lib/prettier.ts
|
|
445
|
+
var import_eslint_config_prettier = __toESM(require("eslint-config-prettier"), 1);
|
|
446
|
+
var import_config7 = require("eslint/config");
|
|
447
|
+
var prettier = (0, import_config7.defineConfig)([import_eslint_config_prettier.default]);
|
|
448
|
+
|
|
389
449
|
// packages/lint-suite/src/lib/rxjs.ts
|
|
390
450
|
var import_eslint_plugin_rxjs = __toESM(require("@smarttools/eslint-plugin-rxjs"), 1);
|
|
391
|
-
var
|
|
392
|
-
var rxjs = (0,
|
|
451
|
+
var import_config8 = require("eslint/config");
|
|
452
|
+
var rxjs = (0, import_config8.defineConfig)([
|
|
393
453
|
{
|
|
394
454
|
files: [
|
|
395
455
|
"**/*.js",
|
|
@@ -445,25 +505,38 @@ var rxjs = (0, import_config7.defineConfig)([
|
|
|
445
505
|
"rxjs/no-unsafe-first": "error",
|
|
446
506
|
"rxjs/no-topromise": "error",
|
|
447
507
|
"rxjs/throw-error": "error",
|
|
448
|
-
"rxjs/no-async-subscribe": "off"
|
|
508
|
+
"rxjs/no-async-subscribe": "off",
|
|
509
|
+
"rxjs/no-exposed-subjects": "error",
|
|
510
|
+
// Enforce subject encapsulation
|
|
511
|
+
"rxjs/no-cyclic-action": "error",
|
|
512
|
+
// Prevent infinite loops in NgRx effects
|
|
513
|
+
"rxjs/no-subscribe-handlers": "warn"
|
|
514
|
+
// Prefer observer objects (complements prefer-observer)
|
|
449
515
|
}
|
|
450
516
|
},
|
|
451
517
|
{
|
|
452
518
|
files: ["**/*.spec.ts", "**/*.test.ts", "**/*.spec.js", "**/*.test.js"],
|
|
453
519
|
rules: {
|
|
454
|
-
"rxjs/no-ignored-subscription": "off"
|
|
520
|
+
"rxjs/no-ignored-subscription": "off",
|
|
521
|
+
"rxjs/no-subscribe-handlers": "off"
|
|
455
522
|
}
|
|
456
523
|
}
|
|
457
524
|
]);
|
|
458
525
|
|
|
459
526
|
// packages/lint-suite/src/lib/storybook.ts
|
|
460
527
|
var import_eslint_plugin_storybook = __toESM(require("eslint-plugin-storybook"), 1);
|
|
461
|
-
var
|
|
462
|
-
var storybook = (0,
|
|
528
|
+
var import_config9 = require("eslint/config");
|
|
529
|
+
var storybook = (0, import_config9.defineConfig)([
|
|
463
530
|
{
|
|
464
531
|
ignores: ["!.storybook"],
|
|
465
532
|
files: ["**/*.stories.ts"],
|
|
466
|
-
extends: [import_eslint_plugin_storybook.default.configs["flat/recommended"]]
|
|
533
|
+
extends: [import_eslint_plugin_storybook.default.configs["flat/recommended"]],
|
|
534
|
+
rules: {
|
|
535
|
+
"storybook/csf-component": "warn",
|
|
536
|
+
// Ensure component property is set
|
|
537
|
+
"storybook/no-stories-of": "error"
|
|
538
|
+
// Prevent deprecated storiesOf API
|
|
539
|
+
}
|
|
467
540
|
}
|
|
468
541
|
]);
|
|
469
542
|
|
|
@@ -471,7 +544,7 @@ var storybook = (0, import_config8.defineConfig)([
|
|
|
471
544
|
var import_eslint_plugin4 = require("@nx/eslint-plugin");
|
|
472
545
|
var import_eslint_import_resolver_typescript = require("eslint-import-resolver-typescript");
|
|
473
546
|
var import_eslint_plugin_import_x2 = __toESM(require("eslint-plugin-import-x"), 1);
|
|
474
|
-
var
|
|
547
|
+
var import_config10 = require("eslint/config");
|
|
475
548
|
|
|
476
549
|
// packages/lint-suite/src/lib/rules/explicit-accessibility.ts
|
|
477
550
|
var import_utils = require("@typescript-eslint/utils");
|
|
@@ -612,7 +685,7 @@ var localTypescriptRules = {
|
|
|
612
685
|
"explicit-accessibility": explicit_accessibility_default
|
|
613
686
|
}
|
|
614
687
|
};
|
|
615
|
-
var typescript = (0,
|
|
688
|
+
var typescript = (0, import_config10.defineConfig)([
|
|
616
689
|
// NOTE: Checks for 'prettier' and 'eslint-plugin-prettier'
|
|
617
690
|
{
|
|
618
691
|
files: ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"],
|
|
@@ -638,6 +711,13 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
638
711
|
"@typescript-eslint/no-unsafe-member-access": "error",
|
|
639
712
|
"@typescript-eslint/no-unsafe-return": "error",
|
|
640
713
|
"@typescript-eslint/no-unsafe-argument": "error",
|
|
714
|
+
// New v8 type-safety rules (replacements for deprecated ban-types)
|
|
715
|
+
"@typescript-eslint/no-empty-object-type": "error",
|
|
716
|
+
// Bans confusing {} type
|
|
717
|
+
"@typescript-eslint/no-unsafe-function-type": "error",
|
|
718
|
+
// Bans Function type
|
|
719
|
+
"@typescript-eslint/no-wrapper-object-types": "error",
|
|
720
|
+
// Bans Number, String, Boolean wrappers
|
|
641
721
|
// B. Explicit Annotations (partially covered, explicit module boundaries is key)
|
|
642
722
|
"@typescript-eslint/explicit-module-boundary-types": "error",
|
|
643
723
|
// Consider enabling if maximum explicitness is desired, even if verbose:
|
|
@@ -658,8 +738,14 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
658
738
|
// E. Best Practices & Potential Errors (Some covered by presets, fine-tuning here)
|
|
659
739
|
"@typescript-eslint/no-inferrable-types": "warn",
|
|
660
740
|
// Keep as warn or disable if inference is preferred
|
|
661
|
-
"@typescript-eslint/no-
|
|
662
|
-
// Use ES modules
|
|
741
|
+
"@typescript-eslint/no-require-imports": "error",
|
|
742
|
+
// Use ES modules (replaces deprecated no-var-requires)
|
|
743
|
+
"@typescript-eslint/only-throw-error": "error",
|
|
744
|
+
// Replaces deprecated no-throw-literal
|
|
745
|
+
"@typescript-eslint/no-array-delete": "error",
|
|
746
|
+
// Prevents delete arr[0]
|
|
747
|
+
"@typescript-eslint/return-await": ["error", "in-try-catch"],
|
|
748
|
+
// Better stack traces in try/catch
|
|
663
749
|
"@typescript-eslint/require-await": "error",
|
|
664
750
|
"@typescript-eslint/restrict-template-expressions": [
|
|
665
751
|
"error",
|
|
@@ -679,6 +765,32 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
679
765
|
"@typescript-eslint/no-useless-constructor": "error",
|
|
680
766
|
"@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
|
|
681
767
|
// Prefer dot notation where possible
|
|
768
|
+
// Strict type-checked rules
|
|
769
|
+
"@typescript-eslint/no-unnecessary-condition": "error",
|
|
770
|
+
// Catches always-true/false conditions
|
|
771
|
+
"@typescript-eslint/no-confusing-void-expression": "error",
|
|
772
|
+
// Prevent confusing void usage
|
|
773
|
+
"@typescript-eslint/no-dynamic-delete": "error",
|
|
774
|
+
// Use Map instead of delete obj[key]
|
|
775
|
+
"@typescript-eslint/no-extraneous-class": ["error", { allowWithDecorator: true }],
|
|
776
|
+
// Allow Angular classes
|
|
777
|
+
"@typescript-eslint/no-invalid-void-type": "error",
|
|
778
|
+
// Restrict void to return types
|
|
779
|
+
"@typescript-eslint/unified-signatures": "error",
|
|
780
|
+
// Merge overloads where possible
|
|
781
|
+
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
|
|
782
|
+
// Forbids foo! ?? bar
|
|
783
|
+
// Stylistic type-checked rules
|
|
784
|
+
"@typescript-eslint/prefer-find": "error",
|
|
785
|
+
// Use find() instead of filter()[0]
|
|
786
|
+
"@typescript-eslint/prefer-for-of": "error",
|
|
787
|
+
// Modern iteration
|
|
788
|
+
"@typescript-eslint/prefer-includes": "error",
|
|
789
|
+
// indexOf() → includes()
|
|
790
|
+
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
|
791
|
+
// Modern string methods
|
|
792
|
+
"@typescript-eslint/prefer-regexp-exec": "error",
|
|
793
|
+
// Better regex performance
|
|
682
794
|
// F. Consistency & Style (Some covered by stylistic-type-checked)
|
|
683
795
|
"@typescript-eslint/consistent-type-assertions": [
|
|
684
796
|
"error",
|
|
@@ -780,10 +892,18 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
780
892
|
"import-x/no-unresolved": "error",
|
|
781
893
|
"import-x/no-duplicates": "error",
|
|
782
894
|
"import-x/prefer-default-export": "off",
|
|
783
|
-
"import-x/no-useless-path-segments": "error",
|
|
895
|
+
"import-x/no-useless-path-segments": ["error", { noUselessIndex: true }],
|
|
784
896
|
"import-x/newline-after-import": "error",
|
|
785
897
|
"import-x/first": "error",
|
|
786
|
-
"import-x/no-mutable-exports": "error"
|
|
898
|
+
"import-x/no-mutable-exports": "error",
|
|
899
|
+
"import-x/no-self-import": "error",
|
|
900
|
+
// Prevents modules importing themselves
|
|
901
|
+
"import-x/no-cycle": ["error", { maxDepth: 2, ignoreExternal: true }],
|
|
902
|
+
// Prevents circular dependencies
|
|
903
|
+
"import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
|
904
|
+
// Consistent type imports
|
|
905
|
+
"import-x/no-anonymous-default-export": "error"
|
|
906
|
+
// Improve code searchability
|
|
787
907
|
},
|
|
788
908
|
settings: {
|
|
789
909
|
"import-x/resolver-next": [
|
|
@@ -808,7 +928,8 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
808
928
|
{
|
|
809
929
|
files: ["**/*.action.ts"],
|
|
810
930
|
rules: {
|
|
811
|
-
"@typescript-eslint/no-namespace": "off"
|
|
931
|
+
"@typescript-eslint/no-namespace": "off",
|
|
932
|
+
"@typescript-eslint/no-extraneous-class": "off"
|
|
812
933
|
}
|
|
813
934
|
},
|
|
814
935
|
{
|
|
@@ -837,38 +958,62 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
837
958
|
|
|
838
959
|
// packages/lint-suite/src/lib/vitest.ts
|
|
839
960
|
var import_eslint_plugin5 = __toESM(require("@vitest/eslint-plugin"), 1);
|
|
840
|
-
var
|
|
961
|
+
var import_config11 = require("eslint/config");
|
|
841
962
|
var vitestPlugin = {
|
|
842
963
|
vitest: import_eslint_plugin5.default
|
|
843
964
|
};
|
|
844
|
-
var vitest = (0,
|
|
965
|
+
var vitest = (0, import_config11.defineConfig)([
|
|
845
966
|
{
|
|
846
967
|
files: ["**/*.spec.ts", "**/*.spec.js", "**/*.test.ts", "**/*.test.js"],
|
|
847
968
|
plugins: vitestPlugin,
|
|
848
969
|
rules: {
|
|
849
970
|
...import_eslint_plugin5.default.configs.recommended.rules,
|
|
850
|
-
"vitest/max-nested-describe": ["error", { max: 3 }]
|
|
971
|
+
"vitest/max-nested-describe": ["error", { max: 3 }],
|
|
972
|
+
// Matcher improvements
|
|
973
|
+
"vitest/prefer-to-be": "error",
|
|
974
|
+
"vitest/prefer-to-contain": "error",
|
|
975
|
+
"vitest/prefer-to-have-length": "error",
|
|
976
|
+
"vitest/prefer-comparison-matcher": "error",
|
|
977
|
+
"vitest/prefer-strict-equal": "warn",
|
|
978
|
+
// Test quality
|
|
979
|
+
"vitest/prefer-spy-on": "error",
|
|
980
|
+
"vitest/prefer-hooks-on-top": "error",
|
|
981
|
+
"vitest/prefer-each": "warn",
|
|
982
|
+
"vitest/no-test-return-statement": "error",
|
|
983
|
+
"vitest/prefer-mock-promise-shorthand": "error"
|
|
851
984
|
}
|
|
852
985
|
}
|
|
853
986
|
]);
|
|
854
987
|
|
|
855
988
|
// packages/lint-suite/src/lib/playwright.ts
|
|
856
989
|
var import_eslint_plugin_playwright = __toESM(require("eslint-plugin-playwright"), 1);
|
|
857
|
-
var
|
|
858
|
-
var playwright = (0,
|
|
990
|
+
var import_config12 = require("eslint/config");
|
|
991
|
+
var playwright = (0, import_config12.defineConfig)([
|
|
859
992
|
{
|
|
860
993
|
...import_eslint_plugin_playwright.default.configs["flat/recommended"],
|
|
861
994
|
files: ["**/*.e2e.ts", "**/*.e2e.js"],
|
|
862
995
|
rules: {
|
|
863
|
-
...import_eslint_plugin_playwright.default.configs["flat/recommended"].rules
|
|
996
|
+
...import_eslint_plugin_playwright.default.configs["flat/recommended"].rules,
|
|
997
|
+
// Locator best practices
|
|
998
|
+
"playwright/prefer-locator": "error",
|
|
999
|
+
"playwright/prefer-native-locators": "error",
|
|
1000
|
+
"playwright/no-nth-methods": "warn",
|
|
1001
|
+
// Matcher improvements
|
|
1002
|
+
"playwright/prefer-to-be": "error",
|
|
1003
|
+
"playwright/prefer-to-have-count": "error",
|
|
1004
|
+
"playwright/prefer-to-have-length": "error",
|
|
1005
|
+
"playwright/prefer-comparison-matcher": "error",
|
|
1006
|
+
// Test structure
|
|
1007
|
+
"playwright/prefer-hooks-on-top": "error",
|
|
1008
|
+
"playwright/require-top-level-describe": "warn"
|
|
864
1009
|
}
|
|
865
1010
|
}
|
|
866
1011
|
]);
|
|
867
1012
|
|
|
868
1013
|
// packages/lint-suite/src/lib/boundaries.ts
|
|
869
1014
|
var import_eslint_plugin_boundaries = __toESM(require("eslint-plugin-boundaries"), 1);
|
|
870
|
-
var
|
|
871
|
-
var boundaries = (0,
|
|
1015
|
+
var import_config13 = require("eslint/config");
|
|
1016
|
+
var boundaries = (0, import_config13.defineConfig)([
|
|
872
1017
|
{
|
|
873
1018
|
files: [
|
|
874
1019
|
"**/*.js",
|
|
@@ -972,7 +1117,9 @@ var recommended = [
|
|
|
972
1117
|
...boundaries,
|
|
973
1118
|
...storybook,
|
|
974
1119
|
...vitest,
|
|
975
|
-
...playwright
|
|
1120
|
+
...playwright,
|
|
1121
|
+
...prettier
|
|
1122
|
+
// Must be last to disable formatting rules that conflict with Prettier
|
|
976
1123
|
];
|
|
977
1124
|
// Annotate the CommonJS export names for ESM import in node:
|
|
978
1125
|
0 && (module.exports = {
|
|
@@ -984,6 +1131,7 @@ var recommended = [
|
|
|
984
1131
|
jest,
|
|
985
1132
|
json,
|
|
986
1133
|
playwright,
|
|
1134
|
+
prettier,
|
|
987
1135
|
recommended,
|
|
988
1136
|
rxjs,
|
|
989
1137
|
storybook,
|