@foray1010/eslint-config 9.1.0 → 10.0.0
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 +35 -0
- package/README.md +85 -41
- package/bases/base.mjs +379 -0
- package/bases/browser.mjs +47 -0
- package/bases/files.mjs +8 -0
- package/bases/ignores.mjs +14 -0
- package/bases/node.mjs +75 -0
- package/bases/prettier.mjs +18 -0
- package/bases/react.mjs +92 -0
- package/{presets/utils/testUtil.cjs → constants.mjs} +3 -4
- package/index.mjs +32 -0
- package/package.json +22 -23
- package/tsconfig.json +1 -1
- package/utils/applyConfig.mjs +61 -0
- package/eslintignore +0 -6
- package/index.cjs +0 -6
- package/presets/base.cjs +0 -360
- package/presets/browser.cjs +0 -22
- package/presets/node.cjs +0 -61
- package/presets/react.cjs +0 -84
- package/react.cjs +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,41 @@
|
|
|
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
|
+
## [10.0.0](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@9.2.0...@foray1010/eslint-config@10.0.0) (2023-03-23)
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
- **eslint-config:** migrate to eslint flat config and mjs
|
|
11
|
+
- require node `^16.14.0 || >=18.12.0`
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- **eslint-config:** migrate to eslint flat config and mjs ([d435d01](https://github.com/foray1010/common-presets/commit/d435d012faf1574dda750917dbada56048eecd09))
|
|
16
|
+
- support ES2021 ([40a0e28](https://github.com/foray1010/common-presets/commit/40a0e282c937825dfca1969c30ffc26e5bd2a27c))
|
|
17
|
+
- **tsconfig:** split tsconfig to mutliple files for different scenarios ([fcaf3ae](https://github.com/foray1010/common-presets/commit/fcaf3aee3f9f1851439d01631c2e8584bde685ba))
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
- **deps:** update dependency eslint-plugin-functional to v5 ([169a5c4](https://github.com/foray1010/common-presets/commit/169a5c4f7f7d10c6d2f5206e71942063f1b710cc))
|
|
22
|
+
- **deps:** update dependency eslint-plugin-unicorn to v46 ([76621eb](https://github.com/foray1010/common-presets/commit/76621eb95fd7eb74fff3710ac739e4d12df1f768))
|
|
23
|
+
- **eslint-config:** migrate eslint-plugin-eslint-comments to eslint-community version ([9a1ce64](https://github.com/foray1010/common-presets/commit/9a1ce646462cffd091d58fbbb39b0a83138f0f3b))
|
|
24
|
+
|
|
25
|
+
### Miscellaneous Chores
|
|
26
|
+
|
|
27
|
+
- require node `^16.14.0 || >=18.12.0` ([5baf6eb](https://github.com/foray1010/common-presets/commit/5baf6eba6d42958596c130724a502c59fe1a4e83))
|
|
28
|
+
|
|
29
|
+
## [9.2.0](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@9.1.0...@foray1010/eslint-config@9.2.0) (2023-02-25)
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
- **eslint-config:** avoid type imports with side effects ([ceda72a](https://github.com/foray1010/common-presets/commit/ceda72a42dab09540fe796cca7c88b82801f073d))
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
- **deps:** update dependency eslint-plugin-jsdoc to v40 ([9d2a01e](https://github.com/foray1010/common-presets/commit/9d2a01e04880e21c2be8dd2e984ec5f01f28fcda))
|
|
38
|
+
- **deps:** update dependency eslint-plugin-simple-import-sort to v10 ([5b258d7](https://github.com/foray1010/common-presets/commit/5b258d70b6c6f344645f983d6f7805edd2ee1908))
|
|
39
|
+
- **deps:** update dependency eslint-plugin-simple-import-sort to v9 ([62d76f2](https://github.com/foray1010/common-presets/commit/62d76f2d2ef83ab5a909d3820a9f16acf387bbfa))
|
|
40
|
+
|
|
6
41
|
## [9.1.0](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@9.0.1...@foray1010/eslint-config@9.1.0) (2022-12-21)
|
|
7
42
|
|
|
8
43
|
### Features
|
package/README.md
CHANGED
|
@@ -20,51 +20,95 @@ Z for looser rules
|
|
|
20
20
|
|
|
21
21
|
1. `yarn add -DE @foray1010/eslint-config eslint prettier`
|
|
22
22
|
|
|
23
|
-
1. Create an
|
|
24
|
-
|
|
25
|
-
For general purpose
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
23
|
+
1. Create an `eslint.config.mjs` in the project root (It is not a standard config path, but we opts for `.mjs` extension to make it compatible with commonjs projects)
|
|
24
|
+
|
|
25
|
+
- For general purpose or Node.js project (support TypeScript)
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import {
|
|
29
|
+
eslintFilesConfig,
|
|
30
|
+
eslintIgnoresConfig,
|
|
31
|
+
eslintNodeConfig,
|
|
32
|
+
} from '@foray1010/eslint-config'
|
|
33
|
+
|
|
34
|
+
const config = [
|
|
35
|
+
...eslintIgnoresConfig,
|
|
36
|
+
...eslintFilesConfig,
|
|
37
|
+
...eslintNodeConfig,
|
|
38
|
+
]
|
|
39
|
+
export default config
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- For general frontend projects (support TypeScript)
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import {
|
|
46
|
+
eslintFilesConfig,
|
|
47
|
+
eslintIgnoresConfig,
|
|
48
|
+
eslintBrowserConfig,
|
|
49
|
+
} from '@foray1010/eslint-config'
|
|
50
|
+
|
|
51
|
+
const config = [
|
|
52
|
+
...eslintIgnoresConfig,
|
|
53
|
+
...eslintFilesConfig,
|
|
54
|
+
...eslintBrowserConfig,
|
|
55
|
+
]
|
|
56
|
+
export default config
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- For frontend React projects (support TypeScript)
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import {
|
|
63
|
+
eslintFilesConfig,
|
|
64
|
+
eslintIgnoresConfig,
|
|
65
|
+
eslintReactConfig,
|
|
66
|
+
} from '@foray1010/eslint-config'
|
|
67
|
+
|
|
68
|
+
const config = [
|
|
69
|
+
...eslintIgnoresConfig,
|
|
70
|
+
...eslintFilesConfig,
|
|
71
|
+
...eslintReactConfig,
|
|
72
|
+
]
|
|
73
|
+
export default config
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- You can apply config per different directories
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import {
|
|
80
|
+
applyConfig,
|
|
81
|
+
eslintFilesConfig,
|
|
82
|
+
eslintIgnoresConfig,
|
|
83
|
+
eslintNodeConfig,
|
|
84
|
+
eslintReactConfig,
|
|
85
|
+
} from '@foray1010/eslint-config'
|
|
86
|
+
|
|
87
|
+
const config = [
|
|
88
|
+
...eslintIgnoresConfig,
|
|
89
|
+
...eslintFilesConfig,
|
|
90
|
+
...applyConfig(
|
|
91
|
+
{
|
|
92
|
+
ignorePrefixes: ['src'],
|
|
93
|
+
},
|
|
94
|
+
eslintNodeConfig,
|
|
95
|
+
),
|
|
96
|
+
...applyConfig(
|
|
97
|
+
{
|
|
98
|
+
filePrefixes: ['src'],
|
|
99
|
+
},
|
|
100
|
+
eslintReactConfig,
|
|
101
|
+
),
|
|
102
|
+
]
|
|
103
|
+
export default config
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
1. Add npm script
|
|
63
107
|
|
|
64
108
|
```json
|
|
65
109
|
{
|
|
66
110
|
"scripts": {
|
|
67
|
-
"eslint": "eslint --
|
|
111
|
+
"eslint": "ESLINT_USE_FLAT_CONFIG=true eslint --config eslint.config.mjs"
|
|
68
112
|
}
|
|
69
113
|
}
|
|
70
114
|
```
|
package/bases/base.mjs
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import eslintPluginEslintComments from '@eslint-community/eslint-plugin-eslint-comments'
|
|
3
|
+
// @ts-expect-error
|
|
4
|
+
import { hasDep, isESM } from '@foray1010/common-presets-utils'
|
|
5
|
+
import eslintPluginTypescriptEslint from '@typescript-eslint/eslint-plugin'
|
|
6
|
+
import typescriptEslintParser from '@typescript-eslint/parser'
|
|
7
|
+
import eslintPluginDeprecation from 'eslint-plugin-deprecation'
|
|
8
|
+
import eslintPluginFunctional from 'eslint-plugin-functional'
|
|
9
|
+
import eslintPluginImport from 'eslint-plugin-import'
|
|
10
|
+
import eslintPluginJest from 'eslint-plugin-jest'
|
|
11
|
+
import eslintPluginSimpleImportSort from 'eslint-plugin-simple-import-sort'
|
|
12
|
+
import eslintPluginUnicorn from 'eslint-plugin-unicorn'
|
|
13
|
+
import globals from 'globals'
|
|
14
|
+
|
|
15
|
+
import { testFileGlobs, typeScriptFileGlobs } from '../constants.mjs'
|
|
16
|
+
|
|
17
|
+
/** @type {import('eslint').Linter.FlatConfig} */
|
|
18
|
+
const cjsConfig = {
|
|
19
|
+
languageOptions: {
|
|
20
|
+
globals: globals.commonjs,
|
|
21
|
+
sourceType: 'script',
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
// commonjs must use strict mode
|
|
25
|
+
strict: ['error', 'global'],
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @type {import('eslint').Linter.FlatConfig} */
|
|
30
|
+
const esmConfig = {
|
|
31
|
+
languageOptions: {
|
|
32
|
+
sourceType: 'module',
|
|
33
|
+
},
|
|
34
|
+
plugins: {
|
|
35
|
+
'simple-import-sort': eslintPluginSimpleImportSort,
|
|
36
|
+
},
|
|
37
|
+
rules: {
|
|
38
|
+
// auto sort export statements
|
|
39
|
+
'simple-import-sort/exports': 'error',
|
|
40
|
+
// auto sort import statements
|
|
41
|
+
'simple-import-sort/imports': 'error',
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @type {readonly import('eslint').Linter.FlatConfig[]} */
|
|
46
|
+
const baseConfig = [
|
|
47
|
+
js.configs.recommended,
|
|
48
|
+
{
|
|
49
|
+
languageOptions: {
|
|
50
|
+
ecmaVersion: 2021,
|
|
51
|
+
globals: {
|
|
52
|
+
// should align with languageOptions.ecmaVersion
|
|
53
|
+
...globals.es2021,
|
|
54
|
+
/* Not using `node` to explicitly import node.js only built-in modules, e.g.
|
|
55
|
+
* import { Buffer } from 'node:buffer'
|
|
56
|
+
* import process from 'node:process'
|
|
57
|
+
*/
|
|
58
|
+
...globals['shared-node-browser'],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
plugins: {
|
|
62
|
+
'@eslint-community/eslint-comments': eslintPluginEslintComments,
|
|
63
|
+
import: eslintPluginImport,
|
|
64
|
+
unicorn: eslintPluginUnicorn,
|
|
65
|
+
},
|
|
66
|
+
rules: {
|
|
67
|
+
...eslintPluginEslintComments.configs['recommended']?.rules,
|
|
68
|
+
...eslintPluginImport.configs['recommended']?.rules,
|
|
69
|
+
// allow disable eslint rules for whole file without re-enable it in the end of the file
|
|
70
|
+
'@eslint-community/eslint-comments/disable-enable-pair': [
|
|
71
|
+
'error',
|
|
72
|
+
{ allowWholeFile: true },
|
|
73
|
+
],
|
|
74
|
+
// make sure every eslint-disable comments are in use
|
|
75
|
+
'@eslint-community/eslint-comments/no-unused-disable': 'error',
|
|
76
|
+
// always use named function for easier to debug via stack trace
|
|
77
|
+
'func-names': ['error', 'as-needed'],
|
|
78
|
+
// this rule doesn't support commonjs, some dependencies are using commonjs
|
|
79
|
+
'import/default': 'off',
|
|
80
|
+
// enforce extensions for both cjs and esm
|
|
81
|
+
'import/extensions': [
|
|
82
|
+
'error',
|
|
83
|
+
// https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_mandatory_file_extensions
|
|
84
|
+
'always',
|
|
85
|
+
{
|
|
86
|
+
pattern: {
|
|
87
|
+
// eslint-plugin-import does not support checking es modules in typescript files
|
|
88
|
+
cts: 'never',
|
|
89
|
+
mts: 'never',
|
|
90
|
+
ts: 'never',
|
|
91
|
+
tsx: 'never',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
// make sure import statements above the others
|
|
96
|
+
'import/first': 'error',
|
|
97
|
+
// separate import statements from the others
|
|
98
|
+
'import/newline-after-import': 'error',
|
|
99
|
+
// avoid anonymous function or class for easier to debug via stack trace
|
|
100
|
+
// for other types, enforcing named data can improve autocomplete when importing
|
|
101
|
+
'import/no-anonymous-default-export': [
|
|
102
|
+
'error',
|
|
103
|
+
{
|
|
104
|
+
allowArray: false,
|
|
105
|
+
allowArrowFunction: false,
|
|
106
|
+
allowAnonymousClass: false,
|
|
107
|
+
allowAnonymousFunction: false,
|
|
108
|
+
allowCallExpression: false,
|
|
109
|
+
allowLiteral: false,
|
|
110
|
+
allowObject: false,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
// no circular dependency
|
|
114
|
+
'import/no-cycle': [
|
|
115
|
+
'error',
|
|
116
|
+
{
|
|
117
|
+
// speed up linting time
|
|
118
|
+
ignoreExternal: true,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
// do not allow import packages that are not listed in dependencies or peerDependencies
|
|
122
|
+
'import/no-extraneous-dependencies': [
|
|
123
|
+
'error',
|
|
124
|
+
{
|
|
125
|
+
devDependencies: [
|
|
126
|
+
'!**/src/**', // allow files outside of src/
|
|
127
|
+
'**/.*', // allow config rc files
|
|
128
|
+
...testFileGlobs,
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
// forbid a module from importing itself
|
|
133
|
+
'import/no-self-import': 'error',
|
|
134
|
+
// use the shortest path in import statement, but allow /index because it will be standard to omit index as default file in directory
|
|
135
|
+
'import/no-useless-path-segments': [
|
|
136
|
+
'error',
|
|
137
|
+
{
|
|
138
|
+
commonjs: true,
|
|
139
|
+
noUselessIndex: false,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
// prefer explicitly convert type for readability
|
|
143
|
+
'no-implicit-coercion': 'error',
|
|
144
|
+
// make sure private class members are in-use
|
|
145
|
+
'no-unused-private-class-members': 'error',
|
|
146
|
+
// avoid assigning anonymous function to object key which is harder to trace when debug
|
|
147
|
+
'object-shorthand': ['error', 'always'],
|
|
148
|
+
// prefer `const` when the variable won't be reassigned
|
|
149
|
+
'prefer-const': [
|
|
150
|
+
'error',
|
|
151
|
+
{
|
|
152
|
+
// if one of the variables will be reassigned, do not enforce `const`
|
|
153
|
+
destructuring: 'all',
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
// use with `unicorn/throw-new-error`
|
|
157
|
+
// disallow builtins to be created without `new` operator, to be consistent with es6 class syntax
|
|
158
|
+
'unicorn/new-for-builtins': 'error',
|
|
159
|
+
// prefer `import from 'node:xxx'`
|
|
160
|
+
'unicorn/prefer-node-protocol': 'error',
|
|
161
|
+
// prefer Number static properties over global ones
|
|
162
|
+
'unicorn/prefer-number-properties': 'error',
|
|
163
|
+
// use with `unicorn/new-for-builtins`
|
|
164
|
+
'unicorn/throw-new-error': 'error',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
files: ['**/*.js'],
|
|
169
|
+
...(isESM() ? esmConfig : cjsConfig),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
files: ['**/*.cjs'],
|
|
173
|
+
...cjsConfig,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
files: ['**/*.mjs'],
|
|
177
|
+
...esmConfig,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
files: testFileGlobs,
|
|
181
|
+
languageOptions: {
|
|
182
|
+
globals: globals.jest,
|
|
183
|
+
},
|
|
184
|
+
plugins: {
|
|
185
|
+
jest: eslintPluginJest,
|
|
186
|
+
},
|
|
187
|
+
rules: {
|
|
188
|
+
...eslintPluginJest.configs['recommended']?.rules,
|
|
189
|
+
...eslintPluginJest.configs['style']?.rules,
|
|
190
|
+
// make sure lifecycle hooks on the top for readability
|
|
191
|
+
'jest/prefer-hooks-on-top': 'error',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
// typescript plugins are depended on `typescript` package
|
|
195
|
+
// @ts-expect-error
|
|
196
|
+
...(hasDep('typescript')
|
|
197
|
+
? [
|
|
198
|
+
{
|
|
199
|
+
files: typeScriptFileGlobs,
|
|
200
|
+
languageOptions: {
|
|
201
|
+
/** @type {any} */
|
|
202
|
+
parser: typescriptEslintParser,
|
|
203
|
+
parserOptions: {
|
|
204
|
+
// faster linting on cli
|
|
205
|
+
// https://github.com/typescript-eslint/typescript-eslint/issues/3528
|
|
206
|
+
// turned off because @typescript-eslint/no-unsafe-* rules will output wrong errors
|
|
207
|
+
// allowAutomaticSingleRunInference: true,
|
|
208
|
+
project: ['./tsconfig*.json', './packages/*/tsconfig*.json'],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
settings: {
|
|
212
|
+
'import/resolver': {
|
|
213
|
+
typescript: true,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
plugins: {
|
|
217
|
+
'@typescript-eslint': eslintPluginTypescriptEslint,
|
|
218
|
+
deprecation: eslintPluginDeprecation,
|
|
219
|
+
functional: eslintPluginFunctional,
|
|
220
|
+
},
|
|
221
|
+
rules: {
|
|
222
|
+
...eslintPluginTypescriptEslint.configs['eslint-recommended']
|
|
223
|
+
?.rules,
|
|
224
|
+
...eslintPluginTypescriptEslint.configs['recommended']?.rules,
|
|
225
|
+
...eslintPluginTypescriptEslint.configs[
|
|
226
|
+
'recommended-requiring-type-checking'
|
|
227
|
+
]?.rules,
|
|
228
|
+
...eslintPluginImport.configs['typescript']?.rules,
|
|
229
|
+
// extend existing rule
|
|
230
|
+
'@typescript-eslint/ban-types': [
|
|
231
|
+
'error',
|
|
232
|
+
{
|
|
233
|
+
types: {
|
|
234
|
+
// TypeScript team suggests to use `<T extends {}>` https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to
|
|
235
|
+
'{}': false,
|
|
236
|
+
},
|
|
237
|
+
extendDefaults: true,
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
// separate type exports which allow certain optimizations within compilers
|
|
241
|
+
'@typescript-eslint/consistent-type-exports': 'error',
|
|
242
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
243
|
+
'error',
|
|
244
|
+
{
|
|
245
|
+
// separate type imports which allow certain optimizations within compilers
|
|
246
|
+
prefer: 'type-imports',
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
// disable the base rule as it can report incorrect errors, use @typescript-eslint/dot-notation instead
|
|
250
|
+
'dot-notation': 'off',
|
|
251
|
+
// only allow indexed syntax (e.g. `obj['key']`) for accessing undefined fields
|
|
252
|
+
'@typescript-eslint/dot-notation': [
|
|
253
|
+
'error',
|
|
254
|
+
{
|
|
255
|
+
allowIndexSignaturePropertyAccess: true,
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
// encourage to use private accessibility modifier
|
|
259
|
+
'@typescript-eslint/explicit-member-accessibility': [
|
|
260
|
+
'error',
|
|
261
|
+
{
|
|
262
|
+
accessibility: 'explicit',
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
// sometimes auto detect can provide a better and narrower type
|
|
266
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
267
|
+
// disallow duplicated value in enum as it is error-prone
|
|
268
|
+
'@typescript-eslint/no-duplicate-enum-values': 'error',
|
|
269
|
+
// need empty function for react context default value
|
|
270
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
271
|
+
// encourage to check error type before use in catch clauses
|
|
272
|
+
'@typescript-eslint/no-implicit-any-catch': 'error',
|
|
273
|
+
// when using typescript 5.0 with verbatimModuleSyntax flag on, compiler will not remove import statements with only inline type imports which lead to side effects
|
|
274
|
+
'@typescript-eslint/no-import-type-side-effects': 'error',
|
|
275
|
+
// enforce correct usage of `void` type
|
|
276
|
+
'@typescript-eslint/no-invalid-void-type': 'error',
|
|
277
|
+
// allow using async function as event handler in frontend
|
|
278
|
+
'@typescript-eslint/no-misused-promises': [
|
|
279
|
+
'error',
|
|
280
|
+
{ checksVoidReturn: false },
|
|
281
|
+
],
|
|
282
|
+
// declaration merging between classes and interfaces is unsafe
|
|
283
|
+
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
|
|
284
|
+
// do not block functions referring to other functions
|
|
285
|
+
'@typescript-eslint/no-use-before-define': [
|
|
286
|
+
'error',
|
|
287
|
+
{
|
|
288
|
+
/* options from eslint/no-use-before-define */
|
|
289
|
+
// allow use function before defined as they could be hoisted
|
|
290
|
+
functions: false,
|
|
291
|
+
classes: true,
|
|
292
|
+
variables: true,
|
|
293
|
+
|
|
294
|
+
/* options from @typescript-eslint/no-use-before-define */
|
|
295
|
+
enums: true,
|
|
296
|
+
// confusing option, it will disable `typedefs`
|
|
297
|
+
ignoreTypeReferences: false,
|
|
298
|
+
// tsc allows types to be used before define
|
|
299
|
+
typedefs: false,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
// use with functional/prefer-readonly-type
|
|
303
|
+
// mark class variables as readonly if it is not mutated
|
|
304
|
+
'@typescript-eslint/prefer-readonly': 'error',
|
|
305
|
+
// make sure functions which return a promise will just return a rejected promise instead of throwing an error
|
|
306
|
+
'@typescript-eslint/promise-function-async': 'error',
|
|
307
|
+
// allow primitive value in template string
|
|
308
|
+
'@typescript-eslint/restrict-template-expressions': [
|
|
309
|
+
'error',
|
|
310
|
+
{
|
|
311
|
+
allowNumber: true,
|
|
312
|
+
allowBoolean: true,
|
|
313
|
+
allowAny: true, // mistakenly recognize string as any in 4.29.3
|
|
314
|
+
allowNullish: true,
|
|
315
|
+
allowRegExp: true,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
// avoid missed switch-case by requiring switch-case statements to be exhaustive with union type
|
|
319
|
+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
320
|
+
// ignore static function as those are not supposed to use `this`
|
|
321
|
+
'@typescript-eslint/unbound-method': [
|
|
322
|
+
'error',
|
|
323
|
+
{ ignoreStatic: true },
|
|
324
|
+
],
|
|
325
|
+
// do not allow usage of deprecated code
|
|
326
|
+
'deprecation/deprecation': 'error',
|
|
327
|
+
// use with @typescript-eslint/prefer-readonly
|
|
328
|
+
'functional/prefer-readonly-type': [
|
|
329
|
+
'error',
|
|
330
|
+
{
|
|
331
|
+
// sometimes it is easier to mutate, it should be fine to mutate within local scope
|
|
332
|
+
allowLocalMutation: true,
|
|
333
|
+
// don't force library consumer to use readonly type
|
|
334
|
+
allowMutableReturnType: true,
|
|
335
|
+
// allow mutating class variables
|
|
336
|
+
ignoreClass: 'fieldsOnly',
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
// forbid unnecessary callback wrapper
|
|
340
|
+
'functional/prefer-tacit': 'error',
|
|
341
|
+
'no-restricted-syntax': [
|
|
342
|
+
'error',
|
|
343
|
+
{
|
|
344
|
+
// encourage to use JS standard #private over TS private accessibility modifier, but excluding constructor because it cannot be private in JS: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields#description
|
|
345
|
+
selector:
|
|
346
|
+
':matches(PropertyDefinition, MethodDefinition, TSParameterProperty)[accessibility="private"]:not([kind="constructor"])',
|
|
347
|
+
message:
|
|
348
|
+
'Use #private instead (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields)',
|
|
349
|
+
},
|
|
350
|
+
],
|
|
351
|
+
// @typescript-eslint/eslint-plugin suggests to disable it: https://github.com/typescript-eslint/typescript-eslint/blob/2588e9ea55f78352fdd6ae92a306135aabb49a1a/docs/linting/TROUBLESHOOTING.md#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
|
352
|
+
// 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
|
|
353
|
+
'no-undef': 'error',
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
files: typeScriptFileGlobs,
|
|
358
|
+
ignores: testFileGlobs.map((glob) => `!${glob}`),
|
|
359
|
+
plugins: {
|
|
360
|
+
'@typescript-eslint': eslintPluginTypescriptEslint,
|
|
361
|
+
jest: eslintPluginJest,
|
|
362
|
+
},
|
|
363
|
+
rules: {
|
|
364
|
+
// doesn't work with jest.fn<void>()
|
|
365
|
+
'@typescript-eslint/no-invalid-void-type': 'off',
|
|
366
|
+
// replace by jest/unbound-method
|
|
367
|
+
'@typescript-eslint/unbound-method': 'off',
|
|
368
|
+
// allow passing an unbound method to `expect` calls
|
|
369
|
+
'jest/unbound-method': ['error', { ignoreStatic: true }],
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
files: typeScriptFileGlobs,
|
|
374
|
+
...esmConfig,
|
|
375
|
+
},
|
|
376
|
+
]
|
|
377
|
+
: []),
|
|
378
|
+
]
|
|
379
|
+
export default baseConfig
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import restrictedGlobals from 'confusing-browser-globals'
|
|
2
|
+
import eslintPluginCompat from 'eslint-plugin-compat'
|
|
3
|
+
import eslintPluginImport from 'eslint-plugin-import'
|
|
4
|
+
import eslintPluginJestDom from 'eslint-plugin-jest-dom'
|
|
5
|
+
import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'
|
|
6
|
+
import globals from 'globals'
|
|
7
|
+
|
|
8
|
+
import { testFileGlobs } from '../constants.mjs'
|
|
9
|
+
|
|
10
|
+
/** @type {import('eslint').Linter.FlatConfig[]} */
|
|
11
|
+
const browserConfig = [
|
|
12
|
+
{
|
|
13
|
+
languageOptions: {
|
|
14
|
+
globals: {
|
|
15
|
+
...globals.browser,
|
|
16
|
+
...globals.webextensions,
|
|
17
|
+
// keep it until webpack has an official way to define env: https://github.com/webpack/webpack/issues/15833
|
|
18
|
+
// @ts-expect-error
|
|
19
|
+
process: 'readonly',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
plugins: {
|
|
23
|
+
compat: eslintPluginCompat,
|
|
24
|
+
import: eslintPluginImport,
|
|
25
|
+
},
|
|
26
|
+
rules: {
|
|
27
|
+
'compat/compat': 'error',
|
|
28
|
+
// frontend environment doesn't support node.js modules
|
|
29
|
+
'import/no-nodejs-modules': 'error',
|
|
30
|
+
'no-restricted-globals': ['error', ...restrictedGlobals],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
files: testFileGlobs,
|
|
35
|
+
plugins: {
|
|
36
|
+
'jest-dom': eslintPluginJestDom,
|
|
37
|
+
'testing-library': eslintPluginTestingLibrary,
|
|
38
|
+
},
|
|
39
|
+
rules: {
|
|
40
|
+
...eslintPluginJestDom.configs['recommended']?.rules,
|
|
41
|
+
...eslintPluginTestingLibrary.configs['dom']?.rules,
|
|
42
|
+
// allow to use nodejs modules in tests
|
|
43
|
+
'import/no-nodejs-modules': 'off',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
]
|
|
47
|
+
export default browserConfig
|
package/bases/files.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @type {readonly import('eslint').Linter.FlatConfig[]} */
|
|
2
|
+
const ignoresConfig = [
|
|
3
|
+
{
|
|
4
|
+
// replace `.eslintignore`
|
|
5
|
+
ignores: [
|
|
6
|
+
'**/.yarn/**',
|
|
7
|
+
'**/build/**',
|
|
8
|
+
'**/coverage/**',
|
|
9
|
+
'**/dist/**',
|
|
10
|
+
'**/node_modules/**',
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
]
|
|
14
|
+
export default ignoresConfig
|