1
1
//@ts -check
2
2
3
- import url from 'node:url' ;
4
-
5
3
import { fixupConfigRules , fixupPluginRules } from '@eslint/compat' ;
6
4
import { FlatCompat } from '@eslint/eslintrc' ;
7
5
import eslint from '@eslint/js' ;
@@ -16,10 +14,10 @@ import perfectionistPlugin from 'eslint-plugin-perfectionist';
16
14
import reactPlugin from 'eslint-plugin-react' ;
17
15
import reactHooksPlugin from 'eslint-plugin-react-hooks' ;
18
16
import regexpPlugin from 'eslint-plugin-regexp' ;
19
- import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort' ;
20
17
import sonarjsPlugin from 'eslint-plugin-sonarjs' ;
21
18
import unicornPlugin from 'eslint-plugin-unicorn' ;
22
19
import globals from 'globals' ;
20
+ import url from 'node:url' ;
23
21
import tseslint from 'typescript-eslint' ;
24
22
25
23
const __dirname = url . fileURLToPath ( new URL ( '.' , import . meta. url ) ) ;
@@ -40,16 +38,23 @@ export default tseslint.config(
40
38
[ 'jest' ] :jestPlugin ,
41
39
[ 'jsdoc' ] :jsdocPlugin ,
42
40
[ 'jsx-a11y' ] :jsxA11yPlugin ,
41
+ [ 'perfectionist' ] :perfectionistPlugin ,
43
42
// https://github.com/facebook/react/issues/28313
44
43
[ 'react-hooks' ] :fixupPluginRules ( reactHooksPlugin ) ,
45
44
// https://github.com/jsx-eslint/eslint-plugin-react/issues/3699
46
45
[ 'react' ] :fixupPluginRules ( reactPlugin ) ,
47
46
[ 'regexp' ] :regexpPlugin ,
48
- [ 'simple-import-sort' ] :simpleImportSortPlugin ,
49
47
[ 'sonarjs' ] :sonarjsPlugin ,
50
48
[ 'unicorn' ] :unicornPlugin ,
51
49
} ,
52
50
/* eslint-enable no-useless-computed-key */
51
+ settings :{
52
+ perfectionist :{
53
+ order :'asc' ,
54
+ partitionByComment :true ,
55
+ type :'natural' ,
56
+ } ,
57
+ } ,
53
58
} ,
54
59
{
55
60
// config with just ignores is the replacement for `.eslintignore`
@@ -67,6 +72,7 @@ export default tseslint.config(
67
72
'.nx/*' ,
68
73
'.yarn/*' ,
69
74
// Files generated by TypeDoc
75
+ 'docs/packages/*/generated' ,
70
76
'packages/*/generated' ,
71
77
'docs/packages/*/generated' ,
72
78
// Files copied as part of the build
@@ -109,11 +115,11 @@ export default tseslint.config(
109
115
'@typescript-eslint/ban-ts-comment' :[
110
116
'error' ,
111
117
{
118
+ minimumDescriptionLength :5 ,
119
+ 'ts-check' :false ,
112
120
'ts-expect-error' :'allow-with-description' ,
113
121
'ts-ignore' :true ,
114
122
'ts-nocheck' :true ,
115
- 'ts-check' :false ,
116
- minimumDescriptionLength :5 ,
117
123
} ,
118
124
] ,
119
125
// TODO: enable it once we drop support for TS<5.0
@@ -124,62 +130,62 @@ export default tseslint.config(
124
130
] ,
125
131
'@typescript-eslint/consistent-type-imports' :[
126
132
'error' ,
127
- { prefer :'type-imports' , disallowTypeAnnotations : true } ,
133
+ { disallowTypeAnnotations : true , prefer :'type-imports' } ,
128
134
] ,
129
135
'@typescript-eslint/explicit-module-boundary-types' :'error' ,
130
136
'@typescript-eslint/no-explicit-any' :'error' ,
131
- 'no-constant-condition' :'off' ,
137
+ '@typescript-eslint/no-require-imports' :[
138
+ 'error' ,
139
+ {
140
+ allow :[ '/package\\.json$' ] ,
141
+ } ,
142
+ ] ,
132
143
'@typescript-eslint/no-unnecessary-condition' :[
133
144
'error' ,
134
145
{ allowConstantLoopConditions :true , checkTypePredicates :true } ,
135
146
] ,
136
147
'@typescript-eslint/no-unnecessary-type-parameters' :'error' ,
137
148
'@typescript-eslint/no-unused-expressions' :'error' ,
149
+ '@typescript-eslint/no-unused-vars' :[
150
+ 'error' ,
151
+ {
152
+ argsIgnorePattern :'^_' ,
153
+ caughtErrors :'all' ,
154
+ varsIgnorePattern :'^_' ,
155
+ } ,
156
+ ] ,
138
157
'@typescript-eslint/no-var-requires' :'off' ,
139
158
'@typescript-eslint/prefer-literal-enum-member' :[
140
159
'error' ,
141
160
{
142
161
allowBitwiseExpressions :true ,
143
162
} ,
144
163
] ,
164
+ '@typescript-eslint/prefer-nullish-coalescing' :[
165
+ 'error' ,
166
+ {
167
+ ignoreConditionalTests :true ,
168
+ ignorePrimitives :true ,
169
+ } ,
170
+ ] ,
145
171
'@typescript-eslint/prefer-string-starts-ends-with' :[
146
172
'error' ,
147
173
{
148
174
allowSingleElementEquality :'always' ,
149
175
} ,
150
176
] ,
151
- '@typescript-eslint/unbound-method' :'off' ,
152
177
'@typescript-eslint/restrict-template-expressions' :[
153
178
'error' ,
154
179
{
155
- allowNumber :true ,
156
- allowBoolean :true ,
157
180
allowAny :true ,
181
+ allowBoolean :true ,
158
182
allowNullish :true ,
183
+ allowNumber :true ,
159
184
allowRegExp :true ,
160
185
} ,
161
186
] ,
162
- '@typescript-eslint/no-unused-vars' :[
163
- 'error' ,
164
- {
165
- caughtErrors :'all' ,
166
- varsIgnorePattern :'^_' ,
167
- argsIgnorePattern :'^_' ,
168
- } ,
169
- ] ,
170
- '@typescript-eslint/prefer-nullish-coalescing' :[
171
- 'error' ,
172
- {
173
- ignoreConditionalTests :true ,
174
- ignorePrimitives :true ,
175
- } ,
176
- ] ,
177
- '@typescript-eslint/no-require-imports' :[
178
- 'error' ,
179
- {
180
- allow :[ '/package\\.json$' ] ,
181
- } ,
182
- ] ,
187
+ '@typescript-eslint/unbound-method' :'off' ,
188
+ 'no-constant-condition' :'off' ,
183
189
184
190
//
185
191
// Internal repo rules
@@ -204,16 +210,16 @@ export default tseslint.config(
204
210
} ,
205
211
] ,
206
212
'logical-assignment-operators' :'error' ,
207
- 'no-else-return' :'error' ,
208
- 'no-mixed-operators' :'error' ,
209
213
'no-console' :'error' ,
210
- 'no-process-exit ' :'error' ,
214
+ 'no-else-return ' :'error' ,
211
215
'no-fallthrough' :[
212
216
'error' ,
213
217
{ commentPattern :'.*intentional fallthrough.*' } ,
214
218
] ,
215
219
'no-implicit-coercion' :[ 'error' , { boolean :false } ] ,
216
220
'no-lonely-if' :'error' ,
221
+ 'no-mixed-operators' :'error' ,
222
+ 'no-process-exit' :'error' ,
217
223
'no-unreachable-loop' :'error' ,
218
224
'no-useless-call' :'error' ,
219
225
'no-useless-computed-key' :'error' ,
@@ -288,8 +294,8 @@ export default tseslint.config(
288
294
'error' ,
289
295
{
290
296
devDependencies :true ,
291
- peerDependencies :true ,
292
297
optionalDependencies :false ,
298
+ peerDependencies :true ,
293
299
} ,
294
300
] ,
295
301
// Forbid mutable exports
@@ -304,7 +310,7 @@ export default tseslint.config(
304
310
'import/prefer-default-export' :'off' , // we want everything to be named
305
311
306
312
// enforce a sort order across the codebase
307
- 'simple-import-sort/ imports' :'error' ,
313
+ 'perfectionist/sort- imports' :'error' ,
308
314
309
315
//
310
316
// eslint-plugin-jsdoc
@@ -339,8 +345,8 @@ export default tseslint.config(
339
345
340
346
'unicorn/no-length-as-slice-end' :'error' ,
341
347
'unicorn/no-lonely-if' :'error' ,
342
- 'unicorn/no-typeof-undefined' :'error' ,
343
348
'unicorn/no-single-promise-in-promise-methods' :'error' ,
349
+ 'unicorn/no-typeof-undefined' :'error' ,
344
350
'unicorn/no-useless-spread' :'error' ,
345
351
'unicorn/prefer-array-some' :'error' ,
346
352
'unicorn/prefer-export-from' :'error' ,
@@ -352,8 +358,8 @@ export default tseslint.config(
352
358
} ,
353
359
} ,
354
360
{
355
- files :[ '**/*.js' ] ,
356
361
extends :[ tseslint . configs . disableTypeChecked ] ,
362
+ files :[ '**/*.js' ] ,
357
363
rules :{
358
364
// turn off other type-aware rules
359
365
'@typescript-eslint/internal/no-poorly-typed-ts-props' :'off' ,
@@ -395,20 +401,20 @@ export default tseslint.config(
395
401
'@typescript-eslint/no-unsafe-call' :'off' ,
396
402
'@typescript-eslint/no-unsafe-member-access' :'off' ,
397
403
'@typescript-eslint/no-unsafe-return' :'off' ,
404
+ 'jest/no-alias-methods' :'error' ,
405
+ 'jest/no-deprecated-functions' :'error' ,
398
406
'jest/no-disabled-tests' :'error' ,
407
+ 'jest/no-done-callback' :'error' ,
399
408
'jest/no-focused-tests' :'error' ,
400
- 'jest/no-alias-methods' :'error' ,
401
409
'jest/no-identical-title' :'error' ,
402
410
'jest/no-jasmine-globals' :'error' ,
403
411
'jest/no-test-prefixes' :'error' ,
404
- 'jest/no-done-callback' :'error' ,
405
412
'jest/no-test-return-statement' :'error' ,
413
+ 'jest/prefer-spy-on' :'error' ,
406
414
'jest/prefer-to-be' :'error' ,
407
415
'jest/prefer-to-contain' :'error' ,
408
416
'jest/prefer-to-have-length' :'error' ,
409
- 'jest/prefer-spy-on' :'error' ,
410
417
'jest/valid-expect' :'error' ,
411
- 'jest/no-deprecated-functions' :'error' ,
412
418
} ,
413
419
} ,
414
420
// plugin rule tests
@@ -451,16 +457,16 @@ export default tseslint.config(
451
457
//
452
458
453
459
{
460
+ extends :[ ...compat . config ( eslintPluginPlugin . configs . recommended ) ] ,
454
461
files :[
455
462
'packages/eslint-plugin-internal/**/*.{ts,tsx,cts,mts}' ,
456
463
'packages/eslint-plugin-tslint/**/*.{ts,tsx,cts,mts}' ,
457
464
'packages/eslint-plugin/**/*.{ts,tsx,cts,mts}' ,
458
465
] ,
466
+
459
467
rules :{
460
468
'@typescript-eslint/internal/no-typescript-estree-import' :'error' ,
461
469
} ,
462
-
463
- extends :[ ...compat . config ( eslintPluginPlugin . configs . recommended ) ] ,
464
470
} ,
465
471
{
466
472
files :[
@@ -491,10 +497,10 @@ export default tseslint.config(
491
497
'no-restricted-syntax' :[
492
498
'error' ,
493
499
{
494
- selector :
495
- 'ExportDefaultDeclaration Property[key.name="create"] MemberExpression[object.name="context"][property.name="options"]' ,
496
500
message :
497
501
"Retrieve options from create's second parameter so that defaultOptions are applied." ,
502
+ selector :
503
+ 'ExportDefaultDeclaration Property[key.name="create"] MemberExpression[object.name="context"][property.name="options"]' ,
498
504
} ,
499
505
] ,
500
506
} ,
@@ -503,8 +509,8 @@ export default tseslint.config(
503
509
files :[ 'packages/eslint-plugin/src/rules/index.ts' ] ,
504
510
rules :{
505
511
// enforce alphabetical ordering
506
- 'sort-keys' :'error' ,
507
512
'import/order' :[ 'error' , { alphabetize :{ order :'asc' } } ] ,
513
+ 'sort-keys' :'error' ,
508
514
} ,
509
515
} ,
510
516
@@ -543,9 +549,9 @@ export default tseslint.config(
543
549
'no-restricted-imports' :[
544
550
'error' ,
545
551
{
546
- name :'@typescript-eslint/typescript-estree' ,
547
552
message :
548
553
'To prevent nx build errors, all `typescript-estree` imports should be done via `packages/ast-spec/tests/util/parsers/typescript-estree-import.ts`.' ,
554
+ name :'@typescript-eslint/typescript-estree' ,
549
555
} ,
550
556
] ,
551
557
} ,
@@ -556,19 +562,19 @@ export default tseslint.config(
556
562
//
557
563
558
564
{
559
- files :[ 'packages/website/**/*.{ts,tsx,mts,cts,js,jsx}' ] ,
560
565
extends :[
561
566
...compat . config ( jsxA11yPlugin . configs . recommended ) ,
562
567
...fixupConfigRules ( compat . config ( reactPlugin . configs . recommended ) ) ,
563
568
...fixupConfigRules ( compat . config ( reactHooksPlugin . configs . recommended ) ) ,
564
569
] ,
570
+ files :[ 'packages/website/**/*.{ts,tsx,mts,cts,js,jsx}' ] ,
565
571
rules :{
566
572
'@typescript-eslint/internal/prefer-ast-types-enum' :'off' ,
567
573
'import/no-default-export' :'off' ,
568
574
'react/jsx-no-target-blank' :'off' ,
569
575
'react/no-unescaped-entities' :'off' ,
570
- 'react-hooks/exhaustive-deps' :'warn' , // TODO: enable it later
571
576
'react/prop-types' :'off' ,
577
+ 'react-hooks/exhaustive-deps' :'warn' , // TODO: enable it later
572
578
} ,
573
579
settings :{
574
580
react :{
@@ -595,28 +601,12 @@ export default tseslint.config(
595
601
} ,
596
602
} ,
597
603
{
598
- extends :[ perfectionistPlugin . configs [ 'recommended-alphabetical' ] ] ,
604
+ files :[ '**/*' ] ,
599
605
ignores :[
600
606
'packages/eslint-plugin/src/configs/*' ,
601
607
'packages/scope-manager/src/configs/*' ,
602
608
'packages/typescript-eslint/src/configs/*' ,
603
609
] ,
604
- files :[
605
- 'packages/ast-spec/{src,tests,typings}/**/*.ts' ,
606
- 'packages/eslint-plugin/{src,tests,tools,typings}/**/*.ts' ,
607
- 'packages/integration-tests/{tests,tools,typing}/**/*.ts' ,
608
- 'packages/parser/{src,tests}/**/*.ts' ,
609
- 'packages/rule-schema-to-typescript-types/src/**/*.ts' ,
610
- 'packages/rule-tester/{src,tests,typings}/**/*.ts' ,
611
- 'packages/scope-manager/{src,tests}/**/*.ts' ,
612
- 'packages/type-utils/{src,tests,typings}/**/*.ts' ,
613
- 'packages/types/{src,tools}/**/*.ts' ,
614
- 'packages/typescript-eslint/{src,tests}/**/*.ts' ,
615
- 'packages/typescript-estree/{src,tests,typings}/**/*.ts' ,
616
- 'packages/utils/src/**/*.ts' ,
617
- 'packages/visitor-keys/src/**/*.ts' ,
618
- 'packages/website*/src/**/*.ts' ,
619
- ] ,
620
610
rules :{
621
611
'@typescript-eslint/sort-type-constituents' :'off' ,
622
612
'perfectionist/sort-classes' :'error' ,
@@ -629,14 +619,6 @@ export default tseslint.config(
629
619
type :'natural' ,
630
620
} ,
631
621
] ,
632
- 'simple-import-sort/imports' :'off' ,
633
- } ,
634
- settings :{
635
- perfectionist :{
636
- partitionByComment :true ,
637
- order :'asc' ,
638
- type :'natural' ,
639
- } ,
640
622
} ,
641
623
} ,
642
624
{
@@ -654,16 +636,19 @@ export default tseslint.config(
654
636
} ,
655
637
} ,
656
638
{
657
- files :[ 'packages/eslint-plugin/src/rules/*.ts' ] ,
639
+ files :[
640
+ 'packages/eslint-plugin/src/rules/*.ts' ,
641
+ 'packages/eslint-plugin-internal/src/rules/*.ts' ,
642
+ ] ,
658
643
rules :{
659
644
'perfectionist/sort-objects' :[
660
645
'error' ,
661
646
{
662
647
customGroups :{
663
648
first :[ 'loc' , 'name' , 'node' , 'type' ] ,
649
+ fourth :[ 'fix' ] ,
664
650
second :[ 'meta' , 'messageId' , 'start' ] ,
665
651
third :[ 'defaultOptions' , 'data' , 'end' ] ,
666
- fourth :[ 'fix' ] ,
667
652
} ,
668
653
groups :[ 'first' , 'second' , 'third' , 'fourth' , 'unknown' ] ,
669
654
} ,