@foray1010/eslint-config 14.0.1 → 15.0.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/CHANGELOG.md +17 -0
- package/README.md +18 -20
- package/bases/base.mjs +86 -79
- package/bases/browser.mjs +11 -23
- package/bases/ignores.mjs +11 -14
- package/bases/node.mjs +8 -10
- package/bases/prettier.mjs +4 -5
- package/bases/react.mjs +10 -18
- package/index.mjs +19 -23
- package/package.json +3 -3
- package/utils/applyConfig.mjs +0 -72
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [15.0.1](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@15.0.0...@foray1010/eslint-config@15.0.1) (2025-03-13)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **eslint-config:** fix types ([28e3bfa](https://github.com/foray1010/common-presets/commit/28e3bfabce71cd1d80b0186f1ac7f3158a049d33))
|
|
11
|
+
|
|
12
|
+
## [15.0.0](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@14.0.1...@foray1010/eslint-config@15.0.0) (2025-03-13)
|
|
13
|
+
|
|
14
|
+
### ⚠ BREAKING CHANGES
|
|
15
|
+
|
|
16
|
+
- drop applyConfig utils
|
|
17
|
+
- require eslint ^9.22.0
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- migrate to eslint defineConfig utils ([faf0aa7](https://github.com/foray1010/common-presets/commit/faf0aa74048b2536e188a45b8371ebe416dcb851))
|
|
22
|
+
|
|
6
23
|
## [14.0.1](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@14.0.0...@foray1010/eslint-config@14.0.1) (2025-03-11)
|
|
7
24
|
|
|
8
25
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -29,8 +29,9 @@ Z for looser rules
|
|
|
29
29
|
eslintIgnoresConfig,
|
|
30
30
|
eslintNodeConfig,
|
|
31
31
|
} from '@foray1010/eslint-config'
|
|
32
|
+
import { defineConfig } from 'eslint/config'
|
|
32
33
|
|
|
33
|
-
const config =
|
|
34
|
+
const config = defineConfig(eslintIgnoresConfig, eslintNodeConfig)
|
|
34
35
|
export default config
|
|
35
36
|
```
|
|
36
37
|
|
|
@@ -41,8 +42,9 @@ Z for looser rules
|
|
|
41
42
|
eslintIgnoresConfig,
|
|
42
43
|
eslintBrowserConfig,
|
|
43
44
|
} from '@foray1010/eslint-config'
|
|
45
|
+
import { defineConfig } from 'eslint/config'
|
|
44
46
|
|
|
45
|
-
const config =
|
|
47
|
+
const config = defineConfig(eslintIgnoresConfig, eslintBrowserConfig)
|
|
46
48
|
export default config
|
|
47
49
|
```
|
|
48
50
|
|
|
@@ -53,8 +55,9 @@ Z for looser rules
|
|
|
53
55
|
eslintIgnoresConfig,
|
|
54
56
|
eslintReactConfig,
|
|
55
57
|
} from '@foray1010/eslint-config'
|
|
58
|
+
import { defineConfig } from 'eslint/config'
|
|
56
59
|
|
|
57
|
-
const config =
|
|
60
|
+
const config = defineConfig(eslintIgnoresConfig, eslintReactConfig)
|
|
58
61
|
export default config
|
|
59
62
|
```
|
|
60
63
|
|
|
@@ -62,28 +65,23 @@ Z for looser rules
|
|
|
62
65
|
|
|
63
66
|
```js
|
|
64
67
|
import {
|
|
65
|
-
applyConfig,
|
|
66
68
|
eslintIgnoresConfig,
|
|
67
69
|
eslintNodeConfig,
|
|
68
70
|
eslintReactConfig,
|
|
69
71
|
} from '@foray1010/eslint-config'
|
|
72
|
+
import { defineConfig } from 'eslint/config'
|
|
70
73
|
|
|
71
|
-
const config =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
filePrefixes: ['src'],
|
|
83
|
-
},
|
|
84
|
-
eslintReactConfig,
|
|
85
|
-
),
|
|
86
|
-
]
|
|
74
|
+
const config = defineConfig(
|
|
75
|
+
eslintIgnoresConfig,
|
|
76
|
+
{
|
|
77
|
+
ignores: ['src/**'],
|
|
78
|
+
extends: [eslintNodeConfig],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
files: ['src/**'],
|
|
82
|
+
extends: [eslintReactConfig],
|
|
83
|
+
},
|
|
84
|
+
)
|
|
87
85
|
export default config
|
|
88
86
|
```
|
|
89
87
|
|
package/bases/base.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import js from '@eslint/js'
|
|
2
|
-
|
|
2
|
+
// eslint-disable-next-line import-x/extensions
|
|
3
|
+
import eslintPluginEslintCommentsConfigs from '@eslint-community/eslint-plugin-eslint-comments/configs'
|
|
3
4
|
import { hasDep, isESM } from '@foray1010/common-presets-utils'
|
|
5
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
6
|
+
import { defineConfig } from 'eslint/config'
|
|
4
7
|
import eslintPluginImportX from 'eslint-plugin-import-x'
|
|
5
8
|
import eslintPluginJest from 'eslint-plugin-jest'
|
|
6
9
|
import eslintPluginRegexp from 'eslint-plugin-regexp'
|
|
@@ -14,23 +17,22 @@ import {
|
|
|
14
17
|
typeScriptTestFileGlobs,
|
|
15
18
|
} from '../constants.mjs'
|
|
16
19
|
|
|
17
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
18
|
-
|
|
19
|
-
/** @returns {Promise<EslintConfig>} */
|
|
20
20
|
async function generateTypeScriptConfig() {
|
|
21
21
|
// typescript plugins are depended on `typescript` package
|
|
22
|
-
if (!hasDep('typescript')) return
|
|
22
|
+
if (!hasDep('typescript')) return defineConfig({})
|
|
23
23
|
|
|
24
24
|
// eslint-disable-next-line import-x/no-unresolved
|
|
25
25
|
const tseslint = (await import('typescript-eslint')).default
|
|
26
26
|
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
...tseslint.config({
|
|
27
|
+
return defineConfig(
|
|
28
|
+
{
|
|
30
29
|
files: typeScriptFileGlobs,
|
|
31
30
|
extends: [
|
|
31
|
+
// @ts-expect-error tseslint interface does not align with eslint
|
|
32
32
|
tseslint.configs.eslintRecommended,
|
|
33
|
-
|
|
33
|
+
// @ts-expect-error tseslint interface does not align with eslint
|
|
34
|
+
tseslint.configs.recommendedTypeChecked,
|
|
35
|
+
eslintPluginImportX.configs['typescript'],
|
|
34
36
|
esmConfig,
|
|
35
37
|
],
|
|
36
38
|
languageOptions: {
|
|
@@ -42,13 +44,7 @@ async function generateTypeScriptConfig() {
|
|
|
42
44
|
project: ['./tsconfig*.json', './packages/*/tsconfig*.json'],
|
|
43
45
|
},
|
|
44
46
|
},
|
|
45
|
-
settings: {
|
|
46
|
-
'import-x/resolver': {
|
|
47
|
-
typescript: true,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
47
|
rules: {
|
|
51
|
-
...eslintPluginImportX.configs['typescript']?.rules,
|
|
52
48
|
// separate type exports which allow certain optimizations within compilers
|
|
53
49
|
'@typescript-eslint/consistent-type-exports': [
|
|
54
50
|
'error',
|
|
@@ -136,8 +132,7 @@ async function generateTypeScriptConfig() {
|
|
|
136
132
|
// It is disabled in recommended config but re-enabled here to enforce a subset of global variables that supported by both node.js and browsers
|
|
137
133
|
'no-undef': 'error',
|
|
138
134
|
},
|
|
139
|
-
}
|
|
140
|
-
// @ts-expect-error As previous item's type is not correct, this item is affected too
|
|
135
|
+
},
|
|
141
136
|
{
|
|
142
137
|
files: typeScriptTestFileGlobs,
|
|
143
138
|
rules: {
|
|
@@ -149,11 +144,10 @@ async function generateTypeScriptConfig() {
|
|
|
149
144
|
'jest/unbound-method': ['error', { ignoreStatic: true }],
|
|
150
145
|
},
|
|
151
146
|
},
|
|
152
|
-
|
|
147
|
+
)
|
|
153
148
|
}
|
|
154
149
|
|
|
155
|
-
|
|
156
|
-
const cjsConfig = {
|
|
150
|
+
const cjsConfig = defineConfig({
|
|
157
151
|
languageOptions: {
|
|
158
152
|
globals: globals.commonjs,
|
|
159
153
|
sourceType: 'script',
|
|
@@ -162,10 +156,9 @@ const cjsConfig = {
|
|
|
162
156
|
// commonjs must use strict mode
|
|
163
157
|
strict: ['error', 'global'],
|
|
164
158
|
},
|
|
165
|
-
}
|
|
159
|
+
})
|
|
166
160
|
|
|
167
|
-
|
|
168
|
-
const esmConfig = {
|
|
161
|
+
const esmConfig = defineConfig({
|
|
169
162
|
languageOptions: {
|
|
170
163
|
sourceType: 'module',
|
|
171
164
|
},
|
|
@@ -178,16 +171,31 @@ const esmConfig = {
|
|
|
178
171
|
// auto sort import statements
|
|
179
172
|
'simple-import-sort/imports': 'error',
|
|
180
173
|
},
|
|
181
|
-
}
|
|
174
|
+
})
|
|
182
175
|
|
|
183
|
-
|
|
184
|
-
const baseConfig = [
|
|
176
|
+
const baseConfig = defineConfig(
|
|
185
177
|
js.configs.recommended,
|
|
186
|
-
eslintPluginRegexp.configs['flat/recommended'],
|
|
187
178
|
{
|
|
188
|
-
|
|
179
|
+
extends: [
|
|
180
|
+
// @ts-expect-error no official types
|
|
181
|
+
eslintPluginEslintCommentsConfigs['recommended'],
|
|
182
|
+
],
|
|
183
|
+
rules: {
|
|
184
|
+
// allow disable eslint rules for whole file without re-enable it in the end of the file
|
|
185
|
+
'@eslint-community/eslint-comments/disable-enable-pair': [
|
|
186
|
+
'error',
|
|
187
|
+
{ allowWholeFile: true },
|
|
188
|
+
],
|
|
189
|
+
// make sure every eslint-disable comments are in use
|
|
190
|
+
'@eslint-community/eslint-comments/no-unused-disable': 'error',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
extends: [
|
|
195
|
+
// @ts-expect-error eslint-plugin-import-x interface does not align with eslint
|
|
196
|
+
eslintPluginImportX.flatConfigs.recommended,
|
|
197
|
+
],
|
|
189
198
|
rules: {
|
|
190
|
-
...eslintPluginImportX.flatConfigs.recommended.rules,
|
|
191
199
|
// this rule doesn't support commonjs, some dependencies are using commonjs
|
|
192
200
|
'import-x/default': 'off',
|
|
193
201
|
// Does not work after upgrading to eslint-plugin-import-x v4, got this error message: `sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options. (undefined:undefined)`
|
|
@@ -262,27 +270,17 @@ const baseConfig = [
|
|
|
262
270
|
},
|
|
263
271
|
},
|
|
264
272
|
{
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
languageOptions: {
|
|
270
|
-
ecmaVersion: 2023,
|
|
271
|
-
globals: {
|
|
272
|
-
...globals.es2023,
|
|
273
|
-
/* Not using `node` to explicitly import node.js only built-in modules, e.g.
|
|
274
|
-
* import { Buffer } from 'node:buffer'
|
|
275
|
-
* import process from 'node:process'
|
|
276
|
-
*/
|
|
277
|
-
...globals['shared-node-browser'],
|
|
278
|
-
},
|
|
273
|
+
extends: [eslintPluginRegexp.configs['flat/recommended']],
|
|
274
|
+
rules: {
|
|
275
|
+
// enable regexp strict mode (use `v` flag instead when it is widely supported)
|
|
276
|
+
'regexp/require-unicode-regexp': 'error',
|
|
279
277
|
},
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
280
|
plugins: {
|
|
281
|
-
'@eslint-community/eslint-comments': eslintPluginEslintComments,
|
|
282
281
|
unicorn: eslintPluginUnicorn,
|
|
283
282
|
},
|
|
284
283
|
rules: {
|
|
285
|
-
...eslintPluginEslintComments.configs['recommended']?.rules,
|
|
286
284
|
...Object.fromEntries(
|
|
287
285
|
Object.entries(
|
|
288
286
|
eslintPluginUnicorn.configs['flat/recommended']?.rules ?? {},
|
|
@@ -294,13 +292,40 @@ const baseConfig = [
|
|
|
294
292
|
)
|
|
295
293
|
}),
|
|
296
294
|
),
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
//
|
|
303
|
-
'
|
|
295
|
+
// use with `unicorn/throw-new-error`
|
|
296
|
+
// disallow builtins to be created without `new` operator, to be consistent with es6 class syntax
|
|
297
|
+
'unicorn/new-for-builtins': 'error',
|
|
298
|
+
// some legacy projects still use commonjs
|
|
299
|
+
'unicorn/prefer-module': 'off',
|
|
300
|
+
// `querySelector` is slower than `getElementById`
|
|
301
|
+
'unicorn/prefer-query-selector': 'off',
|
|
302
|
+
// `Array.from(iterable)` is more readable than `[...iterable]`
|
|
303
|
+
'unicorn/prefer-spread': 'off',
|
|
304
|
+
// sometimes it is less readable using ternary expressions
|
|
305
|
+
'unicorn/prefer-ternary': 'off',
|
|
306
|
+
// webpack support on `top level await` is still experimental, and some legacy projects still use commonjs
|
|
307
|
+
'unicorn/prefer-top-level-await': 'off',
|
|
308
|
+
// use with `unicorn/new-for-builtins`
|
|
309
|
+
'unicorn/throw-new-error': 'error',
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
linterOptions: {
|
|
314
|
+
reportUnusedDisableDirectives: 'error',
|
|
315
|
+
reportUnusedInlineConfigs: 'error',
|
|
316
|
+
},
|
|
317
|
+
languageOptions: {
|
|
318
|
+
ecmaVersion: 2023,
|
|
319
|
+
globals: {
|
|
320
|
+
...globals.es2023,
|
|
321
|
+
/* Not using `node` to explicitly import node.js only built-in modules, e.g.
|
|
322
|
+
* import { Buffer } from 'node:buffer'
|
|
323
|
+
* import process from 'node:process'
|
|
324
|
+
*/
|
|
325
|
+
...globals['shared-node-browser'],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
rules: {
|
|
304
329
|
// always use named function for easier to debug via stack trace
|
|
305
330
|
'func-names': ['error', 'as-needed'],
|
|
306
331
|
// prefer explicitly convert type for readability
|
|
@@ -317,49 +342,31 @@ const baseConfig = [
|
|
|
317
342
|
destructuring: 'all',
|
|
318
343
|
},
|
|
319
344
|
],
|
|
320
|
-
// enable regexp strict mode (use `v` flag instead when it is widely supported)
|
|
321
|
-
'regexp/require-unicode-regexp': 'error',
|
|
322
|
-
// use with `unicorn/throw-new-error`
|
|
323
|
-
// disallow builtins to be created without `new` operator, to be consistent with es6 class syntax
|
|
324
|
-
'unicorn/new-for-builtins': 'error',
|
|
325
|
-
// some legacy projects still use commonjs
|
|
326
|
-
'unicorn/prefer-module': 'off',
|
|
327
|
-
// `querySelector` is slower than `getElementById`
|
|
328
|
-
'unicorn/prefer-query-selector': 'off',
|
|
329
|
-
// `Array.from(iterable)` is more readable than `[...iterable]`
|
|
330
|
-
'unicorn/prefer-spread': 'off',
|
|
331
|
-
// sometimes it is less readable using ternary expressions
|
|
332
|
-
'unicorn/prefer-ternary': 'off',
|
|
333
|
-
// webpack support on `top level await` is still experimental, and some legacy projects still use commonjs
|
|
334
|
-
'unicorn/prefer-top-level-await': 'off',
|
|
335
|
-
// use with `unicorn/new-for-builtins`
|
|
336
|
-
'unicorn/throw-new-error': 'error',
|
|
337
345
|
},
|
|
338
346
|
},
|
|
339
347
|
{
|
|
340
348
|
files: ['**/*.js'],
|
|
341
|
-
|
|
349
|
+
extends: [isESM() ? esmConfig : cjsConfig],
|
|
342
350
|
},
|
|
343
351
|
{
|
|
344
352
|
files: ['**/*.cjs'],
|
|
345
|
-
|
|
353
|
+
extends: [cjsConfig],
|
|
346
354
|
},
|
|
347
355
|
{
|
|
348
356
|
files: ['**/*.mjs'],
|
|
349
|
-
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
files: testFileGlobs,
|
|
353
|
-
...eslintPluginJest.configs['flat/recommended'],
|
|
354
|
-
...eslintPluginJest.configs['flat/style'],
|
|
357
|
+
extends: [esmConfig],
|
|
355
358
|
},
|
|
356
359
|
{
|
|
357
360
|
files: testFileGlobs,
|
|
361
|
+
extends: [
|
|
362
|
+
eslintPluginJest.configs['flat/recommended'],
|
|
363
|
+
eslintPluginJest.configs['flat/style'],
|
|
364
|
+
],
|
|
358
365
|
rules: {
|
|
359
366
|
// make sure lifecycle hooks on the top for readability
|
|
360
367
|
'jest/prefer-hooks-on-top': 'error',
|
|
361
368
|
},
|
|
362
369
|
},
|
|
363
|
-
|
|
364
|
-
|
|
370
|
+
await generateTypeScriptConfig(),
|
|
371
|
+
)
|
|
365
372
|
export default baseConfig
|
package/bases/browser.mjs
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import { hasDep } from '@foray1010/common-presets-utils'
|
|
2
2
|
import restrictedGlobals from 'confusing-browser-globals'
|
|
3
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
4
|
+
import { defineConfig } from 'eslint/config'
|
|
3
5
|
import eslintPluginCompat from 'eslint-plugin-compat'
|
|
4
6
|
import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'
|
|
5
7
|
import globals from 'globals'
|
|
6
8
|
|
|
7
9
|
import { testFileGlobs } from '../constants.mjs'
|
|
8
10
|
|
|
9
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
10
|
-
|
|
11
|
-
/** @returns {Promise<EslintConfig>} */
|
|
12
11
|
async function generateJestDomConfig() {
|
|
13
12
|
// `eslint-plugin-jest-dom` depends on `@testing-library/dom` package
|
|
14
|
-
if (!hasDep('@testing-library/dom')) return
|
|
13
|
+
if (!hasDep('@testing-library/dom')) return defineConfig({})
|
|
15
14
|
|
|
16
15
|
const eslintPluginJestDom = (await import('eslint-plugin-jest-dom')).default
|
|
17
16
|
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
]
|
|
17
|
+
return defineConfig({
|
|
18
|
+
files: testFileGlobs,
|
|
19
|
+
extends: [eslintPluginJestDom.configs['flat/recommended']],
|
|
20
|
+
})
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
const browserConfig = [
|
|
23
|
+
const browserConfig = defineConfig(
|
|
28
24
|
{
|
|
29
25
|
languageOptions: {
|
|
30
26
|
globals: {
|
|
@@ -44,22 +40,14 @@ const browserConfig = [
|
|
|
44
40
|
'no-restricted-globals': ['error', ...restrictedGlobals],
|
|
45
41
|
},
|
|
46
42
|
},
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
files: testFileGlobs,
|
|
50
|
-
plugins: {
|
|
51
|
-
'testing-library': eslintPluginTestingLibrary,
|
|
52
|
-
},
|
|
53
|
-
rules: {
|
|
54
|
-
...eslintPluginTestingLibrary.configs['flat/dom']?.rules,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
43
|
+
await generateJestDomConfig(),
|
|
57
44
|
{
|
|
58
45
|
files: testFileGlobs,
|
|
46
|
+
extends: [eslintPluginTestingLibrary.configs['flat/dom']],
|
|
59
47
|
rules: {
|
|
60
48
|
// allow to use nodejs modules in tests
|
|
61
49
|
'import-x/no-nodejs-modules': 'off',
|
|
62
50
|
},
|
|
63
51
|
},
|
|
64
|
-
|
|
52
|
+
)
|
|
65
53
|
export default browserConfig
|
package/bases/ignores.mjs
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'**/node_modules/**',
|
|
13
|
-
],
|
|
14
|
-
},
|
|
15
|
-
]
|
|
4
|
+
const ignoresConfig = defineConfig(
|
|
5
|
+
globalIgnores([
|
|
6
|
+
'**/.yarn/**',
|
|
7
|
+
'**/build/**',
|
|
8
|
+
'**/coverage/**',
|
|
9
|
+
'**/dist/**',
|
|
10
|
+
'**/node_modules/**',
|
|
11
|
+
]),
|
|
12
|
+
)
|
|
16
13
|
export default ignoresConfig
|
package/bases/node.mjs
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { isESM } from '@foray1010/common-presets-utils'
|
|
2
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
3
|
+
import { defineConfig } from 'eslint/config'
|
|
2
4
|
import eslintPluginN from 'eslint-plugin-n'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** @type {EslintConfig[number]} */
|
|
7
|
-
const cjsConfig = {
|
|
6
|
+
const cjsConfig = defineConfig({
|
|
8
7
|
languageOptions: {
|
|
9
8
|
globals: {
|
|
10
9
|
__dirname: 'readonly',
|
|
11
10
|
__filename: 'readonly',
|
|
12
11
|
},
|
|
13
12
|
},
|
|
14
|
-
}
|
|
13
|
+
})
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
const nodeConfig = [
|
|
15
|
+
const nodeConfig = defineConfig(
|
|
18
16
|
{
|
|
19
17
|
plugins: {
|
|
20
18
|
n: eslintPluginN,
|
|
@@ -67,12 +65,12 @@ const nodeConfig = [
|
|
|
67
65
|
: [
|
|
68
66
|
{
|
|
69
67
|
files: ['**/*.js'],
|
|
70
|
-
|
|
68
|
+
extends: [cjsConfig],
|
|
71
69
|
},
|
|
72
70
|
]),
|
|
73
71
|
{
|
|
74
72
|
files: ['**/*.{cjs,cts}'],
|
|
75
|
-
|
|
73
|
+
extends: [cjsConfig],
|
|
76
74
|
},
|
|
77
|
-
|
|
75
|
+
)
|
|
78
76
|
export default nodeConfig
|
package/bases/prettier.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
1
3
|
// eslint-disable-next-line import-x/extensions
|
|
2
4
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
|
3
5
|
|
|
4
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
5
|
-
|
|
6
|
-
/** @type {EslintConfig} */
|
|
7
6
|
// should be placed at the end to override other configs
|
|
8
|
-
const prettierConfig =
|
|
7
|
+
const prettierConfig = defineConfig(
|
|
9
8
|
// This includes `eslint-config-prettier` as peer dependency
|
|
10
9
|
eslintPluginPrettierRecommended,
|
|
11
|
-
|
|
10
|
+
)
|
|
12
11
|
export default prettierConfig
|
package/bases/react.mjs
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
1
3
|
import eslintPluginReact from 'eslint-plugin-react'
|
|
2
4
|
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
|
|
3
5
|
import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'
|
|
4
6
|
|
|
5
7
|
import { testFileGlobs } from '../constants.mjs'
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** @type {EslintConfig} */
|
|
10
|
-
const reactConfig = [
|
|
11
|
-
eslintPluginReact.configs.flat.recommended,
|
|
12
|
-
eslintPluginReact.configs.flat['jsx-runtime'],
|
|
9
|
+
const reactConfig = defineConfig(
|
|
13
10
|
{
|
|
14
11
|
settings: {
|
|
15
12
|
react: {
|
|
16
13
|
version: 'detect',
|
|
17
14
|
},
|
|
18
15
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
extends: [
|
|
17
|
+
eslintPluginReact.configs.flat.recommended,
|
|
18
|
+
eslintPluginReact.configs.flat['jsx-runtime'],
|
|
19
|
+
eslintPluginReactHooks.configs['recommended-latest'],
|
|
20
|
+
],
|
|
22
21
|
rules: {
|
|
23
|
-
...eslintPluginReactHooks.configs['recommended']?.rules,
|
|
24
22
|
// avoid unexpected form submits
|
|
25
23
|
'react/button-has-type': 'error',
|
|
26
24
|
'react/jsx-no-useless-fragment': [
|
|
@@ -61,13 +59,7 @@ const reactConfig = [
|
|
|
61
59
|
},
|
|
62
60
|
{
|
|
63
61
|
files: testFileGlobs,
|
|
64
|
-
|
|
65
|
-
// Do not use flat config directly as eslint v9 does not support duplicated plugins (already defined in browser.mjs)
|
|
66
|
-
...eslintPluginTestingLibrary.configs['flat/react']?.rules,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
files: testFileGlobs,
|
|
62
|
+
extends: [eslintPluginTestingLibrary.configs['flat/react']],
|
|
71
63
|
rules: {
|
|
72
64
|
// avoid using unnecessary `await` as workaround for `not wrapped in act(...)` warnings
|
|
73
65
|
'testing-library/no-await-sync-events': [
|
|
@@ -82,5 +74,5 @@ const reactConfig = [
|
|
|
82
74
|
'testing-library/prefer-user-event': 'error',
|
|
83
75
|
},
|
|
84
76
|
},
|
|
85
|
-
|
|
77
|
+
)
|
|
86
78
|
export default reactConfig
|
package/index.mjs
CHANGED
|
@@ -1,33 +1,29 @@
|
|
|
1
|
+
// eslint-disable-next-line import-x/extensions, import-x/no-unresolved
|
|
2
|
+
import { defineConfig } from 'eslint/config'
|
|
3
|
+
|
|
1
4
|
import baseConfig from './bases/base.mjs'
|
|
2
5
|
import browserConfig from './bases/browser.mjs'
|
|
3
6
|
import nodeConfig from './bases/node.mjs'
|
|
4
7
|
import prettierConfig from './bases/prettier.mjs'
|
|
5
8
|
import reactConfig from './bases/react.mjs'
|
|
6
9
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export const eslintBrowserConfig = [
|
|
13
|
-
...baseConfig,
|
|
14
|
-
...browserConfig,
|
|
15
|
-
...prettierConfig,
|
|
16
|
-
]
|
|
10
|
+
export const eslintBrowserConfig = defineConfig(
|
|
11
|
+
baseConfig,
|
|
12
|
+
browserConfig,
|
|
13
|
+
prettierConfig,
|
|
14
|
+
)
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]
|
|
16
|
+
export const eslintNodeConfig = defineConfig(
|
|
17
|
+
baseConfig,
|
|
18
|
+
nodeConfig,
|
|
19
|
+
prettierConfig,
|
|
20
|
+
)
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
]
|
|
22
|
+
export const eslintReactConfig = defineConfig(
|
|
23
|
+
baseConfig,
|
|
24
|
+
browserConfig,
|
|
25
|
+
reactConfig,
|
|
26
|
+
prettierConfig,
|
|
27
|
+
)
|
|
32
28
|
|
|
33
29
|
export { default as eslintIgnoresConfig } from './bases/ignores.mjs'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@foray1010/eslint-config",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "15.0.1",
|
|
5
5
|
"homepage": "https://github.com/foray1010/common-presets/tree/master/packages/eslint-config#readme",
|
|
6
6
|
"bugs": "https://github.com/foray1010/common-presets/issues",
|
|
7
7
|
"repository": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@testing-library/dom": "^10.0.0",
|
|
50
|
-
"eslint": "^9.
|
|
50
|
+
"eslint": "^9.22.0",
|
|
51
51
|
"prettier": "^3.0.0",
|
|
52
52
|
"typescript": "^5.0.2"
|
|
53
53
|
},
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "df7fe29d7a74d9a61415c61074e5663db3e56044"
|
|
69
69
|
}
|
package/utils/applyConfig.mjs
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
|
|
3
|
-
import { supportedFilesGlob } from '../constants.mjs'
|
|
4
|
-
|
|
5
|
-
/** @typedef {import('../types/internal.d.ts').EslintConfig} EslintConfig */
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Extend the flat configs with default files and ignores
|
|
9
|
-
* @param {{
|
|
10
|
-
* readonly filePrefixes: string | string[],
|
|
11
|
-
* readonly ignores?: string[] | undefined
|
|
12
|
-
* }} options
|
|
13
|
-
* @param {EslintConfig} eslintConfig
|
|
14
|
-
* @returns {EslintConfig}
|
|
15
|
-
*/
|
|
16
|
-
export function applyConfig(options, eslintConfig) {
|
|
17
|
-
const filePrefixes = [options.filePrefixes].flat()
|
|
18
|
-
if (filePrefixes.length === 0) {
|
|
19
|
-
throw new TypeError('filePrefixes must not be empty')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Do not allow string such as "eslint:recommended" because it cannot be overridden by files/ignores
|
|
23
|
-
for (const config of eslintConfig) {
|
|
24
|
-
if (typeof config === 'string') {
|
|
25
|
-
throw new TypeError(
|
|
26
|
-
`Cannot extend ${config} with files/ignores, use \`@eslint/js\` instead`,
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (Object.keys(config).includes('ignores')) {
|
|
31
|
-
throw new TypeError('Do not use `ignores` in config')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return eslintConfig.map((config) => {
|
|
36
|
-
const files = generateCombinations(filePrefixes, config.files)
|
|
37
|
-
return {
|
|
38
|
-
...config,
|
|
39
|
-
...(files ? { files } : {}),
|
|
40
|
-
...(options.ignores ? { ignores: options.ignores } : {}),
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {string[]} prefixes
|
|
47
|
-
* @param {EslintConfig[number]['files']} originalGlobs
|
|
48
|
-
* @returns {string[] | undefined}
|
|
49
|
-
*/
|
|
50
|
-
function generateCombinations(prefixes, originalGlobs) {
|
|
51
|
-
if (!originalGlobs || originalGlobs.length === 0) {
|
|
52
|
-
return prefixes.map((prefix) => path.join(prefix, supportedFilesGlob))
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const verifiedOriginalGlobs = originalGlobs.filter(
|
|
56
|
-
/** @returns {originalGlob is string} */
|
|
57
|
-
(originalGlob) => typeof originalGlob === 'string',
|
|
58
|
-
)
|
|
59
|
-
if (originalGlobs.length !== verifiedOriginalGlobs.length) {
|
|
60
|
-
throw new TypeError(
|
|
61
|
-
`Do not support using non-string value in files/ignores`,
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return prefixes.flatMap((prefix) => {
|
|
66
|
-
return verifiedOriginalGlobs.flatMap((originalGlob) => {
|
|
67
|
-
const signRegexp = /^!/u
|
|
68
|
-
const sign = originalGlob.match(signRegexp)?.[0] ?? ''
|
|
69
|
-
return sign + path.join(prefix, originalGlob.replace(signRegexp, ''))
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
}
|