1- // @ts -check
2-
31import url from "node:url" ;
42
3+ // @ts -expect-error - this is a valid import
54import eslint from "@eslint/js" ;
5+ import gitignore from "eslint-config-flat-gitignore" ;
6+ // @ts -expect-error - this is a valid import
67import eslintCommentsPlugin from "eslint-plugin-eslint-comments" ;
8+ // @ts -expect-error - this is a valid import
79import eslintPluginPlugin from "eslint-plugin-eslint-plugin" ;
8- import gitignore from "eslint-config-flat-gitignore" ;
910import jsdocPlugin from "eslint-plugin-jsdoc" ;
11+ // @ts -expect-error - this is a valid import
1012import perfectionist from "eslint-plugin-perfectionist" ;
13+ // @ts -expect-error - this is a valid import
1114import perfectionistNatural from "eslint-plugin-perfectionist/configs/recommended-natural" ;
1215import simpleImportSortPlugin from "eslint-plugin-simple-import-sort" ;
16+ // @ts -expect-error - this is a valid import
1317import unicornPlugin from "eslint-plugin-unicorn" ;
14- import tseslint from "typescript-eslint" ;
1518import vitest from "eslint-plugin-vitest" ;
19+ import tseslint from "typescript-eslint" ;
1620
21+ type FlatConfig = Parameters < typeof tseslint . config > [ number ] ;
1722const dirname = url . fileURLToPath ( new URL ( "." , import . meta. url ) ) ;
18-
19- export default tseslint . config (
23+ const config = [
2024 // register all of the plugins up-front
2125 {
2226 // note - intentionally uses computed syntax to make it easy to sort the keys
2327 plugins : {
2428 [ "@typescript-eslint" ] : tseslint . plugin ,
25- [ "eslint-plugin" ] : eslintPluginPlugin ,
2629 [ "eslint-comments" ] : eslintCommentsPlugin ,
30+ [ "eslint-plugin" ] : eslintPluginPlugin ,
2731 [ "jsdoc" ] : jsdocPlugin ,
28- [ "simple-import-sort" ] : simpleImportSortPlugin ,
2932 [ "perfectionist" ] : perfectionist ,
33+ [ "simple-import-sort" ] : simpleImportSortPlugin ,
3034 [ "unicorn" ] : unicornPlugin ,
3135 } ,
3236 } ,
3337 // extends ...
3438 eslint . configs . recommended ,
3539 ...tseslint . configs . strictTypeChecked ,
36- // @ts -ignore
3740 perfectionistNatural ,
3841 jsdocPlugin . configs [ "flat/recommended-typescript-error" ] ,
3942 // base config
@@ -51,30 +54,30 @@ export default tseslint.config(
5154 } ,
5255 } ,
5356 rules : {
54- "@typescript-eslint/no-confusing-void-expression" : "off" ,
55- "@typescript-eslint/ban-types" : "off" ,
5657 "@typescript-eslint/ban-ts-comment" : [
5758 "error" ,
5859 {
60+ minimumDescriptionLength : 5 ,
61+ "ts-check" : false ,
5962 "ts-expect-error" : "allow-with-description" ,
6063 "ts-ignore" : true ,
6164 "ts-nocheck" : true ,
62- "ts-check" : false ,
63- minimumDescriptionLength : 5 ,
6465 } ,
6566 ] ,
67+ "@typescript-eslint/ban-types" : "off" ,
6668 "@typescript-eslint/consistent-type-imports" : [ "error" , {
67- prefer : "type-imports" ,
6869 disallowTypeAnnotations : true ,
70+ prefer : "type-imports" ,
6971 } ] ,
7072 "@typescript-eslint/explicit-function-return-type" : "off" ,
73+ "@typescript-eslint/no-confusing-void-expression" : "off" ,
7174 "@typescript-eslint/no-explicit-any" : "error" ,
7275 "@typescript-eslint/no-unused-vars" : [
7376 "error" ,
7477 {
78+ argsIgnorePattern : "^_" ,
7579 caughtErrors : "all" ,
7680 varsIgnorePattern : "^_" ,
77- argsIgnorePattern : "^_" ,
7881 } ,
7982 ] ,
8083 "@typescript-eslint/prefer-nullish-coalescing" : [
@@ -85,18 +88,43 @@ export default tseslint.config(
8588 } ,
8689 ] ,
8790 "array-callback-return" : "off" ,
91+ curly : "off" ,
92+ eqeqeq : [ "error" , "always" ] ,
93+ "eslint-comments/disable-enable-pair" : [ "error" , { allowWholeFile : true } ] ,
94+ "eslint-comments/no-aggregating-enable" : "error" ,
95+ "eslint-comments/no-duplicate-disable" : "error" ,
96+ "eslint-comments/no-unlimited-disable" : "error" ,
97+ "eslint-comments/no-unused-disable" : "error" ,
98+ "eslint-comments/no-unused-enable" : "error" ,
99+ "eslint-comments/no-use" : [
100+ "error" ,
101+ {
102+ allow : [
103+ "eslint-disable" ,
104+ "eslint-disable-line" ,
105+ "eslint-disable-next-line" ,
106+ "eslint-enable" ,
107+ "global" ,
108+ ] ,
109+ } ,
110+ ] ,
111+ "eslint-plugin/require-meta-docs-url" : "off" ,
112+ "jsdoc/check-param-names" : "off" ,
113+ "jsdoc/check-tag-names" : "off" ,
114+ "jsdoc/informative-docs" : "warn" ,
115+ "jsdoc/require-jsdoc" : "off" ,
116+ "jsdoc/require-param" : "off" ,
117+ "jsdoc/require-param-description" : "off" ,
118+ "jsdoc/require-returns" : "off" ,
119+ "jsdoc/require-yields" : "off" ,
120+ "jsdoc/tag-lines" : "off" ,
88121 "logical-assignment-operators" : "error" ,
89122 "max-depth" : [ "warn" , 3 ] ,
90123 "no-console" : "error" ,
91124 "no-else-return" : "error" ,
92125 "no-fallthrough" : [ "error" , { commentPattern : ".*intentional fallthrough.*" } ] ,
93126 "no-mixed-operators" : "error" ,
94127 "no-process-exit" : "error" ,
95- "no-undef" : "off" ,
96- "one-var" : [ "error" , "never" ] ,
97- "prefer-object-has-own" : "error" ,
98- curly : "off" ,
99- eqeqeq : [ "error" , "always" ] ,
100128 "no-restricted-syntax" : [
101129 "error" ,
102130 {
@@ -116,19 +144,16 @@ export default tseslint.config(
116144 selector : 'ImportDeclaration[source.value="."]' ,
117145 } ,
118146 ] ,
119- "simple-import-sort/imports" : "warn" ,
120- "simple-import-sort/exports" : "warn" ,
121- "unicorn/template-indent" : "warn" ,
147+ "no-undef" : "off" ,
148+ "one-var" : [ "error" , "never" ] ,
122149 "perfectionist/sort-exports" : "off" ,
123150 "perfectionist/sort-imports" : "off" ,
124151 "perfectionist/sort-named-exports" : "off" ,
125152 "perfectionist/sort-named-imports" : "off" ,
126153 "perfectionist/sort-object-types" : [
127154 "warn" ,
128155 {
129- order : "asc" ,
130156 type : "natural" ,
131- groups : [ "id" , "type" , "meta" , "unknown" ] ,
132157 "custom-groups" : {
133158 id : [ "_" , "id" , "key" ] ,
134159 type : [ "type" , "kind" ] ,
@@ -139,15 +164,14 @@ export default tseslint.config(
139164 "description" ,
140165 ] ,
141166 } ,
167+ groups : [ "id" , "type" , "meta" , "unknown" ] ,
168+ order : "asc" ,
142169 } ,
143170 ] ,
144171 "perfectionist/sort-objects" : [
145172 "warn" ,
146173 {
147- order : "asc" ,
148174 type : "natural" ,
149- "partition-by-comment" : "Part:**" ,
150- groups : [ "id" , "type" , "meta" , "unknown" ] ,
151175 "custom-groups" : {
152176 id : [ "_" , "id" , "key" ] ,
153177 type : [ "type" , "kind" ] ,
@@ -158,50 +182,30 @@ export default tseslint.config(
158182 "description" ,
159183 ] ,
160184 } ,
185+ groups : [ "id" , "type" , "meta" , "unknown" ] ,
186+ order : "asc" ,
187+ "partition-by-comment" : "Part:**" ,
161188 } ,
162189 ] ,
163190 "perfectionist/sort-union-types" : [
164191 "warn" ,
165192 {
166- order : "asc" ,
167193 type : "natural" ,
194+ order : "asc" ,
168195 } ,
169196 ] ,
170- "eslint-plugin/require-meta-docs-url" : "off" ,
171- "eslint-comments/disable-enable-pair" : [ "error" , { allowWholeFile : true } ] ,
172- "eslint-comments/no-aggregating-enable" : "error" ,
173- "eslint-comments/no-duplicate-disable" : "error" ,
174- "eslint-comments/no-unlimited-disable" : "error" ,
175- "eslint-comments/no-unused-disable" : "error" ,
176- "eslint-comments/no-unused-enable" : "error" ,
177- "eslint-comments/no-use" : [
178- "error" ,
179- {
180- allow : [
181- "eslint-disable" ,
182- "eslint-disable-line" ,
183- "eslint-disable-next-line" ,
184- "eslint-enable" ,
185- "global" ,
186- ] ,
187- } ,
188- ] ,
189- "jsdoc/check-tag-names" : "off" ,
190- "jsdoc/check-param-names" : "off" ,
191- "jsdoc/require-jsdoc" : "off" ,
192- "jsdoc/require-param" : "off" ,
193- "jsdoc/require-param-description" : "off" ,
194- "jsdoc/require-returns" : "off" ,
195- "jsdoc/require-yields" : "off" ,
196- "jsdoc/tag-lines" : "off" ,
197- "jsdoc/informative-docs" : "warn" ,
197+ "prefer-object-has-own" : "error" ,
198+ "simple-import-sort/exports" : "warn" ,
199+ "simple-import-sort/imports" : "warn" ,
200+ "unicorn/template-indent" : "warn" ,
198201 } ,
199202 } ,
200203 {
201- files : [ "**/*.js" ] ,
202204 extends : [ tseslint . configs . disableTypeChecked ] ,
205+ files : [ "**/*.js" ] ,
203206 rules : {
204207 // turn off rules that don't apply to JS code
208+ "@typescript-eslint/no-var-requires" : "off" ,
205209 } ,
206210 } ,
207211 {
@@ -211,11 +215,15 @@ export default tseslint.config(
211215 "**/spec.{ts,tsx,cts,mts}" ,
212216 "**/test.{ts,tsx,cts,mts}" ,
213217 ] ,
218+ languageOptions : {
219+ globals : {
220+ ...vitest . environments . env . globals ,
221+ } ,
222+ } ,
214223 plugins : {
215224 vitest,
216225 } ,
217226 rules : {
218- // @ts -ignore
219227 ...vitest . configs . recommended . rules ,
220228 "@typescript-eslint/no-empty-function" : [ "error" , { allow : [ "arrowFunctions" ] } ] ,
221229 "@typescript-eslint/no-non-null-assertion" : "off" ,
@@ -224,9 +232,19 @@ export default tseslint.config(
224232 "@typescript-eslint/no-unsafe-member-access" : "off" ,
225233 "@typescript-eslint/no-unsafe-return" : "off" ,
226234 } ,
235+ } ,
236+ {
237+ extends : [ tseslint . configs . disableTypeChecked ] ,
238+ files : [
239+ "*.config.{ts,tsx,cts,mts}" ,
240+ ] ,
227241 languageOptions : {
228- globals : {
229- ...vitest . environments . env . globals ,
242+ parserOptions : {
243+ project : [
244+ "tsconfig.json" ,
245+ ] ,
246+ tsconfigRootDir : dirname ,
247+ warnOnUnsupportedTypeScriptVersion : false ,
230248 } ,
231249 } ,
232250 } ,
@@ -236,7 +254,8 @@ export default tseslint.config(
236254 "docs" ,
237255 "examples" ,
238256 "website" ,
239- "eslint.config.mjs" ,
240257 ] ,
241258 } ,
242- ) ;
259+ ] satisfies FlatConfig [ ] ;
260+
261+ export default tseslint . config ( ...config ) ;
0 commit comments