@perfective/eslint-config 0.32.0 → 0.33.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2020-2025 Andrey Mikheychik (https://github.com/amikheychik)
3
+ Copyright (c) 2020-2026 Andrey Mikheychik (https://github.com/amikheychik)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,4 +1,4 @@
1
- import eslintPluginCypress from 'eslint-plugin-cypress/flat';
1
+ import eslintPluginCypress from 'eslint-plugin-cypress';
2
2
  import { cypressFiles } from "../../linter/glob.js";
3
3
  import { importNoExtraneousDependencies } from "../import/rules/no-extraneous-dependencies.js";
4
4
  export function cypressConfig(files = [cypressFiles]) {
@@ -165,6 +165,9 @@ export const eslintSuggestionsRules = {
165
165
  'prefer-rest-params': 'error',
166
166
  'prefer-spread': 'error',
167
167
  'prefer-template': 'warn',
168
+ 'preserve-caught-error': ['off', {
169
+ requireCatchParameter: true
170
+ }],
168
171
  'quote-props': 'off',
169
172
  'radix': 'error',
170
173
  'require-await': 'error',
@@ -53,6 +53,7 @@ export function jestConfig(files = jestFiles) {
53
53
  'jest/no-standalone-expect': 'error',
54
54
  'jest/no-test-prefixes': 'warn',
55
55
  'jest/no-test-return-statement': 'error',
56
+ 'jest/no-unneeded-async-expect-function': 'warn',
56
57
  'jest/no-untyped-mock-factory': 'warn',
57
58
  'jest/padding-around-after-all-blocks': 'warn',
58
59
  'jest/padding-around-after-each-blocks': 'warn',
@@ -76,14 +77,18 @@ export function jestConfig(files = jestFiles) {
76
77
  'jest/prefer-lowercase-title': ['error', {
77
78
  allowedPrefixes: [],
78
79
  ignore: [],
80
+ ignoreTodos: false,
79
81
  ignoreTopLevelDescribe: true
80
82
  }],
81
83
  'jest/prefer-mock-promise-shorthand': 'warn',
84
+ 'jest/prefer-mock-return-shorthand': 'warn',
82
85
  'jest/prefer-snapshot-hint': ['error', 'always'],
83
86
  'jest/prefer-spy-on': 'warn',
84
87
  'jest/prefer-strict-equal': 'warn',
85
88
  'jest/prefer-to-be': 'warn',
86
89
  'jest/prefer-to-contain': 'warn',
90
+ 'jest/prefer-to-have-been-called': 'warn',
91
+ 'jest/prefer-to-have-been-called-times': 'warn',
87
92
  'jest/prefer-to-have-length': 'warn',
88
93
  'jest/prefer-todo': 'warn',
89
94
  'jest/require-hook': ['error', {
@@ -94,6 +99,7 @@ export function jestConfig(files = jestFiles) {
94
99
  'jest/valid-describe-callback': 'error',
95
100
  'jest/valid-expect-in-promise': 'error',
96
101
  'jest/valid-expect': 'error',
102
+ 'jest/valid-mock-module-path': 'error',
97
103
  'jest/valid-title': ['warn', {
98
104
  ignoreTypeOfDescribeName: true,
99
105
  ignoreTypeOfTestName: false,
@@ -1,5 +1,8 @@
1
1
  export const typescriptEslintJestRules = {
2
+ 'jest/no-error-equal': 'error',
3
+ 'jest/no-unnecessary-assertion': 'error',
2
4
  'jest/unbound-method': ['error', {
3
5
  ignoreStatic: false
4
- }]
6
+ }],
7
+ 'jest/valid-expect-with-promise': 'error'
5
8
  };
@@ -1,13 +1,9 @@
1
- import eslintPluginJsdoc from 'eslint-plugin-jsdoc';
1
+ import { jsdoc } from 'eslint-plugin-jsdoc';
2
2
  import { javascriptFiles } from "../../linter/glob.js";
3
3
  import { javascriptLanguageOptions } from "../../linter/language-options.js";
4
4
  export function jsdocConfig() {
5
- return {
6
- plugins: {
7
- jsdoc: {
8
- rules: eslintPluginJsdoc.configs['flat/recommended'].plugins['jsdoc'].rules
9
- }
10
- },
5
+ return jsdoc({
6
+ config: 'flat/recommended',
11
7
  settings: {
12
8
  jsdoc: {
13
9
  tagNamePreference: {
@@ -30,7 +26,9 @@ export function jsdocConfig() {
30
26
  },
31
27
  rules: {
32
28
  'jsdoc/check-access': 'off',
33
- 'jsdoc/check-alignment': 'error',
29
+ 'jsdoc/check-alignment': ['error', {
30
+ innerIndent: 1
31
+ }],
34
32
  'jsdoc/check-examples': 'off',
35
33
  'jsdoc/check-indentation': 'off',
36
34
  'jsdoc/check-line-alignment': ['off', 'never'],
@@ -60,6 +58,11 @@ export function jsdocConfig() {
60
58
  'jsdoc/empty-tags': ['error', {
61
59
  tags: ['final', 'flags', 'sealed']
62
60
  }],
61
+ 'jsdoc/escape-inline-tags': ['error', {
62
+ allowedInlineTags: [],
63
+ enableFixer: false,
64
+ fixType: 'backticks'
65
+ }],
63
66
  'jsdoc/implements-on-classes': 'error',
64
67
  'jsdoc/imports-as-dependencies': 'error',
65
68
  'jsdoc/lines-before-block': 'off',
@@ -90,6 +93,9 @@ export function jsdocConfig() {
90
93
  'jsdoc/no-restricted-syntax': 'off',
91
94
  'jsdoc/no-types': 'error',
92
95
  'jsdoc/no-undefined-types': 'error',
96
+ 'jsdoc/prefer-import-tag': 'warn',
97
+ 'jsdoc/reject-any-type': 'error',
98
+ 'jsdoc/reject-function-type': 'error',
93
99
  'jsdoc/require-asterisk-prefix': ['error', 'always'],
94
100
  'jsdoc/require-description': ['error', {
95
101
  exemptedBy: ['inheritdoc', 'package', 'private', 'see', 'deprecated']
@@ -99,6 +105,8 @@ export function jsdocConfig() {
99
105
  'jsdoc/require-file-overview': 'off',
100
106
  'jsdoc/require-hyphen-before-param-description': ['warn', 'always'],
101
107
  'jsdoc/require-jsdoc': 'off',
108
+ 'jsdoc/require-next-description': 'error',
109
+ 'jsdoc/require-next-type': 'error',
102
110
  'jsdoc/require-param': 'off',
103
111
  'jsdoc/require-param-description': 'error',
104
112
  'jsdoc/require-param-name': 'error',
@@ -107,16 +115,24 @@ export function jsdocConfig() {
107
115
  'jsdoc/require-property-description': 'error',
108
116
  'jsdoc/require-property-name': 'error',
109
117
  'jsdoc/require-property-type': 'error',
118
+ 'jsdoc/require-rejects': 'error',
110
119
  'jsdoc/require-returns': 'off',
111
120
  'jsdoc/require-returns-check': 'error',
112
121
  'jsdoc/require-returns-description': 'error',
113
122
  'jsdoc/require-returns-type': 'off',
123
+ 'jsdoc/require-tags': 'off',
114
124
  'jsdoc/require-template': ['off', {
125
+ exemptedBy: [],
115
126
  requireSeparateTemplates: false
116
127
  }],
128
+ 'jsdoc/require-template-description': 'off',
117
129
  'jsdoc/require-throws': 'error',
130
+ 'jsdoc/require-throws-description': 'error',
131
+ 'jsdoc/require-throws-type': 'error',
118
132
  'jsdoc/require-yields': 'error',
119
133
  'jsdoc/require-yields-check': 'error',
134
+ 'jsdoc/require-yields-description': 'error',
135
+ 'jsdoc/require-yields-type': 'error',
120
136
  'jsdoc/sort-tags': ['warn', {
121
137
  tagSequence: [{
122
138
  tags: ['summary', 'typeSummary']
@@ -157,11 +173,46 @@ export function jsdocConfig() {
157
173
  startLines: 1,
158
174
  endLines: 0,
159
175
  applyToEndTag: false,
176
+ maxBlockLines: null,
160
177
  tags: {}
161
178
  }],
179
+ 'jsdoc/ts-method-signature-style': 'warn',
180
+ 'jsdoc/ts-no-empty-object-type': 'error',
181
+ 'jsdoc/ts-no-unnecessary-template-expression': 'warn',
182
+ 'jsdoc/ts-prefer-function-type': 'warn',
183
+ 'jsdoc/type-formatting': ['warn', {
184
+ arrayBrackets: 'square',
185
+ arrowFunctionPostReturnMarkerSpacing: '',
186
+ arrowFunctionPreReturnMarkerSpacing: '',
187
+ enableFixer: true,
188
+ functionOrClassParameterSpacing: '',
189
+ functionOrClassPostGenericSpacing: '',
190
+ functionOrClassPostReturnMarkerSpacing: '',
191
+ functionOrClassPreReturnMarkerSpacing: '',
192
+ functionOrClassTypeParameterSpacing: '',
193
+ genericAndTupleElementSpacing: '',
194
+ genericDot: false,
195
+ keyValuePostColonSpacing: '',
196
+ keyValuePostKeySpacing: '',
197
+ keyValuePostOptionalSpacing: '',
198
+ keyValuePostVariadicSpacing: '',
199
+ methodQuotes: 'double',
200
+ objectFieldIndent: '',
201
+ objectFieldQuote: null,
202
+ objectFieldSeparator: 'comma',
203
+ objectFieldSeparatorOptionalLinebreak: true,
204
+ objectFieldSeparatorTrailingPunctuation: false,
205
+ parameterDefaultValueSpacing: ' ',
206
+ postMethodNameSpacing: '',
207
+ postNewSpacing: ' ',
208
+ separatorForSingleObjectField: false,
209
+ stringQuotes: 'double',
210
+ typeBracketSpacing: '',
211
+ unionSpacing: ' '
212
+ }],
162
213
  'jsdoc/valid-types': 'error'
163
214
  }
164
- };
215
+ });
165
216
  }
166
217
  export function jsdocJavascriptConfig() {
167
218
  return {
@@ -48,12 +48,14 @@ export function rxjsConfig(files = typescriptFiles) {
48
48
  'rxjs-x/no-nested-subscribe': 'error',
49
49
  'rxjs-x/no-redundant-notify': 'error',
50
50
  'rxjs-x/no-sharereplay': 'off',
51
+ 'rxjs-x/no-sharereplay-before-takeuntil': 'error',
51
52
  'rxjs-x/no-subclass': 'error',
52
53
  'rxjs-x/no-subject-unsubscribe': 'error',
53
54
  'rxjs-x/no-subject-value': 'error',
54
55
  'rxjs-x/no-subscribe-handlers': 'off',
55
56
  'rxjs-x/no-topromise': 'error',
56
57
  'rxjs-x/no-unbound-methods': 'error',
58
+ 'rxjs-x/no-unnecessary-collection': 'error',
57
59
  'rxjs-x/no-unsafe-catch': 'error',
58
60
  'rxjs-x/no-unsafe-first': 'error',
59
61
  'rxjs-x/no-unsafe-subject-next': 'error',
@@ -94,7 +94,7 @@ export function stylisticConfig() {
94
94
  allowNamespace: false,
95
95
  ignore: []
96
96
  }],
97
- '@stylistic/jsx-props-no-multi-spaces': 'warn',
97
+ '@stylistic/jsx-props-no-multi-spaces': 'off',
98
98
  '@stylistic/jsx-quotes': ['warn', 'prefer-double'],
99
99
  '@stylistic/jsx-self-closing-comp': ['warn', {
100
100
  component: true,
@@ -161,6 +161,7 @@ export function stylisticConfig() {
161
161
  exceptAfterSingleLine: true,
162
162
  exceptAfterOverload: true
163
163
  }],
164
+ '@stylistic/exp-list-style': 'off',
164
165
  '@stylistic/max-len': ['error', {
165
166
  code: 120,
166
167
  tabWidth: 4,
@@ -197,8 +198,8 @@ export function stylisticConfig() {
197
198
  ignoreJSX: 'all',
198
199
  nestedBinaryExpressions: false,
199
200
  nestedConditionalExpressions: false,
200
- enforceForArrowConditionals: false,
201
- ternaryOperandBinaryExpressions: false
201
+ ternaryOperandBinaryExpressions: false,
202
+ ignoredNodes: ['ArrowFunctionExpression[body.type=ConditionalExpression]']
202
203
  }],
203
204
  '@stylistic/no-extra-semi': 'warn',
204
205
  '@stylistic/no-floating-decimal': 'warn',
@@ -227,6 +228,7 @@ export function stylisticConfig() {
227
228
  }],
228
229
  '@stylistic/object-curly-spacing': ['warn', 'always', {
229
230
  arraysInObjects: true,
231
+ emptyObjects: 'never',
230
232
  objectsInObjects: true
231
233
  }],
232
234
  '@stylistic/object-property-newline': ['warn', {
@@ -8,14 +8,14 @@ export function testingLibraryConfig(files = jestFiles) {
8
8
  },
9
9
  rules: {
10
10
  'testing-library/await-async-events': 'off',
11
- 'testing-library/await-async-queries': 'error',
12
- 'testing-library/await-async-utils': 'error',
11
+ 'testing-library/await-async-queries': 'warn',
12
+ 'testing-library/await-async-utils': 'warn',
13
13
  'testing-library/consistent-data-testid': ['error', {
14
14
  testIdPattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
15
15
  testIdAttribute: 'data-testId'
16
16
  }],
17
17
  'testing-library/no-await-sync-events': 'error',
18
- 'testing-library/no-await-sync-queries': 'error',
18
+ 'testing-library/no-await-sync-queries': 'warn',
19
19
  'testing-library/no-container': 'error',
20
20
  'testing-library/no-debugging-utils': 'error',
21
21
  'testing-library/no-dom-import': 'warn',
@@ -26,7 +26,7 @@ export function testingLibraryConfig(files = jestFiles) {
26
26
  'testing-library/no-render-in-lifecycle': 'error',
27
27
  'testing-library/no-test-id-queries': 'error',
28
28
  'testing-library/no-unnecessary-act': 'off',
29
- 'testing-library/no-wait-for-multiple-assertions': 'error',
29
+ 'testing-library/no-wait-for-multiple-assertions': 'warn',
30
30
  'testing-library/no-wait-for-side-effects': 'error',
31
31
  'testing-library/no-wait-for-snapshot': 'error',
32
32
  'testing-library/prefer-explicit-assert': 'off',
@@ -40,6 +40,7 @@ export function testingLibraryConfig(files = jestFiles) {
40
40
  'testing-library/prefer-query-matchers': 'off',
41
41
  'testing-library/prefer-screen-queries': 'error',
42
42
  'testing-library/prefer-user-event': 'error',
43
+ 'testing-library/prefer-user-event-setup': 'error',
43
44
  'testing-library/render-result-naming-convention': 'error'
44
45
  }
45
46
  };
@@ -68,6 +68,8 @@ export const extensionRules = {
68
68
  }],
69
69
  'no-unused-expressions': 'off',
70
70
  '@typescript-eslint/no-unused-expressions': 'error',
71
+ 'no-unused-private-class-members': 'off',
72
+ '@typescript-eslint/no-unused-private-class-members': 'error',
71
73
  'no-unused-vars': 'off',
72
74
  '@typescript-eslint/no-unused-vars': ['error', {
73
75
  args: 'after-used',
@@ -144,10 +144,13 @@ export const supportedRules = {
144
144
  '@typescript-eslint/no-unsafe-declaration-merging': 'error',
145
145
  '@typescript-eslint/no-unsafe-enum-comparison': 'error',
146
146
  '@typescript-eslint/no-unsafe-function-type': 'warn',
147
- '@typescript-eslint/no-unsafe-member-access': 'error',
147
+ '@typescript-eslint/no-unsafe-member-access': ['error', {
148
+ allowOptionalChaining: false
149
+ }],
148
150
  '@typescript-eslint/no-unsafe-return': 'error',
149
151
  '@typescript-eslint/no-unsafe-type-assertion': 'off',
150
152
  '@typescript-eslint/no-unsafe-unary-minus': 'error',
153
+ '@typescript-eslint/no-useless-default-assignment': 'error',
151
154
  '@typescript-eslint/no-useless-empty-export': 'warn',
152
155
  '@typescript-eslint/no-useless-template-literal': 'off',
153
156
  '@typescript-eslint/no-var-requires': ['error', {
@@ -36,6 +36,7 @@ export function unicornConfig() {
36
36
  'unicorn/no-array-method-this-argument': 'warn',
37
37
  'unicorn/no-array-reduce': 'off',
38
38
  'unicorn/no-array-reverse': 'off',
39
+ 'unicorn/no-array-sort': 'off',
39
40
  'unicorn/no-await-expression-member': 'error',
40
41
  'unicorn/no-await-in-promise-methods': 'error',
41
42
  'unicorn/no-console-spaces': 'warn',
@@ -43,6 +44,7 @@ export function unicornConfig() {
43
44
  'unicorn/no-empty-file': 'error',
44
45
  'unicorn/no-for-loop': 'warn',
45
46
  'unicorn/no-hex-escape': 'warn',
47
+ 'unicorn/no-immediate-mutation': 'warn',
46
48
  'unicorn/no-instanceof-array': 'off',
47
49
  'unicorn/no-instanceof-builtins': 'warn',
48
50
  'unicorn/no-invalid-fetch-options': 'error',
@@ -79,6 +81,7 @@ export function unicornConfig() {
79
81
  'unicorn/no-unreadable-iife': 'error',
80
82
  'unicorn/no-unsafe-regex': 'off',
81
83
  'unicorn/no-unused-properties': 'off',
84
+ 'unicorn/no-useless-collection-argument': 'warn',
82
85
  'unicorn/no-useless-error-capture-stack-trace': 'warn',
83
86
  'unicorn/no-useless-fallback-in-spread': 'warn',
84
87
  'unicorn/no-useless-length-check': 'warn',
@@ -117,8 +120,10 @@ export function unicornConfig() {
117
120
  'unicorn/prefer-array-index-of': 'warn',
118
121
  'unicorn/prefer-array-some': 'error',
119
122
  'unicorn/prefer-at': 'off',
123
+ 'unicorn/prefer-bigint-literals': 'warn',
120
124
  'unicorn/prefer-blob-reading-methods': 'error',
121
125
  'unicorn/prefer-class-fields': 'warn',
126
+ 'unicorn/prefer-classlist-toggle': 'warn',
122
127
  'unicorn/prefer-code-point': 'error',
123
128
  'unicorn/prefer-date-now': 'warn',
124
129
  'unicorn/prefer-default-parameters': 'warn',
@@ -154,6 +159,7 @@ export function unicornConfig() {
154
159
  'unicorn/prefer-query-selector': 'warn',
155
160
  'unicorn/prefer-reflect-apply': 'warn',
156
161
  'unicorn/prefer-regexp-test': 'off',
162
+ 'unicorn/prefer-response-static-json': 'warn',
157
163
  'unicorn/prefer-set-has': 'warn',
158
164
  'unicorn/prefer-set-size': 'warn',
159
165
  'unicorn/prefer-single-call': ['warn', {
@@ -176,6 +182,7 @@ export function unicornConfig() {
176
182
  'unicorn/prevent-abbreviations': ['warn', unicornPreventAbbreviations()],
177
183
  'unicorn/relative-url-style': ['warn', 'always'],
178
184
  'unicorn/require-array-join-separator': 'warn',
185
+ 'unicorn/require-module-attributes': 'warn',
179
186
  'unicorn/require-module-specifiers': 'warn',
180
187
  'unicorn/require-number-to-fixed-digits-argument': 'warn',
181
188
  'unicorn/require-post-message-target-origin': 'error',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perfective/eslint-config",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "ESLint shareable rules configuration",
5
5
  "keywords": ["code quality", "code standard", "code style", "eslint", "eslint config", "lint", "perfective", "tslint", "tslint config", "typescript"],
6
6
  "author": "Andrey Mikheychik <a.mikheychik@gmail.com>",
@@ -13,24 +13,24 @@
13
13
  "license": "MIT",
14
14
  "peerDependencies": {
15
15
  "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0",
16
- "@stylistic/eslint-plugin": "^5.2.3",
17
- "eslint": "^9.34.0",
16
+ "@stylistic/eslint-plugin": "^5.6.1",
17
+ "eslint": "^9.39.2",
18
18
  "eslint-import-resolver-typescript": "^3.10.1",
19
- "eslint-plugin-array-func": "^5.0.2",
20
- "eslint-plugin-cypress": "^5.1.1",
19
+ "eslint-plugin-array-func": "^5.1.0",
20
+ "eslint-plugin-cypress": "^5.2.1",
21
21
  "eslint-plugin-import": "^2.32.0",
22
- "eslint-plugin-jest": "^29.0.1",
22
+ "eslint-plugin-jest": "^29.12.1",
23
23
  "eslint-plugin-jest-dom": "^5.5.0",
24
- "eslint-plugin-jsdoc": "^54.1.1",
25
- "eslint-plugin-n": "^17.21.3",
24
+ "eslint-plugin-jsdoc": "^61.5.0",
25
+ "eslint-plugin-n": "^17.23.1",
26
26
  "eslint-plugin-prefer-arrow": "^1.2.3",
27
27
  "eslint-plugin-promise": "^7.2.1",
28
- "eslint-plugin-rxjs-x": "~0.7.7",
28
+ "eslint-plugin-rxjs-x": "~0.8.4",
29
29
  "eslint-plugin-security": "^3.0.1",
30
30
  "eslint-plugin-simple-import-sort": "^12.1.1",
31
- "eslint-plugin-testing-library": "^7.6.6",
32
- "eslint-plugin-unicorn": "^60.0.0",
33
- "typescript-eslint": "^8.40.0"
31
+ "eslint-plugin-testing-library": "^7.15.4",
32
+ "eslint-plugin-unicorn": "^62.0.0",
33
+ "typescript-eslint": "^8.52.0"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "eslint-plugin-cypress": {