@lidofinance/eslint-config 0.0.1 → 0.11.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/.eslintrc.js ADDED
@@ -0,0 +1,14 @@
1
+ const buildConfig = require("./lib/build-config");
2
+ const rulesets = require("./rulesets/hard");
3
+
4
+ const { plugins, rules, ...base } = buildConfig({}, rulesets);
5
+
6
+ module.exports = {
7
+ root: true,
8
+ ...base,
9
+ plugins: [...plugins, "prettier"],
10
+ rules: {
11
+ ...rules,
12
+ "prettier/prettier": "error",
13
+ },
14
+ };
package/README.md CHANGED
@@ -1,10 +1,64 @@
1
- This is pre-release stage software for evaluation purposes; full release will come soon.
1
+ # Lido ESint config
2
+ Automated, non-opinionated ESLint config foundation
3
+ >
4
+ >❗ _Please note that this ESLint config is still 0.x and is subject to significant changes; it is mainly used by internal Lido teams._
2
5
 
3
- Please, do not use it unless you specifically know what you are doing.
4
6
 
5
- ---
7
+ ### Installation
8
+ ```bash
9
+ npm install --dev @lidofinance/eslint-config
10
+ # and plugins
11
+ npm install --dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-typescript eslint-plugin-eslint-comments eslint-plugin-import eslint-plugin-jest eslint-plugin-promise eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-sonarjs eslint-plugin-unicorn @next/eslint-plugin-next
12
+ ```
6
13
 
7
- Behavior changes are dependent upon:
14
+ If using TypeScript, alter `tsconfig.json` line `includes` to include everything, like that:
15
+ `"include": ["**/*","**/.*"]`
8
16
 
9
- - presence of React, Jest, Next.js, Typescript in dependencies/devDependencies
10
- - Typescript `strict` flag in tsconfig
17
+ > ℹ️ Modern module resolution [ESLint patch](https://www.npmjs.com/package/@rushstack/eslint-patch) by Rush team is intentionally not used, as it conflicts with same patch in `@next/eslint-plugin`.
18
+
19
+ ### Configuration
20
+ Style rules are intentionally not provided; bring your own code style, whatever it is - prettier, airbnb, xo or standard.
21
+
22
+ ```json5
23
+ // .eslintrc.js.js
24
+ {
25
+ "root": true,
26
+
27
+ "extends": [
28
+ // note: use every other config BEFORE @lidofinance config,
29
+ // EXCEPT prettier; prettier is bundled with multiple
30
+ // disable rules that should be turned off to avoid conflicts
31
+
32
+ //"airbnb",
33
+ "@lidofinance",
34
+ //"prettier"
35
+ ]
36
+ }
37
+ ```
38
+
39
+ ### What's inside
40
+
41
+ `@lidofinance/eslint-config` is feature-packed config that ships with some logic.
42
+
43
+ Following assumptions are done:
44
+ - ES version target is latest (2022); if you need other, change `env` in `.eslintrc`
45
+ - code is always server-ready
46
+ - code is client-ready if `react` package is present
47
+ - there is no magic resolution mechanism and usage of webpack loaders; only explicit file paths and `tsconfig.json` `paths` are considered
48
+ - latest version of TypeScript (4.6.x) and ESLint (^8.13) are used
49
+
50
+ For performance, developer experience and accuracy reasons some rules will turn on if following conditions will happen:
51
+
52
+ - `React` package is declared in `package.json`
53
+ - `react`, `react-hooks` rules will be used
54
+ - `Next` package is declared in `package.json`
55
+ - `next` plugin rules will be used
56
+ - react rule `react/react-in-jsx-scope` will turn off
57
+ - `Jest` package is declared in `package.json`
58
+ - `jest` plugin rules will be used
59
+ - some rules will be disabled (like "avoid code duplication" and "do not use any") for test-specific file patterns
60
+ - `Typescript` package is declared in `package.json`:
61
+ - `typescript-eslint` rules will be enabled
62
+ - parser will be switched to typescript-eslint
63
+ - if `tsconfig.json` is present, type-level lint rules will be enabled
64
+ - if `compilerOptions.strict` is `true`, additional anti-any rules will be enabled
package/all-hard.js CHANGED
@@ -1,12 +1,12 @@
1
- const buildConfig = require('./lib/build-config')
2
- const rulesets = require('./rulesets/hard')
1
+ const buildConfig = require("./lib/build-config");
2
+ const rulesets = require("./rulesets/hard");
3
3
 
4
4
  module.exports = buildConfig(
5
- {
6
- typescript: true,
7
- react: true,
8
- next: true,
9
- jest: true,
10
- },
11
- rulesets
12
- )
5
+ {
6
+ typescript: true,
7
+ react: true,
8
+ next: true,
9
+ jest: true,
10
+ },
11
+ rulesets
12
+ );
package/all.js CHANGED
@@ -1,12 +1,12 @@
1
- const buildConfig = require('./lib/build-config')
2
- const rulesets = require('./rulesets/easy')
1
+ const buildConfig = require("./lib/build-config");
2
+ const rulesets = require("./rulesets/easy");
3
3
 
