Skip to content

Commit 710a107

Browse files
authored
Migrate to ESLint flat config (#18)
Flat config is available in ESLint 8.x and default in 9.x. Let's future-proof our ESLint configuration. The configuration is functionally exactly the same as before, only the format changed. Some implementation details: - Replaced @typescript-eslint/eslint-plugin peer dep with typescript-eslint, the unified package that exports flat config objects (tseslint.config(), tseslint.configs.recommendedTypeChecked, etc.) - Added @eslint/js dependency (programmatic replacement for "eslint:recommended") - Added globals dependency (replacement for env: { browser, es2021 }) This is a breaking change: consumers must switch to flat config and install typescript-eslint instead of @typescript-eslint/eslint-plugin. Disclosure: the configuration has been LLM-translated but I then LLM-reviewed it multiple times and spot-checked manually. [1] https://eslint.org/docs/latest/extend/plugin-migration-flat-config
1 parent 31afb38 commit 710a107

4 files changed

Lines changed: 111 additions & 408 deletions

File tree

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@ yarn add --dev git+https://github.com/lune-climate/eslint-config.git#master
1919
be present in your `package.json`.
2020
* You have to provide the `peerDependencies` that we [expect](./package.json).
2121

22-
3. Adapt your `.eslintrc` or equivalent:
22+
3. Create an `eslint.config.js` (or adapt your existing one):
2323

2424
a. Remove configuration that is already provided by [this shared configuration](./index.js).
25-
b. Add `@lune-climate` to `extends`, like:
25+
b. Spread the shared config array into your config:
2626

27-
```
28-
extends: ["@lune-climate"],
29-
```
27+
```js
28+
const luneConfig = require('@lune-climate/eslint-config')
29+
30+
module.exports = [
31+
...luneConfig,
32+
// your project-specific overrides here
33+
]
34+
```

index.js

Lines changed: 91 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,105 @@
1-
module.exports = {
2-
env: {
3-
browser: true,
4-
es2021: true,
5-
},
6-
extends: [
7-
'eslint:recommended',
8-
'plugin:promise/recommended',
9-
'plugin:@typescript-eslint/recommended-type-checked',
10-
'prettier',
11-
],
12-
parser: '@typescript-eslint/parser',
13-
parserOptions: {
14-
projectService: true,
15-
},
16-
plugins: ['@typescript-eslint', 'n', 'simple-import-sort'],
17-
rules: {
18-
// Unnecessary with TS and generates false positives.
19-
// https://github.com/typescript-eslint/typescript-eslint/blob/181e705887e9e07f0fa28195644cc94e5b4f039d/docs/linting/Troubleshooting.mdx#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
20-
'no-undef': 'off',
21-
'no-use-before-define': 'off', // Unnecessary with TS and generates false positives.
22-
'comma-dangle': ['error', 'always-multiline'],
23-
'func-style': ['error', 'declaration'],
1+
const eslint = require('@eslint/js')
2+
const tseslint = require('typescript-eslint')
3+
const pluginPromise = require('eslint-plugin-promise')
4+
const pluginN = require('eslint-plugin-n')
5+
const pluginSimpleImportSort = require('eslint-plugin-simple-import-sort')
6+
const eslintConfigPrettier = require('eslint-config-prettier')
7+
const globals = require('globals')
8+
9+
module.exports = tseslint.config(
10+
eslint.configs.recommended,
11+
pluginPromise.configs['flat/recommended'],
12+
...tseslint.configs.recommendedTypeChecked,
13+
{
14+
languageOptions: {
15+
ecmaVersion: 2021,
16+
globals: {
17+
...globals.browser,
18+
...globals.es2021,
19+
},
20+
parserOptions: {
21+
projectService: true,
22+
},
23+
},
24+
plugins: {
25+
n: pluginN,
26+
'simple-import-sort': pluginSimpleImportSort,
27+
},
28+
rules: {
29+
// Unnecessary with TS and generates false positives.
30+
// https://github.com/typescript-eslint/typescript-eslint/blob/181e705887e9e07f0fa28195644cc94e5b4f039d/docs/linting/Troubleshooting.mdx#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
31+
'no-undef': 'off',
32+
'no-use-before-define': 'off', // Unnecessary with TS and generates false positives.
33+
'comma-dangle': ['error', 'always-multiline'],
34+
'func-style': ['error', 'declaration'],
2435

25-
// Allows idiomatic infinite loops, rejects other cases
26-
'no-constant-condition': ['error', { checkLoops: false }],
36+
// Allows idiomatic infinite loops, rejects other cases
37+
'no-constant-condition': ['error', { checkLoops: false }],
2738

28-
'no-useless-constructor': 'off',
29-
'no-unused-vars': 'off',
30-
'no-extra-semi': 'off',
31-
'no-trailing-spaces': 'error',
39+
'no-useless-constructor': 'off',
40+
'no-unused-vars': 'off',
41+
'no-extra-semi': 'off',
42+
'no-trailing-spaces': 'error',
3243

33-
// Doesn't complain when we have let {a, b} = obj and b is not reassigned,
34-
// complains otherwise.
35-
'prefer-const': ['error', { destructuring: 'all' }],
44+
// Doesn't complain when we have let {a, b} = obj and b is not reassigned,
45+
// complains otherwise.
46+
'prefer-const': ['error', { destructuring: 'all' }],
3647

37-
'@typescript-eslint/no-useless-constructor': ['error'],
38-
'@typescript-eslint/no-unnecessary-type-assertion': ['error'],
39-
'@typescript-eslint/no-unused-vars': [
40-
'error',
41-
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
42-
],
43-
'@typescript-eslint/no-unnecessary-condition': ['error'],
44-
'simple-import-sort/imports': ['error'],
45-
complexity: ['error', { max: 14 }],
46-
// To support TS overloads
47-
// https://github.com/typescript-eslint/typescript-eslint/blob/6fd476c32c4757cb9f4c442f0cd92875671eed30/packages/eslint-plugin/docs/rules/no-redeclare.md
48-
'no-redeclare': 'off',
49-
'@typescript-eslint/no-redeclare': ['error'],
48+
'@typescript-eslint/no-useless-constructor': ['error'],
49+
'@typescript-eslint/no-unnecessary-type-assertion': ['error'],
50+
'@typescript-eslint/no-unused-vars': [
51+
'error',
52+
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
53+
],
54+
'@typescript-eslint/no-unnecessary-condition': ['error'],
55+
'simple-import-sort/imports': ['error'],
56+
complexity: ['error', { max: 14 }],
57+
// To support TS overloads
58+
// https://github.com/typescript-eslint/typescript-eslint/blob/6fd476c32c4757cb9f4c442f0cd92875671eed30/packages/eslint-plugin/docs/rules/no-redeclare.md
59+
'no-redeclare': 'off',
60+
'@typescript-eslint/no-redeclare': ['error'],
5061

51-
/*
52-
@typescript-eslint/recommended-type-checked exceptions
62+
/*
63+
@typescript-eslint/recommended-type-checked exceptions
5364
54-
To be determined if we want to keep these rules disabled long-term, at least some
55-
of these look useful, we just need to configure them so they don't generate so many
56-
false positives.
57-
*/
65+
To be determined if we want to keep these rules disabled long-term, at least some
66+
of these look useful, we just need to configure them so they don't generate so many
67+
false positives.
68+
*/
5869

59-
'@typescript-eslint/require-await': 'off',
60-
'@typescript-eslint/unbound-method': 'off',
70+
'@typescript-eslint/require-await': 'off',
71+
'@typescript-eslint/unbound-method': 'off',
6172

62-
// Being able to use and interact with "any" values
63-
'@typescript-eslint/no-explicit-any': 'off',
64-
'@typescript-eslint/no-unsafe-member-access': 'off',
65-
'@typescript-eslint/no-unsafe-assignment': 'off',
66-
'@typescript-eslint/no-unsafe-return': 'off',
67-
'@typescript-eslint/no-unsafe-call': 'off',
68-
'@typescript-eslint/no-unsafe-argument': 'off',
73+
// Being able to use and interact with "any" values
74+
'@typescript-eslint/no-explicit-any': 'off',
75+
'@typescript-eslint/no-unsafe-member-access': 'off',
76+
'@typescript-eslint/no-unsafe-assignment': 'off',
77+
'@typescript-eslint/no-unsafe-return': 'off',
78+
'@typescript-eslint/no-unsafe-call': 'off',
79+
'@typescript-eslint/no-unsafe-argument': 'off',
6980

70-
// Generates a lof of false positives when it doesn't always understand when a value
71-
// can be safely used in a string context. We can try to configure this behavior.
72-
'@typescript-eslint/no-base-to-string': 'off',
81+
// Generates a lof of false positives when it doesn't always understand when a value
82+
// can be safely used in a string context. We can try to configure this behavior.
83+
'@typescript-eslint/no-base-to-string': 'off',
7384

74-
// We find it creates more problems than it solves.
75-
'@typescript-eslint/no-use-before-define': 'off',
85+
// We find it creates more problems than it solves.
86+
'@typescript-eslint/no-use-before-define': 'off',
7687

77-
// Prevents using Big (among others) in string templates
78-
'@typescript-eslint/restrict-template-expressions': 'off',
88+
// Prevents using Big (among others) in string templates
89+
'@typescript-eslint/restrict-template-expressions': 'off',
7990

80-
/*
81-
End of @typescript-eslint/recommended-type-checked exceptions
82-
*/
91+
/*
92+
End of @typescript-eslint/recommended-type-checked exceptions
93+
*/
8394

84-
'n/handle-callback-err': ['error', '^(err|error)$'],
85-
'n/no-callback-literal': 'error',
86-
'n/no-deprecated-api': 'error',
87-
'n/no-exports-assign': 'error',
88-
'n/no-new-require': 'error',
89-
'n/no-path-concat': 'error',
90-
'n/process-exit-as-throw': 'error',
95+
'n/handle-callback-err': ['error', '^(err|error)$'],
96+
'n/no-callback-literal': 'error',
97+
'n/no-deprecated-api': 'error',
98+
'n/no-exports-assign': 'error',
99+
'n/no-new-require': 'error',
100+
'n/no-path-concat': 'error',
101+
'n/process-exit-as-throw': 'error',
102+
},
91103
},
92-
}
104+
eslintConfigPrettier,
105+
)

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323
"prettier": "^3.0.3"
2424
},
2525
"peerDependencies": {
26-
"@typescript-eslint/eslint-plugin": "^8.0.0",
2726
"eslint": "^8.51.0 || ^9.0.0",
2827
"eslint-plugin-n": "^17.20.0",
2928
"eslint-plugin-promise": "^7.1.0",
30-
"eslint-plugin-simple-import-sort": "^10.0.0 || ^11.0.0 || ^12.0.0"
29+
"eslint-plugin-simple-import-sort": "^10.0.0 || ^11.0.0 || ^12.0.0",
30+
"typescript-eslint": "^8.0.0"
3131
},
3232
"dependencies": {
33-
"eslint-config-prettier": "^9.0.0"
33+
"@eslint/js": "^9.0.0",
34+
"eslint-config-prettier": "^9.0.0",
35+
"globals": "^15.0.0"
3436
}
3537
}

0 commit comments

Comments
 (0)