Skip to content

Commit bbb82cc

Browse files
authored
chore: migrate to flat ESLint config (#1781)
* chore: migrate to flat eslint config * chore: add types for untyped plugins * chore: ignore a ts error with `@typescript-eslint` plugin for now * test: always run linting
1 parent ae04468 commit bbb82cc

File tree

7 files changed

+181
-152
lines changed

7 files changed

+181
-152
lines changed

.eslintignore

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

.eslintrc.js

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

eslint.config.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
'use strict';
2+
3+
const pluginEslintCommentsConfigs = require('@eslint-community/eslint-plugin-eslint-comments/configs');
4+
const pluginTypeScriptESLint = require('@typescript-eslint/eslint-plugin');
5+
const parserTypeScriptESLint = require('@typescript-eslint/parser');
6+
const pluginESLintPlugin = require('eslint-plugin-eslint-plugin');
7+
const pluginImport = require('eslint-plugin-import');
8+
const pluginN = require('eslint-plugin-n');
9+
const pluginPrettier = require('eslint-plugin-prettier');
10+
const pluginPrettierRecommended = require('eslint-plugin-prettier/recommended');
11+
const globals = require('./src/globals.json');
12+
13+
/** @type {import('eslint').Linter.FlatConfig[]} */
14+
const config = [
15+
{ files: ['**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}'] },
16+
{ ignores: ['.yarn', 'coverage/', 'lib/', 'src/rules/__tests__/fixtures'] },
17+
{
18+
plugins: {
19+
// @ts-expect-error types are currently not considered compatible currently
20+
// todo: suspect this is because of differences in ESLint (types) versions
21+
'@typescript-eslint': pluginTypeScriptESLint,
22+
...pluginEslintCommentsConfigs.recommended.plugins,
23+
import: pluginImport,
24+
'eslint-plugin': pluginESLintPlugin,
25+
n: pluginN,
26+
prettier: pluginPrettier,
27+
},
28+
languageOptions: { parser: parserTypeScriptESLint },
29+
linterOptions: {
30+
reportUnusedDisableDirectives: 'error',
31+
},
32+
rules: {
33+
...pluginESLintPlugin.configs['flat/recommended'].rules,
34+
...pluginEslintCommentsConfigs.recommended.rules,
35+
...pluginPrettierRecommended.rules,
36+
},
37+
},
38+
{
39+
rules: {
40+
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
41+
'@typescript-eslint/no-require-imports': 'error',
42+
'@typescript-eslint/ban-ts-comment': 'error',
43+
'@typescript-eslint/no-empty-object-type': 'error',
44+
'@typescript-eslint/no-unsafe-function-type': 'error',
45+
'@typescript-eslint/no-wrapper-object-types': 'error',
46+
'@typescript-eslint/consistent-type-imports': [
47+
'error',
48+
{ disallowTypeAnnotations: false, fixStyle: 'inline-type-imports' },
49+
],
50+
'@typescript-eslint/no-import-type-side-effects': 'error',
51+
'@typescript-eslint/no-unused-vars': 'error',
52+
'@eslint-community/eslint-comments/no-unused-disable': 'error',
53+
'eslint-plugin/require-meta-docs-description': [
54+
'error',
55+
{ pattern: '^(Enforce|Require|Disallow|Suggest|Prefer)' },
56+
],
57+
'eslint-plugin/test-case-property-ordering': 'error',
58+
'no-else-return': 'error',
59+
'no-negated-condition': 'error',
60+
eqeqeq: ['error', 'smart'],
61+
strict: 'error',
62+
'prefer-template': 'error',
63+
'object-shorthand': [
64+
'error',
65+
'always',
66+
{ avoidExplicitReturnArrows: true },
67+
],
68+
'prefer-destructuring': [
69+
'error',
70+
{ VariableDeclarator: { array: true, object: true } },
71+
],
72+
'sort-imports': ['error', { ignoreDeclarationSort: true }],
73+
'require-unicode-regexp': 'error',
74+
// TS covers these 2
75+
'n/no-missing-import': 'off',
76+
'n/no-missing-require': 'off',
77+
'n/no-unsupported-features/es-syntax': 'off',
78+
'n/no-unsupported-features/es-builtins': 'error',
79+
'import/no-commonjs': 'error',
80+
'import/no-duplicates': 'error',
81+
'import/no-extraneous-dependencies': 'error',
82+
'import/no-unused-modules': 'error',
83+
'import/order': [
84+
'error',
85+
{ alphabetize: { order: 'asc' }, 'newlines-between': 'never' },
86+
],
87+
'padding-line-between-statements': [
88+
'error',
89+
{ blankLine: 'always', prev: '*', next: 'return' },
90+
{ blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
91+
{
92+
blankLine: 'any',
93+
prev: ['const', 'let', 'var'],
94+
next: ['const', 'let', 'var'],
95+
},
96+
{ blankLine: 'always', prev: 'directive', next: '*' },
97+
{ blankLine: 'any', prev: 'directive', next: 'directive' },
98+
],
99+
100+
'prefer-spread': 'error',
101+
'prefer-rest-params': 'error',
102+
'prefer-const': ['error', { destructuring: 'all' }],
103+
'no-var': 'error',
104+
curly: 'error',
105+
},
106+
},
107+
{
108+
files: ['*.js'],
109+
rules: {
110+
'@typescript-eslint/no-require-imports': 'off',
111+
},
112+
},
113+
{
114+
files: ['*.test.js', '*.test.ts'],
115+
languageOptions: { globals },
116+
},
117+
{
118+
files: [
119+
'.eslint-doc-generatorrc.js',
120+
'eslint.config.js',
121+
'babel.config.js',
122+
],
123+
languageOptions: {
124+
sourceType: 'commonjs',
125+
},
126+
rules: {
127+
'@typescript-eslint/no-require-imports': 'off',
128+
'import/no-commonjs': 'off',
129+
},
130+
},
131+
{
132+
files: ['*.d.ts'],
133+
rules: {
134+
strict: 'off',
135+
},
136+
},
137+
];
138+
139+
module.exports = config;

jest.config.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { version as eslintVersion } from 'eslint/package.json';
21
import type { Config } from 'jest';
3-
import * as semver from 'semver';
42

53
const config = {
64
clearMocks: true,
@@ -36,11 +34,4 @@ const config = {
3634
],
3735
} satisfies Config;
3836

39-
if (semver.major(eslintVersion) !== 8) {
40-
// our eslint config only works for v8
41-
config.projects = config.projects.filter(
42-
({ displayName }) => displayName !== 'lint',
43-
);
44-
}
45-
4637
export default config;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"scripts": {
3232
"build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf --glob lib/__tests__ 'lib/**/__tests__'",
3333
"postinstall": "is-ci || husky",
34-
"lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
34+
"lint": "eslint .",
3535
"prepack": "rimraf lib && yarn build",
3636
"prepublishOnly": "pinst --disable",
3737
"prettier:check": "prettier --check 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",

tsconfig.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@
2020
},
2121
"files": [
2222
".eslint-doc-generatorrc.js",
23-
".eslintrc.js",
23+
"eslint.config.js",
2424
"babel.config.js",
2525
"eslint-remote-tester.config.ts",
26-
"jest.config.ts"
26+
"jest.config.ts",
27+
"types.d.ts"
2728
],
2829
"include": ["src/**/*"],
2930
"exclude": ["src/rules/__tests__/fixtures/**/*"]

types.d.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
declare module 'eslint-plugin-eslint-plugin' {
2+
import type * as ESLint from 'eslint';
3+
4+
const plugin: ESLint.ESLint.Plugin & {
5+
configs: {
6+
all: ESLint.Linter.LegacyConfig;
7+
'all-type-checked': ESLint.Linter.LegacyConfig;
8+
recommended: ESLint.Linter.LegacyConfig;
9+
rules: ESLint.Linter.LegacyConfig;
10+
tests: ESLint.Linter.LegacyConfig;
11+
'rules-recommended': ESLint.Linter.LegacyConfig;
12+
'tests-recommended': ESLint.Linter.LegacyConfig;
13+
14+
'flat/all': ESLint.Linter.FlatConfig;
15+
'flat/all-type-checked': ESLint.Linter.FlatConfig;
16+
'flat/recommended': ESLint.Linter.FlatConfig;
17+
'flat/rules': ESLint.Linter.FlatConfig;
18+
'flat/tests': ESLint.Linter.FlatConfig;
19+
'flat/rules-recommended': ESLint.Linter.FlatConfig;
20+
'flat/tests-recommended': ESLint.Linter.FlatConfig;
21+
};
22+
};
23+
export = plugin;
24+
}
25+
26+
// todo: see https://github.com/eslint-community/eslint-plugin-eslint-comments/pull/246
27+
declare module '@eslint-community/eslint-plugin-eslint-comments/configs' {
28+
import type * as ESLint from 'eslint';
29+
30+
const configs: {
31+
recommended: ESLint.Linter.FlatConfig & {
32+
plugins: {
33+
'@eslint-community/eslint-plugin-eslint-comments': ESLint.ESLint.Plugin;
34+
};
35+
};
36+
};
37+
export = configs;
38+
}

0 commit comments

Comments
 (0)