4
4
  module.exports = buildConfig(
5
- {
6
- typescript: true,
7
- react: true,
8
- next: true,
9
- jest: true,
10
- },
11
- rulesets
12
- )
5
+ {
6
+ typescript: true,
7
+ react: true,
8
+ next: true,
9
+ jest: true,
10
+ },
11
+ rulesets
12
+ );
package/auto-hard.js CHANGED
@@ -1,5 +1,5 @@
1
- const buildConfig = require('./lib/build-config')
2
- const rulesets = require('./rulesets/hard')
3
- const env = require('./lib/env')
1
+ const buildConfig = require("./lib/build-config");
2
+ const rulesets = require("./rulesets/hard");
3
+ const env = require("./lib/env");
4
4
 
5
- module.exports = buildConfig(env, rulesets)
5
+ module.exports = buildConfig(env, rulesets);
package/auto.js CHANGED
@@ -1,5 +1,5 @@
1
- const buildConfig = require('./lib/build-config')
2
- const rulesets = require('./rulesets/easy')
3
- const env = require('./lib/env')
1
+ const buildConfig = require("./lib/build-config");
2
+ const rulesets = require("./rulesets/easy");
3
+ const env = require("./lib/env");
4
4
 
5
- module.exports = buildConfig(env, rulesets)
5
+ module.exports = buildConfig(env, rulesets);
@@ -1,212 +1,229 @@
1
- const ts = require('typescript')
1
+ const ts = require("typescript");
2
2
 
3
3
  const generalLoosenRules = {
4
- 'unicorn/consistent-function-scoping': 'off',
5
- 'unicorn/error-message': 'off',
6
- 'sonarjs/no-identical-conditions': 'off',
7
- 'sonarjs/no-identical-expressions': 'off',
8
- 'sonarjs/no-identical-functions': 'off',
9
- }
4
+ "unicorn/consistent-function-scoping": "off",
5
+ "unicorn/error-message": "off",
6
+ "sonarjs/no-identical-conditions": "off",
7
+ "sonarjs/no-identical-expressions": "off",
8
+ "sonarjs/no-identical-functions": "off",
9
+ };
10
+
10
11
  const loosenTsRules = {
11
- '@typescript-eslint/no-unsafe-argument': 'off',
12
- '@typescript-eslint/no-unsafe-assignment': 'off',
13
- '@typescript-eslint/no-unsafe-call': 'off',
14
- '@typescript-eslint/no-unsafe-member-access': 'off',
15
- '@typescript-eslint/no-unsafe-return': 'off',
16
- '@typescript-eslint/require-await': 'off',
17
- '@typescript-eslint/await-thenable': 'off',
18
- '@typescript-eslint/no-explicit-any': 'off',
19
- }
12
+ "@typescript-eslint/no-unsafe-argument": "off",
13
+ "@typescript-eslint/no-unsafe-assignment": "off",
14
+ "@typescript-eslint/no-unsafe-call": "off",
15
+ "@typescript-eslint/no-unsafe-member-access": "off",
16
+ "@typescript-eslint/no-unsafe-return": "off",
17
+ "@typescript-eslint/require-await": "off",
18
+ "@typescript-eslint/await-thenable": "off",
19
+ "@typescript-eslint/no-explicit-any": "off",
20
+ "@typescript-eslint/restrict-plus-operands": "off",
21
+ "@typescript-eslint/restrict-template-expressions": "off",
22
+ };
23
+
20
24
  const loosenReactRules = {
21
- // loosen some rules
22
- 'react/prop-types': 'off',
23
- 'react/react-in-jsx-scope': 'off',
24
- }
25
+ // loosen some rules
26
+ "react/prop-types": "off",
27
+ "react/react-in-jsx-scope": "off",
28
+ };
25
29
 
