lint-suite 1.2.3 → 1.3.0
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 +174 -25
- package/index.cjs.map +4 -4
- package/index.d.ts +2 -1
- package/index.d.ts.map +1 -1
- package/index.js +173 -25
- 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/boundaries.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,7 +505,13 @@ 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
|
{
|
|
@@ -458,12 +524,18 @@ var rxjs = (0, import_config7.defineConfig)([
|
|
|
458
524
|
|
|
459
525
|
// packages/lint-suite/src/lib/storybook.ts
|
|
460
526
|
var import_eslint_plugin_storybook = __toESM(require("eslint-plugin-storybook"), 1);
|
|
461
|
-
var
|
|
462
|
-
var storybook = (0,
|
|
527
|
+
var import_config9 = require("eslint/config");
|
|
528
|
+
var storybook = (0, import_config9.defineConfig)([
|
|
463
529
|
{
|
|
464
530
|
ignores: ["!.storybook"],
|
|
465
531
|
files: ["**/*.stories.ts"],
|
|
466
|
-
extends: [import_eslint_plugin_storybook.default.configs["flat/recommended"]]
|
|
532
|
+
extends: [import_eslint_plugin_storybook.default.configs["flat/recommended"]],
|
|
533
|
+
rules: {
|
|
534
|
+
"storybook/csf-component": "warn",
|
|
535
|
+
// Ensure component property is set
|
|
536
|
+
"storybook/no-stories-of": "error"
|
|
537
|
+
// Prevent deprecated storiesOf API
|
|
538
|
+
}
|
|
467
539
|
}
|
|
468
540
|
]);
|
|
469
541
|
|
|
@@ -471,7 +543,7 @@ var storybook = (0, import_config8.defineConfig)([
|
|
|
471
543
|
var import_eslint_plugin4 = require("@nx/eslint-plugin");
|
|
472
544
|
var import_eslint_import_resolver_typescript = require("eslint-import-resolver-typescript");
|
|
473
545
|
var import_eslint_plugin_import_x2 = __toESM(require("eslint-plugin-import-x"), 1);
|
|
474
|
-
var
|
|
546
|
+
var import_config10 = require("eslint/config");
|
|
475
547
|
|
|
476
548
|
// packages/lint-suite/src/lib/rules/explicit-accessibility.ts
|
|
477
549
|
var import_utils = require("@typescript-eslint/utils");
|
|
@@ -612,7 +684,7 @@ var localTypescriptRules = {
|
|
|
612
684
|
"explicit-accessibility": explicit_accessibility_default
|
|
613
685
|
}
|
|
614
686
|
};
|
|
615
|
-
var typescript = (0,
|
|
687
|
+
var typescript = (0, import_config10.defineConfig)([
|
|
616
688
|
// NOTE: Checks for 'prettier' and 'eslint-plugin-prettier'
|
|
617
689
|
{
|
|
618
690
|
files: ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"],
|
|
@@ -638,6 +710,13 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
638
710
|
"@typescript-eslint/no-unsafe-member-access": "error",
|
|
639
711
|
"@typescript-eslint/no-unsafe-return": "error",
|
|
640
712
|
"@typescript-eslint/no-unsafe-argument": "error",
|
|
713
|
+
// New v8 type-safety rules (replacements for deprecated ban-types)
|
|
714
|
+
"@typescript-eslint/no-empty-object-type": "error",
|
|
715
|
+
// Bans confusing {} type
|
|
716
|
+
"@typescript-eslint/no-unsafe-function-type": "error",
|
|
717
|
+
// Bans Function type
|
|
718
|
+
"@typescript-eslint/no-wrapper-object-types": "error",
|
|
719
|
+
// Bans Number, String, Boolean wrappers
|
|
641
720
|
// B. Explicit Annotations (partially covered, explicit module boundaries is key)
|
|
642
721
|
"@typescript-eslint/explicit-module-boundary-types": "error",
|
|
643
722
|
// Consider enabling if maximum explicitness is desired, even if verbose:
|
|
@@ -658,8 +737,14 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
658
737
|
// E. Best Practices & Potential Errors (Some covered by presets, fine-tuning here)
|
|
659
738
|
"@typescript-eslint/no-inferrable-types": "warn",
|
|
660
739
|
// Keep as warn or disable if inference is preferred
|
|
661
|
-
"@typescript-eslint/no-
|
|
662
|
-
// Use ES modules
|
|
740
|
+
"@typescript-eslint/no-require-imports": "error",
|
|
741
|
+
// Use ES modules (replaces deprecated no-var-requires)
|
|
742
|
+
"@typescript-eslint/only-throw-error": "error",
|
|
743
|
+
// Replaces deprecated no-throw-literal
|
|
744
|
+
"@typescript-eslint/no-array-delete": "error",
|
|
745
|
+
// Prevents delete arr[0]
|
|
746
|
+
"@typescript-eslint/return-await": ["error", "in-try-catch"],
|
|
747
|
+
// Better stack traces in try/catch
|
|
663
748
|
"@typescript-eslint/require-await": "error",
|
|
664
749
|
"@typescript-eslint/restrict-template-expressions": [
|
|
665
750
|
"error",
|
|
@@ -679,6 +764,32 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
679
764
|
"@typescript-eslint/no-useless-constructor": "error",
|
|
680
765
|
"@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
|
|
681
766
|
// Prefer dot notation where possible
|
|
767
|
+
// Strict type-checked rules
|
|
768
|
+
"@typescript-eslint/no-unnecessary-condition": "error",
|
|
769
|
+
// Catches always-true/false conditions
|
|
770
|
+
"@typescript-eslint/no-confusing-void-expression": "error",
|
|
771
|
+
// Prevent confusing void usage
|
|
772
|
+
"@typescript-eslint/no-dynamic-delete": "error",
|
|
773
|
+
// Use Map instead of delete obj[key]
|
|
774
|
+
"@typescript-eslint/no-extraneous-class": ["error", { allowWithDecorator: true }],
|
|
775
|
+
// Allow Angular classes
|
|
776
|
+
"@typescript-eslint/no-invalid-void-type": "error",
|
|
777
|
+
// Restrict void to return types
|
|
778
|
+
"@typescript-eslint/unified-signatures": "error",
|
|
779
|
+
// Merge overloads where possible
|
|
780
|
+
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
|
|
781
|
+
// Forbids foo! ?? bar
|
|
782
|
+
// Stylistic type-checked rules
|
|
783
|
+
"@typescript-eslint/prefer-find": "error",
|
|
784
|
+
// Use find() instead of filter()[0]
|
|
785
|
+
"@typescript-eslint/prefer-for-of": "error",
|
|
786
|
+
// Modern iteration
|
|
787
|
+
"@typescript-eslint/prefer-includes": "error",
|
|
788
|
+
// indexOf() → includes()
|
|
789
|
+
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
|
790
|
+
// Modern string methods
|
|
791
|
+
"@typescript-eslint/prefer-regexp-exec": "error",
|
|
792
|
+
// Better regex performance
|
|
682
793
|
// F. Consistency & Style (Some covered by stylistic-type-checked)
|
|
683
794
|
"@typescript-eslint/consistent-type-assertions": [
|
|
684
795
|
"error",
|
|
@@ -780,10 +891,18 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
780
891
|
"import-x/no-unresolved": "error",
|
|
781
892
|
"import-x/no-duplicates": "error",
|
|
782
893
|
"import-x/prefer-default-export": "off",
|
|
783
|
-
"import-x/no-useless-path-segments": "error",
|
|
894
|
+
"import-x/no-useless-path-segments": ["error", { noUselessIndex: true }],
|
|
784
895
|
"import-x/newline-after-import": "error",
|
|
785
896
|
"import-x/first": "error",
|
|
786
|
-
"import-x/no-mutable-exports": "error"
|
|
897
|
+
"import-x/no-mutable-exports": "error",
|
|
898
|
+
"import-x/no-self-import": "error",
|
|
899
|
+
// Prevents modules importing themselves
|
|
900
|
+
"import-x/no-cycle": ["error", { maxDepth: 2, ignoreExternal: true }],
|
|
901
|
+
// Prevents circular dependencies
|
|
902
|
+
"import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
|
903
|
+
// Consistent type imports
|
|
904
|
+
"import-x/no-anonymous-default-export": "error"
|
|
905
|
+
// Improve code searchability
|
|
787
906
|
},
|
|
788
907
|
settings: {
|
|
789
908
|
"import-x/resolver-next": [
|
|
@@ -837,38 +956,63 @@ var typescript = (0, import_config9.defineConfig)([
|
|
|
837
956
|
|
|
838
957
|
// packages/lint-suite/src/lib/vitest.ts
|
|
839
958
|
var import_eslint_plugin5 = __toESM(require("@vitest/eslint-plugin"), 1);
|
|
840
|
-
var
|
|
959
|
+
var import_config11 = require("eslint/config");
|
|
841
960
|
var vitestPlugin = {
|
|
842
961
|
vitest: import_eslint_plugin5.default
|
|
843
962
|
};
|
|
844
|
-
var vitest = (0,
|
|
963
|
+
var vitest = (0, import_config11.defineConfig)([
|
|
845
964
|
{
|
|
846
965
|
files: ["**/*.spec.ts", "**/*.spec.js", "**/*.test.ts", "**/*.test.js"],
|
|
847
966
|
plugins: vitestPlugin,
|
|
848
967
|
rules: {
|
|
849
968
|
...import_eslint_plugin5.default.configs.recommended.rules,
|
|
850
|
-
"vitest/max-nested-describe": ["error", { max: 3 }]
|
|
969
|
+
"vitest/max-nested-describe": ["error", { max: 3 }],
|
|
970
|
+
// Matcher improvements
|
|
971
|
+
"vitest/prefer-to-be": "error",
|
|
972
|
+
"vitest/prefer-to-contain": "error",
|
|
973
|
+
"vitest/prefer-to-have-length": "error",
|
|
974
|
+
"vitest/prefer-comparison-matcher": "error",
|
|
975
|
+
"vitest/prefer-strict-equal": "warn",
|
|
976
|
+
// Test quality
|
|
977
|
+
"vitest/prefer-spy-on": "error",
|
|
978
|
+
"vitest/prefer-hooks-on-top": "error",
|
|
979
|
+
"vitest/prefer-each": "warn",
|
|
980
|
+
"vitest/no-conditional-in-test": "error",
|
|
981
|
+
"vitest/no-test-return-statement": "error",
|
|
982
|
+
"vitest/prefer-mock-promise-shorthand": "error"
|
|
851
983
|
}
|
|
852
984
|
}
|
|
853
985
|
]);
|
|
854
986
|
|
|
855
987
|
// packages/lint-suite/src/lib/playwright.ts
|
|
856
988
|
var import_eslint_plugin_playwright = __toESM(require("eslint-plugin-playwright"), 1);
|
|
857
|
-
var
|
|
858
|
-
var playwright = (0,
|
|
989
|
+
var import_config12 = require("eslint/config");
|
|
990
|
+
var playwright = (0, import_config12.defineConfig)([
|
|
859
991
|
{
|
|
860
992
|
...import_eslint_plugin_playwright.default.configs["flat/recommended"],
|
|
861
993
|
files: ["**/*.e2e.ts", "**/*.e2e.js"],
|
|
862
994
|
rules: {
|
|
863
|
-
...import_eslint_plugin_playwright.default.configs["flat/recommended"].rules
|
|
995
|
+
...import_eslint_plugin_playwright.default.configs["flat/recommended"].rules,
|
|
996
|
+
// Locator best practices
|
|
997
|
+
"playwright/prefer-locator": "error",
|
|
998
|
+
"playwright/prefer-native-locators": "error",
|
|
999
|
+
"playwright/no-nth-methods": "warn",
|
|
1000
|
+
// Matcher improvements
|
|
1001
|
+
"playwright/prefer-to-be": "error",
|
|
1002
|
+
"playwright/prefer-to-have-count": "error",
|
|
1003
|
+
"playwright/prefer-to-have-length": "error",
|
|
1004
|
+
"playwright/prefer-comparison-matcher": "error",
|
|
1005
|
+
// Test structure
|
|
1006
|
+
"playwright/prefer-hooks-on-top": "error",
|
|
1007
|
+
"playwright/require-top-level-describe": "warn"
|
|
864
1008
|
}
|
|
865
1009
|
}
|
|
866
1010
|
]);
|
|
867
1011
|
|
|
868
1012
|
// packages/lint-suite/src/lib/boundaries.ts
|
|
869
1013
|
var import_eslint_plugin_boundaries = __toESM(require("eslint-plugin-boundaries"), 1);
|
|
870
|
-
var
|
|
871
|
-
var boundaries = (0,
|
|
1014
|
+
var import_config13 = require("eslint/config");
|
|
1015
|
+
var boundaries = (0, import_config13.defineConfig)([
|
|
872
1016
|
{
|
|
873
1017
|
files: [
|
|
874
1018
|
"**/*.js",
|
|
@@ -916,6 +1060,8 @@ var boundaries = (0, import_config12.defineConfig)([
|
|
|
916
1060
|
},
|
|
917
1061
|
rules: {
|
|
918
1062
|
...import_eslint_plugin_boundaries.default.configs.recommended.rules,
|
|
1063
|
+
"boundaries/no-unknown": "warn",
|
|
1064
|
+
// Warn on imports from uncategorized files
|
|
919
1065
|
"boundaries/element-types": [
|
|
920
1066
|
"error",
|
|
921
1067
|
{
|
|
@@ -972,7 +1118,9 @@ var recommended = [
|
|
|
972
1118
|
...boundaries,
|
|
973
1119
|
...storybook,
|
|
974
1120
|
...vitest,
|
|
975
|
-
...playwright
|
|
1121
|
+
...playwright,
|
|
1122
|
+
...prettier
|
|
1123
|
+
// Must be last to disable formatting rules that conflict with Prettier
|
|
976
1124
|
];
|
|
977
1125
|
// Annotate the CommonJS export names for ESM import in node:
|
|
978
1126
|
0 && (module.exports = {
|
|
@@ -984,6 +1132,7 @@ var recommended = [
|
|
|
984
1132
|
jest,
|
|
985
1133
|
json,
|
|
986
1134
|
playwright,
|
|
1135
|
+
prettier,
|
|
987
1136
|
recommended,
|
|
988
1137
|
rxjs,
|
|
989
1138
|
storybook,
|