Skip to content

Commit c275a0a

Browse files
authored
Migrate to ESLint flat config (#519)
1 parent dccd36f commit c275a0a

File tree

6 files changed

+239
-4725
lines changed

6 files changed

+239
-4725
lines changed

.eslintrc.cjs

Lines changed: 0 additions & 138 deletions
This file was deleted.

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"eslint.experimental.useFlatConfig": true,
3+
"eslint.options": {
4+
"overrideConfigFile": "eslint.config.mjs"
5+
}
6+
}

eslint.config.mjs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// @ts-check
2+
3+
import eslint from '@eslint/js';
4+
import eslintConfigPrettier from 'eslint-config-prettier';
5+
import eslintPluginJest from 'eslint-plugin-jest';
6+
import * as eslintPluginJestFormatting from 'eslint-plugin-jest-formatting';
7+
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
8+
import typescriptEslint from 'typescript-eslint';
9+
10+
export default typescriptEslint.config(
11+
eslint.configs.recommended,
12+
...typescriptEslint.configs.strictTypeChecked,
13+
...typescriptEslint.configs.stylisticTypeChecked,
14+
/** @type {any} */ (eslintPluginUnicorn.configs['flat/recommended']),
15+
eslintConfigPrettier,
16+
{
17+
languageOptions: {
18+
ecmaVersion: 'latest',
19+
parserOptions: {
20+
project: true,
21+
},
22+
},
23+
rules: {
24+
// Core ESLint rules
25+
'accessor-pairs': 'error',
26+
'camelcase': [
27+
'error',
28+
{
29+
allow: ['Vue2_6', 'Vue2_7'],
30+
},
31+
],
32+
'consistent-return': 'error',
33+
'curly': ['error', 'all'],
34+
'dot-notation': 'error',
35+
'eqeqeq': 'error',
36+
'getter-return': 'error',
37+
'grouped-accessor-pairs': ['error', 'getBeforeSet'],
38+
'guard-for-in': 'error',
39+
'no-array-constructor': 'error',
40+
'no-bitwise': 'error',
41+
'no-constant-binary-expression': 'error',
42+
'no-constant-condition': 'error',
43+
'no-else-return': ['error', { allowElseIf: false }],
44+
'no-irregular-whitespace': 'error',
45+
'no-lonely-if': 'error',
46+
'no-loop-func': 'error',
47+
'no-mixed-operators': 'error',
48+
'no-new-object': 'error',
49+
'no-prototype-builtins': 'error',
50+
'no-return-assign': 'error',
51+
'no-return-await': 'error',
52+
'no-shadow': 'off', // replaced by @typescript-eslint/no-shadow
53+
'no-template-curly-in-string': 'error',
54+
'no-unsafe-optional-chaining': [
55+
'error',
56+
{ disallowArithmeticOperators: true },
57+
],
58+
'object-shorthand': ['error', 'always', { avoidQuotes: true }],
59+
'prefer-arrow-callback': 'error',
60+
'prefer-template': 'error',
61+
'quotes': [
62+
'error',
63+
'single',
64+
{ avoidEscape: true, allowTemplateLiterals: false },
65+
],
66+
'radix': 'error',
67+
'spaced-comment': 'error',
68+
69+
// eslint-plugin-unicorn
70+
'unicorn/filename-case': 'off',
71+
'unicorn/no-null': 'off',
72+
'unicorn/no-useless-undefined': 'off', // conflicts with consistent-return
73+
'unicorn/prevent-abbreviations': [
74+
'warn',
75+
{
76+
replacements: {
77+
prop: false,
78+
},
79+
},
80+
],
81+
82+
// @typescript-eslint/eslint-plugin
83+
'@typescript-eslint/consistent-type-exports': 'error',
84+
'@typescript-eslint/consistent-type-imports': 'error',
85+
'@typescript-eslint/explicit-module-boundary-types': 'error',
86+
'@typescript-eslint/no-confusing-void-expression': [
87+
'error',
88+
{
89+
ignoreVoidOperator: true,
90+
ignoreArrowShorthand: true,
91+
},
92+
],
93+
'@typescript-eslint/no-explicit-any': 'off', // needed for Vue types compatibility
94+
'@typescript-eslint/no-extraneous-class': 'off',
95+
'@typescript-eslint/no-shadow': [
96+
'warn',
97+
{ ignoreOnInitialization: true },
98+
],
99+
'@typescript-eslint/no-unsafe-unary-minus': 'error',
100+
'@typescript-eslint/no-useless-template-literals': 'error',
101+
'@typescript-eslint/prefer-enum-initializers': 'error',
102+
'@typescript-eslint/prefer-readonly': 'error',
103+
'@typescript-eslint/promise-function-async': 'error',
104+
'@typescript-eslint/sort-type-constituents': 'warn',
105+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
106+
},
107+
},
108+
{ ignores: ['**/*.json', 'node_modules', 'dist'] },
109+
{
110+
files: ['eslint.config.mjs'],
111+
rules: {
112+
// less strict rules for ESLint config while some ESLint plugins don't provide proper types
113+
'@typescript-eslint/no-unsafe-argument': 'off',
114+
'@typescript-eslint/no-unsafe-assignment': 'off',
115+
'@typescript-eslint/no-unsafe-call': 'off',
116+
'@typescript-eslint/no-unsafe-member-access': 'off',
117+
},
118+
},
119+
{
120+
files: ['tests/**/*.spec.ts'],
121+
plugins: {
122+
'jest': eslintPluginJest,
123+
'jest-formatting': eslintPluginJestFormatting,
124+
},
125+
rules: {
126+
...eslintPluginJest.configs['flat/recommended'].rules,
127+
...eslintPluginJestFormatting.configs.recommended.overrides[0].rules,
128+
129+
// additional Jest rules
130+
'jest/consistent-test-it': 'error',
131+
'jest/no-confusing-set-timeout': 'error',
132+
'jest/no-duplicate-hooks': 'error',
133+
'jest/no-test-return-statement': 'error',
134+
'jest/no-untyped-mock-factory': 'error',
135+
'jest/prefer-called-with': 'warn',
136+
'jest/prefer-comparison-matcher': 'warn',
137+
'jest/prefer-equality-matcher': 'warn',
138+
'jest/prefer-expect-resolves': 'warn',
139+
'jest/prefer-hooks-on-top': 'warn',
140+
'jest/prefer-mock-promise-shorthand': 'error',
141+
'jest/prefer-spy-on': 'warn',
142+
'jest/prefer-strict-equal': 'warn',
143+
'jest/require-to-throw-message': 'warn',
144+
'jest/require-top-level-describe': 'warn',
145+
146+
// less strict other rules
147+
'@typescript-eslint/no-non-null-assertion': 'off',
148+
'@typescript-eslint/no-unsafe-argument': 'off',
149+
'@typescript-eslint/no-unsafe-assignment': 'off',
150+
'@typescript-eslint/no-unsafe-call': 'off',
151+
},
152+
},
153+
);

0 commit comments

Comments
 (0)