@foray1010/eslint-config 10.0.1 → 10.0.3

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 CHANGED
@@ -3,6 +3,18 @@
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.3](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@10.0.2...@foray1010/eslint-config@10.0.3) (2023-03-23)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **eslint-config:** errors when using in project without typescript ([d357595](https://github.com/foray1010/common-presets/commit/d3575954b9dac1290c77ff23ece9ce3e7c8fcc2f))
11
+
12
+ ## [10.0.2](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@10.0.1...@foray1010/eslint-config@10.0.2) (2023-03-23)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **eslint-config:** disable some eslint-plugin-import rules due to not support flat config ([3a84a7d](https://github.com/foray1010/common-presets/commit/3a84a7d10e0bdd8b81ce115ad509e46eee2330c5))
17
+
6
18
  ## [10.0.1](https://github.com/foray1010/common-presets/compare/@foray1010/eslint-config@10.0.0...@foray1010/eslint-config@10.0.1) (2023-03-23)
7
19
 
8
20
  ### Bug Fixes
package/bases/base.mjs CHANGED
@@ -2,8 +2,6 @@ import js from '@eslint/js'
2
2
  import eslintPluginEslintComments from '@eslint-community/eslint-plugin-eslint-comments'
3
3
  // @ts-expect-error
4
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
5
  import eslintPluginDeprecation from 'eslint-plugin-deprecation'
8
6
  import eslintPluginFunctional from 'eslint-plugin-functional'
9
7
  import eslintPluginImport from 'eslint-plugin-import'
@@ -18,6 +16,197 @@ import {
18
16
  typeScriptTestFileGlobs,
19
17
  } from '../constants.mjs'
20
18
 
19
+ /** @returns {Promise<readonly import('eslint').Linter.FlatConfig[]>} */
20
+ async function generateTypeScriptConfig() {
21
+ // typescript plugins are depended on `typescript` package
22
+ if (!hasDep('typescript')) return []
23
+
24
+ const eslintPluginTypescriptEslint = (
25
+ await import('@typescript-eslint/eslint-plugin')
26
+ ).default
27
+ const typescriptEslintParser = (await import('@typescript-eslint/parser'))
28
+ .default
29
+
30
+ return [
31
+ {
32
+ files: typeScriptFileGlobs,
33
+ languageOptions: {
34
+ /** @type {any} */
35
+ parser: typescriptEslintParser,
36
+ parserOptions: {
37
+ // faster linting on cli
38
+ // https://github.com/typescript-eslint/typescript-eslint/issues/3528
39
+ // turned off because @typescript-eslint/no-unsafe-* rules will output wrong errors
40
+ // allowAutomaticSingleRunInference: true,
41
+ project: ['./tsconfig*.json', './packages/*/tsconfig*.json'],
42
+ },
43
+ },
44
+ settings: {
45
+ 'import/resolver': {
46
+ typescript: true,
47
+ },
48
+ },
49
+ plugins: {
50
+ // @ts-expect-error
51
+ '@typescript-eslint': eslintPluginTypescriptEslint,
52
+ // @ts-expect-error
53
+ deprecation: eslintPluginDeprecation,
54
+ functional: eslintPluginFunctional,
55
+ },
56
+ rules: {
57
+ ...eslintPluginTypescriptEslint.configs['eslint-recommended']?.rules,
58
+ ...eslintPluginTypescriptEslint.configs['recommended']?.rules,
59
+ ...eslintPluginTypescriptEslint.configs[
60
+ 'recommended-requiring-type-checking'
61
+ ]?.rules,
62
+ ...eslintPluginImport.configs['typescript']?.rules,
63
+ // extend existing rule
64
+ '@typescript-eslint/ban-types': [
65
+ 'error',
66
+ {
67
+ types: {
68
+ // TypeScript team suggests to use `<T extends {}>` https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to
69
+ '{}': false,
70
+ },
71
+ extendDefaults: true,
72
+ },
73
+ ],
74
+ // separate type exports which allow certain optimizations within compilers
75
+ '@typescript-eslint/consistent-type-exports': 'error',
76
+ '@typescript-eslint/consistent-type-imports': [
77
+ 'error',
78
+ {
79
+ // separate type imports which allow certain optimizations within compilers
80
+ prefer: 'type-imports',
81
+ },
82
+ ],
83
+ // disable the base rule as it can report incorrect errors, use @typescript-eslint/dot-notation instead
84
+ 'dot-notation': 'off',
85
+ // only allow indexed syntax (e.g. `obj['key']`) for accessing undefined fields
86
+ '@typescript-eslint/dot-notation': [
87
+ 'error',
88
+ {
89
+ allowIndexSignaturePropertyAccess: true,
90
+ },
91
+ ],
92
+ // encourage to use private accessibility modifier
93
+ '@typescript-eslint/explicit-member-accessibility': [
94
+ 'error',
95
+ {
96
+ accessibility: 'explicit',
97
+ },
98
+ ],
99
+ // sometimes auto detect can provide a better and narrower type
100
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
101
+ // disallow duplicated value in enum as it is error-prone
102
+ '@typescript-eslint/no-duplicate-enum-values': 'error',
103
+ // need empty function for react context default value
104
+ '@typescript-eslint/no-empty-function': 'off',
105
+ // encourage to check error type before use in catch clauses
106
+ '@typescript-eslint/no-implicit-any-catch': 'error',
107
+ // 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
108
+ '@typescript-eslint/no-import-type-side-effects': 'error',
109
+ // enforce correct usage of `void` type
110
+ '@typescript-eslint/no-invalid-void-type': 'error',
111
+ // allow using async function as event handler in frontend
112
+ '@typescript-eslint/no-misused-promises': [
113
+ 'error',
114
+ { checksVoidReturn: false },
115
+ ],
116
+ // declaration merging between classes and interfaces is unsafe
117
+ '@typescript-eslint/no-unsafe-declaration-merging': 'error',
118
+ // do not block functions referring to other functions
119
+ '@typescript-eslint/no-use-before-define': [
120
+ 'error',
121
+ {
122
+ /* options from eslint/no-use-before-define */
123
+ // allow use function before defined as they could be hoisted
124
+ functions: false,
125
+ classes: true,
126
+ variables: true,
127
+
128
+ /* options from @typescript-eslint/no-use-before-define */
129
+ enums: true,
130
+ // confusing option, it will disable `typedefs`
131
+ ignoreTypeReferences: false,
132
+ // tsc allows types to be used before define
133
+ typedefs: false,
134
+ },
135
+ ],
136
+ // use with functional/prefer-readonly-type
137
+ // mark class variables as readonly if it is not mutated
138
+ '@typescript-eslint/prefer-readonly': 'error',
139
+ // make sure functions which return a promise will just return a rejected promise instead of throwing an error
140
+ '@typescript-eslint/promise-function-async': 'error',
141
+ // allow primitive value in template string
142
+ '@typescript-eslint/restrict-template-expressions': [
143
+ 'error',
144
+ {
145
+ allowNumber: true,
146
+ allowBoolean: true,
147
+ allowAny: true, // mistakenly recognize string as any in 4.29.3
148
+ allowNullish: true,
149
+ allowRegExp: true,
150
+ },
151
+ ],
152
+ // avoid missed switch-case by requiring switch-case statements to be exhaustive with union type
153
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
154
+ // ignore static function as those are not supposed to use `this`
155
+ '@typescript-eslint/unbound-method': ['error', { ignoreStatic: true }],
156
+ // do not allow usage of deprecated code
157
+ 'deprecation/deprecation': 'error',
158
+ // use with @typescript-eslint/prefer-readonly
159
+ 'functional/prefer-readonly-type': [
160
+ 'error',
161
+ {
162
+ // sometimes it is easier to mutate, it should be fine to mutate within local scope
163
+ allowLocalMutation: true,
164
+ // don't force library consumer to use readonly type
165
+ allowMutableReturnType: true,
166
+ // allow mutating class variables
167
+ ignoreClass: 'fieldsOnly',
168
+ },
169
+ ],
170
+ // forbid unnecessary callback wrapper
171
+ 'functional/prefer-tacit': 'error',
172
+ 'no-restricted-syntax': [
173
+ 'error',
174
+ {
175
+ // 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
176
+ selector:
177
+ ':matches(PropertyDefinition, MethodDefinition, TSParameterProperty)[accessibility="private"]:not([kind="constructor"])',
178
+ message:
179
+ 'Use #private instead (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields)',
180
+ },
181
+ ],
182
+ // @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
183
+ // 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
184
+ 'no-undef': 'error',
185
+ },
186
+ },
187
+ {
188
+ files: typeScriptTestFileGlobs,
189
+ plugins: {
190
+ // @ts-expect-error
191
+ '@typescript-eslint': eslintPluginTypescriptEslint,
192
+ jest: eslintPluginJest,
193
+ },
194
+ rules: {
195
+ // doesn't work with jest.fn<void>()
196
+ '@typescript-eslint/no-invalid-void-type': 'off',
197
+ // replace by jest/unbound-method
198
+ '@typescript-eslint/unbound-method': 'off',
199
+ // allow passing an unbound method to `expect` calls
200
+ 'jest/unbound-method': ['error', { ignoreStatic: true }],
201
+ },
202
+ },
203
+ {
204
+ files: typeScriptFileGlobs,
205
+ ...esmConfig,
206
+ },
207
+ ]
208
+ }
209
+
21
210
  /** @type {import('eslint').Linter.FlatConfig} */
22
211
  const cjsConfig = {
23
212
  languageOptions: {
@@ -51,7 +240,7 @@ const baseConfig = [
51
240
  js.configs.recommended,
52
241
  {
53
242
  languageOptions: {
54
- ecmaVersion: 2021,
243
+ ecmaVersion: 2022,
55
244
  globals: {
56
245
  // should align with languageOptions.ecmaVersion
57
246
  ...globals.es2021,
@@ -143,6 +332,10 @@ const baseConfig = [
143
332
  noUselessIndex: false,
144
333
  },
145
334
  ],
335
+ // turn off these rules as they do not support flat config: https://github.com/import-js/eslint-plugin-import/issues/2556
336
+ 'import/namespace': 'off',
337
+ 'import/no-named-as-default': 'off',
338
+ 'import/no-named-as-default-member': 'off',
146
339
  // prefer explicitly convert type for readability
147
340
  'no-implicit-coercion': 'error',
148
341
  // make sure private class members are in-use
@@ -195,188 +388,6 @@ const baseConfig = [
195
388
  'jest/prefer-hooks-on-top': 'error',
196
389
  },
197
390
  },
198
- // typescript plugins are depended on `typescript` package
199
- // @ts-expect-error
200
- ...(hasDep('typescript')
201
- ? [
202
- {
203
- files: typeScriptFileGlobs,
204
- languageOptions: {
205
- /** @type {any} */
206
- parser: typescriptEslintParser,
207
- parserOptions: {
208
- // faster linting on cli
209
- // https://github.com/typescript-eslint/typescript-eslint/issues/3528
210
- // turned off because @typescript-eslint/no-unsafe-* rules will output wrong errors
211
- // allowAutomaticSingleRunInference: true,
212
- project: ['./tsconfig*.json', './packages/*/tsconfig*.json'],
213
- },
214
- },
215
- settings: {
216
- 'import/resolver': {
217
- typescript: true,
218
- },
219
- },
220
- plugins: {
221
- '@typescript-eslint': eslintPluginTypescriptEslint,
222
- deprecation: eslintPluginDeprecation,
223
- functional: eslintPluginFunctional,
224
- },
225
- rules: {
226
- ...eslintPluginTypescriptEslint.configs['eslint-recommended']
227
- ?.rules,
228
- ...eslintPluginTypescriptEslint.configs['recommended']?.rules,
229
- ...eslintPluginTypescriptEslint.configs[
230
- 'recommended-requiring-type-checking'
231
- ]?.rules,
232
- ...eslintPluginImport.configs['typescript']?.rules,
233
- // extend existing rule
234
- '@typescript-eslint/ban-types': [
235
- 'error',
236
- {
237
- types: {
238
- // TypeScript team suggests to use `<T extends {}>` https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to
239
- '{}': false,
240
- },
241
- extendDefaults: true,
242
- },
243
- ],
244
- // separate type exports which allow certain optimizations within compilers
245
- '@typescript-eslint/consistent-type-exports': 'error',
246
- '@typescript-eslint/consistent-type-imports': [
247
- 'error',
248
- {
249
- // separate type imports which allow certain optimizations within compilers
250
- prefer: 'type-imports',
251
- },
252
- ],
253
- // disable the base rule as it can report incorrect errors, use @typescript-eslint/dot-notation instead
254
- 'dot-notation': 'off',
255
- // only allow indexed syntax (e.g. `obj['key']`) for accessing undefined fields
256
- '@typescript-eslint/dot-notation': [
257
- 'error',
258
- {
259
- allowIndexSignaturePropertyAccess: true,
260
- },
261
- ],
262
- // encourage to use private accessibility modifier
263
- '@typescript-eslint/explicit-member-accessibility': [
264
- 'error',
265
- {
266
- accessibility: 'explicit',
267
- },
268
- ],
269
- // sometimes auto detect can provide a better and narrower type
270
- '@typescript-eslint/explicit-module-boundary-types': 'off',
271
- // disallow duplicated value in enum as it is error-prone
272
- '@typescript-eslint/no-duplicate-enum-values': 'error',
273
- // need empty function for react context default value
274
- '@typescript-eslint/no-empty-function': 'off',
275
- // encourage to check error type before use in catch clauses
276
- '@typescript-eslint/no-implicit-any-catch': 'error',
277
- // 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
278
- '@typescript-eslint/no-import-type-side-effects': 'error',
279
- // enforce correct usage of `void` type
280
- '@typescript-eslint/no-invalid-void-type': 'error',
281
- // allow using async function as event handler in frontend
282
- '@typescript-eslint/no-misused-promises': [
283
- 'error',
284
- { checksVoidReturn: false },
285
- ],
286
- // declaration merging between classes and interfaces is unsafe
287
- '@typescript-eslint/no-unsafe-declaration-merging': 'error',
288
- // do not block functions referring to other functions
289
- '@typescript-eslint/no-use-before-define': [
290
- 'error',
291
- {
292
- /* options from eslint/no-use-before-define */
293
- // allow use function before defined as they could be hoisted
294
- functions: false,
295
- classes: true,
296
- variables: true,
297
-
298
- /* options from @typescript-eslint/no-use-before-define */
299
- enums: true,
300
- // confusing option, it will disable `typedefs`
301
- ignoreTypeReferences: false,
302
- // tsc allows types to be used before define
303
- typedefs: false,
304
- },
305
- ],
306
- // use with functional/prefer-readonly-type
307
- // mark class variables as readonly if it is not mutated
308
- '@typescript-eslint/prefer-readonly': 'error',
309
- // make sure functions which return a promise will just return a rejected promise instead of throwing an error
310
- '@typescript-eslint/promise-function-async': 'error',
311
- // allow primitive value in template string
312
- '@typescript-eslint/restrict-template-expressions': [
313
- 'error',
314
- {
315
- allowNumber: true,
316
- allowBoolean: true,
317
- allowAny: true, // mistakenly recognize string as any in 4.29.3
318
- allowNullish: true,
319
- allowRegExp: true,
320
- },
321
- ],
322
- // avoid missed switch-case by requiring switch-case statements to be exhaustive with union type
323
- '@typescript-eslint/switch-exhaustiveness-check': 'error',
324
- // ignore static function as those are not supposed to use `this`
325
- '@typescript-eslint/unbound-method': [
326
- 'error',
327
- { ignoreStatic: true },
328
- ],
329
- // do not allow usage of deprecated code
330
- 'deprecation/deprecation': 'error',
331
- // use with @typescript-eslint/prefer-readonly
332
- 'functional/prefer-readonly-type': [
333
- 'error',
334
- {
335
- // sometimes it is easier to mutate, it should be fine to mutate within local scope
336
- allowLocalMutation: true,
337
- // don't force library consumer to use readonly type
338
- allowMutableReturnType: true,
339
- // allow mutating class variables
340
- ignoreClass: 'fieldsOnly',
341
- },
342
- ],
343
- // forbid unnecessary callback wrapper
344
- 'functional/prefer-tacit': 'error',
345
- 'no-restricted-syntax': [
346
- 'error',
347
- {
348
- // 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
349
- selector:
350
- ':matches(PropertyDefinition, MethodDefinition, TSParameterProperty)[accessibility="private"]:not([kind="constructor"])',
351
- message:
352
- 'Use #private instead (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields)',
353
- },
354
- ],
355
- // @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
356
- // 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
357
- 'no-undef': 'error',
358
- },
359
- },
360
- {
361
- files: typeScriptTestFileGlobs,
362
- plugins: {
363
- '@typescript-eslint': eslintPluginTypescriptEslint,
364
- jest: eslintPluginJest,
365
- },
366
- rules: {
367
- // doesn't work with jest.fn<void>()
368
- '@typescript-eslint/no-invalid-void-type': 'off',
369
- // replace by jest/unbound-method
370
- '@typescript-eslint/unbound-method': 'off',
371
- // allow passing an unbound method to `expect` calls
372
- 'jest/unbound-method': ['error', { ignoreStatic: true }],
373
- },
374
- },
375
- {
376
- files: typeScriptFileGlobs,
377
- ...esmConfig,
378
- },
379
- ]
380
- : []),
391
+ ...(await generateTypeScriptConfig()),
381
392
  ]
382
393
  export default baseConfig
@@ -1,5 +1,4 @@
1
1
  import eslintConfigPrettier from 'eslint-config-prettier'
2
- // eslint-disable-next-line import/namespace, import/no-named-as-default, import/no-named-as-default-member
3
2
  import eslintPluginPrettier from 'eslint-plugin-prettier'
4
3
 
5
4
  /** @type {import('eslint').Linter.FlatConfig[]} */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@foray1010/eslint-config",
4
- "version": "10.0.1",
4
+ "version": "10.0.3",
5
5
  "homepage": "https://github.com/foray1010/common-presets/tree/master/packages/eslint-config#readme",
6
6
  "bugs": "https://github.com/foray1010/common-presets/issues",
7
7
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
24
24
  "@eslint/js": "^8.36.0",
25
- "@foray1010/common-presets-utils": "^7.0.0",
25
+ "@foray1010/common-presets-utils": "^7.0.1",
26
26
  "@typescript-eslint/eslint-plugin": "^5.56.0",
27
27
  "@typescript-eslint/parser": "^5.56.0",
28
28
  "confusing-browser-globals": "^1.0.10",
@@ -50,7 +50,13 @@
50
50
  },
51
51
  "peerDependencies": {
52
52
  "eslint": "^8.36.0",
53
- "prettier": "^2.0.0"
53
+ "prettier": "^2.0.0",
54
+ "typescript": "^5.0.2"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "typescript": {
58
+ "optional": true
59
+ }
54
60
  },
55
61
  "engines": {
56
62
  "node": "^16.14.0 || >=18.12.0"
@@ -58,5 +64,5 @@
58
64
  "publishConfig": {
59
65
  "access": "public"
60
66
  },
61
- "gitHead": "c722884bc466360097d9ab80e72f350a15ed7cad"
67
+ "gitHead": "11db51812a862318500928563f382138f8b5a9d6"
62
68
  }