26
- module.exports = function buildConfig(env, { nextRules, tsRules, reactRules, defaultRules }) {
27
- const config = {
28
- extends: ['eslint:recommended'],
29
- env: {
30
- es2022: true,
31
- browser: env.react,
32
- node: true,
33
- },
34
- // future: add @brettz9, css-modules, eslint-comments plugins
35
- plugins: ['sonarjs', 'unicorn', 'import', 'promise'],
36
- settings: {
37
- 'import/resolver': {
38
- [require.resolve('eslint-import-resolver-node')]: {
39
- extensions: ['.js', '.jsx'],
40
- },
41
- },
30
+ module.exports = function buildConfig(
31
+ env,
32
+ { nextRules, tsRules, reactRules, defaultRules }
33
+ ) {
34
+ const config = {
35
+ extends: ["eslint:recommended"],
36
+ env: {
37
+ es2022: true,
38
+ browser: env.react,
39
+ node: true,
40
+ },
41
+ // future: add @brettz9, css-modules, eslint-comments plugins
42
+ plugins: ["sonarjs", "unicorn", "import", "promise"],
43
+ settings: {
44
+ "import/resolver": {
45
+ [require.resolve("eslint-import-resolver-node")]: {
46
+ extensions: [".js", ".jsx"],
42
47
  },
43
- rules: defaultRules,
44
- overrides: [],
45
- }
48
+ },
49
+ },
50
+ rules: defaultRules,
51
+ overrides: [],
52
+ };
46
53
 
47
- const loosenRules = {
48
- ...generalLoosenRules,
49
- ...(env.react ? loosenReactRules : {}),
50
- ...(env.typescript ? loosenTsRules : {}),
51
- }
54
+ const loosenRules = {
55
+ ...generalLoosenRules,
56
+ ...(env.react ? loosenReactRules : {}),
57
+ ...(env.typescript ? loosenTsRules : {}),
58
+ };
52
59
 
53
- if (env.react) {
54
- Object.assign(config, {
55
- plugins: [...config.plugins, 'react', 'react-hooks'],
56
- rules: {
57
- ...config.rules,
58
- ...reactRules,
59
- },
60
- settings: {
61
- ...config.settings,
62
- react: {
63
- version: 'detect',
64
- },
65
- },
66
- overrides: [
67
- ...config.overrides,
68
- {
69
- files: ['*.stories.*', '*.test.*'],
70
- rules: loosenRules,
71
- },
72
- ],
73
- })
74
- }
75
-
76
- if (env.next) {
77
- Object.assign(config, {
78
- plugins: [...config.plugins, '@next/next'],
79
- rules: {
80
- ...config.rules,
81
- ...nextRules,
82
- },
83
- })
84
- }
60
+ if (env.react) {
61
+ Object.assign(config, {
62
+ plugins: [...config.plugins, "react", "react-hooks"],
63
+ rules: {
64
+ ...config.rules,
65
+ ...reactRules,
66
+ },
67
+ settings: {
68
+ ...config.settings,
69
+ react: {
70
+ version: "detect",
71
+ },
72
+ },
73
+ overrides: [
74
+ ...config.overrides,
75
+ {
76
+ files: ["*.stories.*", "*.test.*"],
77
+ rules: loosenRules,
78
+ },
79
+ ],
80
+ });
81
+ }
85
82
 
86
- // order is important here
87
- if (env.jest) {
88
- Object.assign(config, {
89
- plugins: [...config.plugins, 'jest'],
90
- overrides: [
91
- ...config.overrides,
92
- {
93
- extends: ['plugin:jest/recommended'],
94
- files: ['__test__/**', 'test/**', '*.spec.*'],
95
- env: {
96
- 'jest/globals': true,
97
- },
98
- rules: {
99
- ...loosenRules,
100
- // sometimes there are problems with version detection causing this rule to crash ESLint
101
- 'jest/no-deprecated-functions': 'off',
102
- },
103
- },
104
- ],
105
- })
106
- }
83
+ if (env.next) {
84
+ Object.assign(config, {
85
+ plugins: [...config.plugins, "@next/next"],
86
+ rules: {
87
+ ...config.rules,
88
+ ...nextRules,
89
+ },
90
+ });
91
+ }
107
92
 
108
- if (env.typescript) {
109
- let tsconfigPath
93
+ // order is important here
94
+ if (env.jest) {
95
+ Object.assign(config, {
96
+ plugins: [...config.plugins, "jest"],
97
+ overrides: [
98
+ ...config.overrides,
99
+ {
100
+ extends: ["plugin:jest/recommended"],
101
+ files: ["__test__/**", "test/**", "*.spec.*", "*.test.js"],
102
+ env: {
103
+ "jest/globals": true,
104
+ },
105
+ rules: {
106
+ ...loosenRules,
107
+ // sometimes there are problems with version detection causing this rule to crash ESLint
108
+ "jest/no-deprecated-functions": "off",
109
+ },
110
+ },
111
+ ],
112
+ });
113
+ }
110
114
 
111
- try {
112
- // eslint-disable-next-line @typescript-eslint/unbound-method
113
- tsconfigPath = ts.findConfigFile(process.cwd(), ts.sys.fileExists, 'tsconfig.json')
114
- // eslint-disable-next-line @typescript-eslint/unbound-method
115
- const { config } = ts.readConfigFile(tsconfigPath, ts.sys.readFile)
116
- if (config) {
117
- // this are type-aware checks that require tsconfig presence
118
- Object.assign(tsRules, {
119
- '@typescript-eslint/await-thenable': 'warn',
120
- '@typescript-eslint/no-floating-promises': 'error',
121
- 'no-implied-eval': 'off',
122
- '@typescript-eslint/no-implied-eval': 'error',
123
- '@typescript-eslint/no-misused-promises': 'warn',
124
- '@typescript-eslint/no-unnecessary-type-assertion': 'warn',
125
- 'require-await': 'off',
126
- '@typescript-eslint/require-await': 'error',
127
- '@typescript-eslint/unbound-method': ['error', { ignoreStatic: true }],
128
- })
129
- }
130
- if (config?.compilerOptions?.strict) {
131
- Object.assign(tsRules, {
132
- '@typescript-eslint/restrict-plus-operands': 'warn',
133
- '@typescript-eslint/no-explicit-any': 'error',
134
- '@typescript-eslint/no-unsafe-argument': 'error',
135
- '@typescript-eslint/no-unsafe-assignment': 'error',
136
- '@typescript-eslint/no-unsafe-call': 'error',
137
- '@typescript-eslint/no-unsafe-member-access': 'error',
138
- '@typescript-eslint/no-unsafe-return': 'error',
139
- '@typescript-eslint/restrict-template-expressions': 'error',
140
- })
141
- }
142
- } catch {
143
- void 0
144
- }
115
+ if (env.typescript) {
116
+ let tsconfigPath;
145
117
 
146
- Object.assign(config, {
147
- plugins: [...config.plugins, '@typescript-eslint'],
148
- parser: '@typescript-eslint/parser',
149
- parserOptions: {
150
- sourceType: 'module',
151
- project: tsconfigPath,
152
- ecmaFeatures: {
153
- jsx: env.react,
154
- },
155
- warnOnUnsupportedTypeScriptVersion: true,
156
- },
157
- settings: {
158
- ...config.settings,
159
- 'import/resolver': {
160
- ...config.settings['import/resolver'],
161
- [require.resolve('eslint-import-resolver-typescript')]: {
162
- alwaysTryTypes: true,
163
- },
164
- },
165
- },
166
- rules: {
167
- ...config.rules,
168
- ...tsRules,
169
- },
170
- overrides: [
171
- ...config.overrides,
172
- // ESLint can only apply one override per file, and takes first one matched,
173
- // so multiple overrides should be combined.
174
- // order is important.
175
- {
176
- files: ['*.stories.ts', '*.stories.tsx', '*.stories.mts', '*.stories.cts'],
177
- rules: {
178
- ...loosenRules,
179
- },
180
- },
181
- {
182
- files: [
183
- '*.test.ts',
184
- '*.test.tsx',
185
- '*.test.mts',
186
- '*.test.cts',
187
- '__test__/**/*.ts',
188
- '__test__/**/*.tsx',
189
- '__test__/**/*.mts',
190
- '__test__/**/*.cts',
191
- ],
192
- extends: ['plugin:jest/recommended'],
193
- env: {
194
- 'jest/globals': true,
195
- },
196
- rules: {
197
- ...loosenRules,
198
- 'jest/no-deprecated-functions': 'off',
199
- },
200
- },
201
- {
202
- files: ['*.ts', '*.tsx', '*.mts', '*.cts'],
203
- rules: {
204
- ...tsRules,
205
- },
206
- },
207
- ],
208
- })
118
+ try {
119
+ tsconfigPath = ts.findConfigFile(
120
+ process.cwd(),
121
+ ts.sys.fileExists,
122
+ "tsconfig.json"
123
+ );
124
+ const tsConfigFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
125
+ if (tsConfigFile.config) {
126
+ // this are type-aware checks that require tsconfig presence
127
+ Object.assign(tsRules, {
128
+ "@typescript-eslint/await-thenable": "warn",
129
+ "@typescript-eslint/no-floating-promises": "error",
130
+ "no-implied-eval": "off",
131
+ "@typescript-eslint/no-implied-eval": "error",
132
+ "@typescript-eslint/no-misused-promises": "warn",
133
+ "@typescript-eslint/no-unnecessary-type-assertion": "warn",
134
+ "require-await": "off",
135
+ "@typescript-eslint/require-await": "error",
136
+ "@typescript-eslint/unbound-method": [
137
+ "error",
138
+ { ignoreStatic: true },
139
+ ],
140
+ });
141
+ }
142
+ if (config?.compilerOptions?.strict) {
143
+ Object.assign(tsRules, {
144
+ "@typescript-eslint/restrict-plus-operands": "warn",
145
+ "@typescript-eslint/no-explicit-any": "error",
146
+ "@typescript-eslint/no-unsafe-argument": "error",
147
+ "@typescript-eslint/no-unsafe-assignment": "error",
148
+ "@typescript-eslint/no-unsafe-call": "error",
149
+ "@typescript-eslint/no-unsafe-member-access": "error",
150
+ "@typescript-eslint/no-unsafe-return": "error",
151
+ "@typescript-eslint/restrict-template-expressions": "error",
152
+ });
153
+ }
154
+ } catch {
155
+ void 0;
209
156
  }
210
157
 
211
- return config
212
- }
158
+ Object.assign(config, {
159
+ plugins: [...config.plugins, "@typescript-eslint"],
160
+ parser: "@typescript-eslint/parser",
161
+ parserOptions: {
162
+ sourceType: "module",
163
+ project: tsconfigPath,
164
+ ecmaFeatures: {
165
+ jsx: env.react,
166
+ },
167
+ warnOnUnsupportedTypeScriptVersion: true,
168
+ },
169
+ settings: {
170
+ ...config.settings,
171
+ "import/resolver": {
172
+ ...config.settings["import/resolver"],
173
+ [require.resolve("eslint-import-resolver-typescript")]: {
174
+ alwaysTryTypes: true,
175
+ },
176
+ },
177
+ },
178
+ rules: {
179
+ ...config.rules,
180
+ ...tsRules,
181
+ },
182
+ overrides: [
183
+ ...config.overrides,
184
+ // ESLint can only apply one override per file, and takes first one matched,
185
+ // so multiple overrides should be combined.
186
+ // order is important.
187
+ {
188
+ files: [
189
+ "*.stories.ts",
190
+ "*.stories.tsx",
191
+ "*.stories.mts",
192
+ "*.stories.cts",
193
+ ],
194
+ rules: {
195
+ ...loosenRules,
196
+ },
197
+ },
198
+ {
199
+ files: [
200
+ "*.test.ts",
201
+ "*.test.tsx",
202
+ "*.test.mts",
203
+ "*.test.cts",
204
+ "__test__/**/*.ts",
205
+ "__test__/**/*.tsx",
206
+ "__test__/**/*.mts",
207
+ "__test__/**/*.cts",
208
+ ],
209
+ extends: ["plugin:jest/recommended"],
210
+ env: {
211
+ "jest/globals": true,
212
+ },
213
+ rules: {
214
+ ...loosenRules,
215
+ "jest/no-deprecated-functions": "off",
216
+ },
217
+ },
218
+ {
219
+ files: ["*.ts", "*.tsx", "*.mts", "*.cts"],
220
+ rules: {
221
+ ...tsRules,
222
+ },
223
+ },
224
+ ],
225
+ });
226
+ }
227
+
228
+ return config;
229
+ };