@mikey-pro/eslint-config 8.0.19 → 8.1.1

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.
Files changed (4) hide show
  1. package/index.js +85 -91
  2. package/overrides.js +116 -107
  3. package/package.json +23 -24
  4. package/rules.js +124 -142
package/index.js CHANGED
@@ -1,33 +1,30 @@
1
1
  import cypressJson from '@cypress/eslint-plugin-json';
2
2
  import eslintJs from '@eslint/js';
3
+ import boundariesPlugin from 'eslint-plugin-boundaries';
3
4
  import compatPlugin from 'eslint-plugin-compat';
4
5
  import cssModules from 'eslint-plugin-css-modules';
5
6
  import importPlugin from 'eslint-plugin-import';
7
+ import nPlugin from 'eslint-plugin-n';
8
+ import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests';
9
+ import noSecretsPlugin from 'eslint-plugin-no-secrets';
6
10
  import onlyWarn from 'eslint-plugin-only-warn';
7
- import unicorn from 'eslint-plugin-unicorn';
8
- import globals from 'globals';
9
- import securityPlugin from 'eslint-plugin-security';
11
+ import optimizeRegexPlugin from 'eslint-plugin-optimize-regex';
12
+ import perfectionistPlugin from 'eslint-plugin-perfectionist';
13
+ import eslintPluginPrettier from 'eslint-plugin-prettier';
14
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
10
15
  import promisePlugin from 'eslint-plugin-promise';
16
+ import regexpPlugin from 'eslint-plugin-regexp';
17
+ import securityPlugin from 'eslint-plugin-security';
11
18
  import importSortPlugin from 'eslint-plugin-simple-import-sort';
12
- import perfectionistPlugin from 'eslint-plugin-perfectionist';
13
- import noSecretsPlugin from 'eslint-plugin-no-secrets';
14
- import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests';
15
19
  import sonarjsPlugin from 'eslint-plugin-sonarjs';
16
- import regexpPlugin from 'eslint-plugin-regexp';
17
- import etcPlugin from 'eslint-plugin-etc';
18
- import typescriptSortKeysPlugin from 'eslint-plugin-typescript-sort-keys';
19
20
  import sortDestructureKeysPlugin from 'eslint-plugin-sort-destructure-keys';
21
+ import unicorn from 'eslint-plugin-unicorn';
20
22
  import writeGoodCommentsPlugin from 'eslint-plugin-write-good-comments';
21
- import boundariesPlugin from 'eslint-plugin-boundaries';
22
- import nPlugin from 'eslint-plugin-n';
23
- import radarPlugin from 'eslint-plugin-radar';
24
- import optimizeRegexPlugin from 'eslint-plugin-optimize-regex';
25
- import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
23
+ import globals from 'globals';
26
24
 
27
25
  import { baseOverrides } from './overrides.js';
28
26
  import { baseRules } from './rules.js';
29
27
 
30
- /** @type {import('eslint').Linter.Config[]} */
31
28
  const config = [
32
29
  {
33
30
  ignores: [
@@ -51,45 +48,43 @@ const config = [
51
48
  eslintJs.configs.recommended,
52
49
  eslintPluginPrettierRecommended,
53
50
  {
54
- files: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'], // Add files pattern
51
+ files: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],
55
52
  languageOptions: {
56
53
  ecmaVersion: 'latest',
57
- sourceType: 'module',
58
54
  globals: {
59
55
  ...globals.browser,
60
56
  ...globals.commonjs,
61
57
  ...globals.es2022,
62
58
  ...globals.es6,
63
- ...globals.node
59
+ ...globals.node,
64
60
  },
61
+ sourceType: 'module',
65
62
  },
66
63
  linterOptions: {
67
64
  noInlineConfig: true,
68
65
  reportUnusedDisableDirectives: true,
69
66
  },
70
67
  plugins: {
71
- unicorn,
72
- 'css-modules': cssModules,
73
- 'only-warn': onlyWarn,
74
68
  '@cypress/json': cypressJson,
69
+ boundaries: boundariesPlugin,
70
+ compat: compatPlugin,
71
+ 'css-modules': cssModules,
75
72
  import: importPlugin,
76
- security: securityPlugin,
73
+ n: nPlugin,
74
+ 'no-only-tests': noOnlyTestsPlugin,
75
+ 'no-secrets': noSecretsPlugin,
76
+ 'only-warn': onlyWarn,
77
+ 'optimize-regex': optimizeRegexPlugin,
78
+ perfectionist: perfectionistPlugin,
79
+ prettier: eslintPluginPrettier,
77
80
  promise: promisePlugin,
81
+ regexp: regexpPlugin,
82
+ security: securityPlugin,
78
83
  'simple-import-sort': importSortPlugin,
79
- perfectionist: perfectionistPlugin,
80
- 'no-secrets': noSecretsPlugin,
81
- 'no-only-tests': noOnlyTestsPlugin,
82
84
  sonarjs: sonarjsPlugin,
83
- regexp: regexpPlugin,
84
- etc: etcPlugin,
85
- 'typescript-sort-keys': typescriptSortKeysPlugin,
86
85
  'sort-destructure-keys': sortDestructureKeysPlugin,
86
+ unicorn,
87
87
  'write-good-comments': writeGoodCommentsPlugin,
88
- boundaries: boundariesPlugin,
89
- n: nPlugin,
90
- radar: radarPlugin,
91
- 'optimize-regex': optimizeRegexPlugin,
92
- compat: compatPlugin,
93
88
  },
94
89
  rules: {
95
90
  ...baseRules,
@@ -98,85 +93,84 @@ const config = [
98
93
  ...cssModules.configs.recommended.rules,
99
94
  ...importPlugin.configs.recommended.rules,
100
95
  ...sonarjsPlugin.configs.recommended.rules,
101
- 'prettier/prettier': ['warn', {
102
- parser: 'babel',
103
- endOfLine: 'lf',
104
- singleQuote: true,
105
- trailingComma: 'all'
106
- }],
107
-
108
- // Security
109
- 'security/detect-object-injection': 'warn',
110
- 'security/detect-possible-timing-attacks': 'warn',
111
- 'security/detect-non-literal-regexp': 'warn',
112
-
113
- // Promises
96
+ 'import/no-anonymous-default-export': 'warn',
97
+ 'import/no-cycle': 'warn',
98
+ 'import/no-useless-path-segments': 'warn',
99
+ 'no-only-tests/no-only-tests': 'warn',
100
+ 'no-secrets/no-secrets': ['warn', { tolerance: 4.5 }],
101
+ 'perfectionist/sort-named-imports': 'warn',
102
+ 'perfectionist/sort-objects': [
103
+ 'warn',
104
+ {
105
+ order: 'asc',
106
+ type: 'natural',
107
+ },
108
+ ],
109
+ 'prettier/prettier': [
110
+ 'warn',
111
+ {
112
+ endOfLine: 'lf',
113
+ parser: 'babel',
114
+ singleQuote: true,
115
+ trailingComma: 'all',
116
+ },
117
+ ],
114
118
  'promise/always-return': 'warn',
119
+ 'promise/catch-or-return': 'warn',
115
120
  'promise/no-return-wrap': 'warn',
116
121
  'promise/param-names': 'error',
117
- 'promise/catch-or-return': 'warn',
118
-
119
- // Better import sorting
120
- 'simple-import-sort/imports': 'warn',
122
+ 'security/detect-non-literal-regexp': 'warn',
123
+ 'security/detect-object-injection': 'warn',
124
+ 'security/detect-possible-timing-attacks': 'warn',
121
125
  'simple-import-sort/exports': 'warn',
122
-
123
- // Better code organization
124
- 'perfectionist/sort-objects': ['warn', {
125
- type: 'natural',
126
- order: 'asc',
127
- }],
128
- 'perfectionist/sort-named-imports': 'warn',
129
-
130
- // Security and testing
131
- 'no-secrets/no-secrets': ['warn', { tolerance: 4.5 }],
132
- 'no-only-tests/no-only-tests': 'warn',
133
-
134
- // Enhanced import rules
135
- 'import/no-cycle': 'warn',
136
- 'import/no-useless-path-segments': 'warn',
137
- 'import/no-anonymous-default-export': 'warn',
138
-
139
- // SonarJS rules
126
+ 'simple-import-sort/imports': 'warn',
140
127
  'sonarjs/cognitive-complexity': ['error', 15],
128
+ 'sonarjs/max-switch-cases': ['warn', 10],
141
129
  'sonarjs/no-duplicate-string': ['error', { threshold: 5 }],
130
+ 'sonarjs/no-duplicated-branches': 'error',
142
131
  'sonarjs/no-redundant-boolean': 'error',
143
- 'sonarjs/prefer-immediate-return': 'error',
144
132
  'sonarjs/no-small-switch': 'warn',
145
- 'sonarjs/no-duplicated-branches': 'error',
146
- 'sonarjs/max-switch-cases': ['warn', 10],
133
+ 'sonarjs/prefer-immediate-return': 'error',
134
+ 'unicorn/expiring-todo-comments': 'off',
147
135
  },
148
136
  settings: {
149
- 'json/json-with-comments-files': [],
150
- polyfills: ['Promise', 'fetch', 'URLSearchParams', 'Array.prototype.includes'],
151
- jest: {
152
- version: 29,
137
+ boundaries: {
138
+ elements: [
139
+ { pattern: 'app/*', type: 'app' },
140
+ { pattern: 'pages/*', type: 'pages' },
141
+ { pattern: 'components/*', type: 'components' },
142
+ { pattern: 'hooks/*', type: 'hooks' },
143
+ { pattern: 'utils/*', type: 'utils' },
144
+ { pattern: 'services/*', type: 'services' },
145
+ { pattern: 'types/*', type: 'types' },
146
+ { pattern: 'config/*', type: 'config' },
147
+ ],
153
148
  },
149
+ 'import/extensions': ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'],
154
150
  'import/parsers': {
155
151
  '@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
156
152
  },
157
- 'import/extensions': ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'],
158
153
  'import/resolver': {
159
154
  node: {
160
- extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs']
161
- }
155
+ extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'],
156
+ },
162
157
  },
163
- boundaries: {
164
- elements: [
165
- { type: 'app', pattern: 'app/*' },
166
- { type: 'pages', pattern: 'pages/*' },
167
- { type: 'components', pattern: 'components/*' },
168
- { type: 'hooks', pattern: 'hooks/*' },
169
- { type: 'utils', pattern: 'utils/*' },
170
- { type: 'services', pattern: 'services/*' },
171
- { type: 'types', pattern: 'types/*' },
172
- { type: 'config', pattern: 'config/*' }
173
- ]
174
- }
158
+ jest: {
159
+ version: 29,
160
+ },
161
+ 'json/json-with-comments-files': [],
162
+ polyfills: [
163
+ 'Promise',
164
+ 'fetch',
165
+ 'URLSearchParams',
166
+ 'Array.prototype.includes',
167
+ ],
175
168
  },
176
169
  },
177
170
  ...baseOverrides,
178
171
  ];
179
172
 
180
173
  export default config;
181
- export { baseRules } from './rules.js';
174
+
182
175
  export { baseOverrides } from './overrides.js';
176
+ export { baseRules } from './rules.js';
package/overrides.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
- import typescriptParser from '@typescript-eslint/parser';
3
+
4
4
  import typeScriptPlugin from '@typescript-eslint/eslint-plugin';
5
5
  import importPlugin from 'eslint-plugin-import';
6
- import markdownPlugin from 'eslint-plugin-markdownlint';
7
6
  import jestPlugin from 'eslint-plugin-jest';
7
+ import markdownPlugin from 'eslint-plugin-markdownlint';
8
8
 
9
- const currentDir = path.dirname(fileURLToPath(import.meta.url));
9
+ const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
10
10
 
11
11
  const ts = {
12
12
  files: ['*.ts', '*.tsx'],
@@ -16,9 +16,9 @@ const ts = {
16
16
  },
17
17
  ecmaVersion: 'latest',
18
18
  extraFileExtensions: ['.vue', '.svelte'],
19
- sourceType: 'module',
20
19
  project: 'tsconfig.json',
21
- tsconfigRootDir: path.join(currentDir, '../../..'),
20
+ sourceType: 'module',
21
+ tsconfigRootDir: path.join(currentDirectory, '../../..'),
22
22
  },
23
23
  plugins: {
24
24
  '@typescript-eslint': typeScriptPlugin,
@@ -29,12 +29,35 @@ const ts = {
29
29
  ...typeScriptPlugin.configs['recommended-requiring-type-checking'].rules,
30
30
  ...importPlugin.configs.typescript.rules,
31
31
  '@typescript-eslint/class-methods-use-this': 'off',
32
+ '@typescript-eslint/consistent-generic-constructors': [
33
+ 'error',
34
+ 'constructor',
35
+ ],
36
+ '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'],
37
+ '@typescript-eslint/consistent-type-assertions': [
38
+ 'error',
39
+ {
40
+ assertionStyle: 'as',
41
+ objectLiteralTypeAssertions: 'never',
42
+ },
43
+ ],
44
+ '@typescript-eslint/consistent-type-exports': [
45
+ 'error',
46
+ { fixMixedExportsWithInlineTypeSpecifier: true },
47
+ ],
32
48
  '@typescript-eslint/consistent-type-imports': [
33
49
  'error',
34
50
  {
35
- prefer: 'type-imports',
36
- fixStyle: 'separate-type-imports',
37
51
  disallowTypeAnnotations: false,
52
+ fixStyle: 'separate-type-imports',
53
+ prefer: 'type-imports',
54
+ },
55
+ ],
56
+ '@typescript-eslint/explicit-function-return-type': [
57
+ 'warn',
58
+ {
59
+ allowExpressions: true,
60
+ allowTypedFunctionExpressions: true,
38
61
  },
39
62
  ],
40
63
  '@typescript-eslint/explicit-member-accessibility': [
@@ -45,8 +68,8 @@ const ts = {
45
68
  accessors: 'explicit',
46
69
  constructors: 'no-public',
47
70
  methods: 'explicit',
48
- properties: 'off',
49
71
  parameterProperties: 'explicit',
72
+ properties: 'off',
50
73
  },
51
74
  },
52
75
  ],
@@ -74,134 +97,120 @@ const ts = {
74
97
  ],
75
98
  },
76
99
  ],
100
+ '@typescript-eslint/method-signature-style': ['error', 'property'],
77
101
  '@typescript-eslint/naming-convention': [
78
102
  'error',
79
103
  {
104
+ format: ['PascalCase'],
80
105
  selector: ['typeLike'],
81
- format: ['PascalCase']
82
106
  },
83
107
  {
84
- selector: ['typeParameter'],
85
108
  format: ['PascalCase'],
86
- prefix: ['T']
109
+ prefix: ['T'],
110
+ selector: ['typeParameter'],
87
111
  },
88
112
  {
89
- selector: ['interface'],
90
- format: ['PascalCase'],
91
113
  custom: {
92
- regex: '^I[A-Z]',
93
114
  match: false,
94
- message: 'Interface name should not be prefixed with "I"'
95
- }
96
- }
115
+ message: 'Interface name should not be prefixed with "I"',
116
+ regex: '^I[A-Z]',
117
+ },
118
+ format: ['PascalCase'],
119
+ selector: ['interface'],
120
+ },
121
+ ],
122
+ '@typescript-eslint/no-confusing-void-expression': [
123
+ 'error',
124
+ { ignoreArrowShorthand: true },
97
125
  ],
126
+ '@typescript-eslint/no-explicit-any': 'warn',
98
127
  '@typescript-eslint/no-extraneous-class': [
99
128
  'warn',
100
129
  {
101
- allowEmpty: true,
102
130
  allowConstructorOnly: false,
131
+ allowEmpty: true,
103
132
  allowStaticOnly: false,
104
133
  allowWithDecorator: false,
105
134
  },
106
135
  ],
107
- '@typescript-eslint/no-inferrable-types': 'off',
108
- '@typescript-eslint/no-magic-numbers': 'off',
109
- '@typescript-eslint/no-unnecessary-condition': 'off',
110
- '@typescript-eslint/parameter-properties': ['error', { prefer: 'parameter-property' }],
111
- '@typescript-eslint/prefer-nullish-coalescing': 'off',
112
- '@typescript-eslint/prefer-readonly': 'off',
113
- '@typescript-eslint/prefer-readonly-parameter-types': 'off',
114
- '@typescript-eslint/strict-boolean-expressions': 'off',
115
- '@typescript-eslint/unbound-method': 'off',
116
- '@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
117
- '@typescript-eslint/consistent-type-assertions': [
118
- 'error',
119
- {
120
- assertionStyle: 'as',
121
- objectLiteralTypeAssertions: 'never',
122
- },
123
- ],
124
- '@typescript-eslint/explicit-function-return-type': [
125
- 'warn',
126
- {
127
- allowExpressions: true,
128
- allowTypedFunctionExpressions: true,
129
- },
130
- ],
131
- '@typescript-eslint/no-explicit-any': 'warn',
132
136
  '@typescript-eslint/no-floating-promises': 'error',
133
137
  '@typescript-eslint/no-for-in-array': 'error',
134
138
  '@typescript-eslint/no-import-type-side-effects': 'error',
139
+ '@typescript-eslint/no-inferrable-types': 'off',
140
+ '@typescript-eslint/no-magic-numbers': 'off',
135
141
  '@typescript-eslint/no-misused-promises': [
136
142
  'error',
137
143
  {
138
144
  checksVoidReturn: false,
139
145
  },
140
146
  ],
141
- '@typescript-eslint/no-unnecessary-type-constraint': 'error',
147
+ '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
148
+ '@typescript-eslint/no-redundant-type-constituents': 'error',
142
149
  '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
150
+ '@typescript-eslint/no-unnecessary-condition': 'off',
143
151
  '@typescript-eslint/no-unnecessary-qualifier': 'error',
152
+ '@typescript-eslint/no-unnecessary-type-arguments': 'error',
153
+ '@typescript-eslint/no-unnecessary-type-constraint': 'error',
154
+ '@typescript-eslint/no-unsafe-argument': 'error',
144
155
  '@typescript-eslint/no-unsafe-declaration-merging': 'error',
145
156
  '@typescript-eslint/no-unsafe-enum-comparison': 'error',
146
- '@typescript-eslint/prefer-optional-chain': 'error',
157
+ '@typescript-eslint/no-unsafe-member-access': 'error',
158
+ '@typescript-eslint/no-unsafe-unary-minus': 'error',
159
+ '@typescript-eslint/no-useless-template-literals': 'error',
160
+ '@typescript-eslint/parameter-properties': [
161
+ 'error',
162
+ { prefer: 'parameter-property' },
163
+ ],
164
+ '@typescript-eslint/prefer-enum-initializers': 'error',
165
+ '@typescript-eslint/prefer-find': 'error',
166
+ '@typescript-eslint/prefer-includes': 'error',
167
+ '@typescript-eslint/prefer-literal-enum-member': 'error',
168
+ '@typescript-eslint/prefer-nullish-coalescing': 'off',
169
+ '@typescript-eslint/prefer-optional-chain': [
170
+ 'error',
171
+ {
172
+ checkAny: true,
173
+ checkBigInt: true,
174
+ checkBoolean: true,
175
+ checkNumber: true,
176
+ checkString: true,
177
+ checkUnknown: true,
178
+ },
179
+ ],
180
+ '@typescript-eslint/prefer-readonly': 'off',
181
+ '@typescript-eslint/prefer-readonly-parameter-types': 'off',
147
182
  '@typescript-eslint/prefer-reduce-type-parameter': 'error',
183
+ '@typescript-eslint/prefer-regexp-exec': 'error',
148
184
  '@typescript-eslint/prefer-return-this-type': 'error',
149
- 'deprecation/deprecation': 'warn',
150
- 'prettier/prettier': ['warn', { parser: 'typescript' }],
151
- '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'],
152
- '@typescript-eslint/consistent-generic-constructors': ['error', 'constructor'],
153
- '@typescript-eslint/no-confusing-void-expression': [
185
+ '@typescript-eslint/prefer-string-starts-ends-with': 'error',
186
+ '@typescript-eslint/prefer-ts-expect-error': 'error',
187
+ '@typescript-eslint/promise-function-async': [
154
188
  'error',
155
- { ignoreArrowShorthand: true }
189
+ {
190
+ checkArrowFunctions: true,
191
+ checkFunctionDeclarations: true,
192
+ checkFunctionExpressions: true,
193
+ checkMethodDeclarations: true,
194
+ },
156
195
  ],
157
- '@typescript-eslint/prefer-string-starts-ends-with': 'error',
158
- '@typescript-eslint/promise-function-async': 'error',
159
196
  '@typescript-eslint/require-array-sort-compare': [
160
197
  'error',
161
- { ignoreStringArrays: true }
198
+ { ignoreStringArrays: true },
162
199
  ],
200
+ '@typescript-eslint/sort-type-constituents': 'error',
163
201
  '@typescript-eslint/strict-boolean-expressions': [
164
202
  'error',
165
203
  {
166
- allowString: false,
204
+ allowNullableObject: false,
167
205
  allowNumber: false,
168
- allowNullableObject: false
169
- }
206
+ allowString: false,
207
+ },
170
208
  ],
171
- '@typescript-eslint/method-signature-style': ['error', 'property'],
172
- '@typescript-eslint/prefer-enum-initializers': 'error',
173
- '@typescript-eslint/prefer-literal-enum-member': 'error',
174
- '@typescript-eslint/prefer-ts-expect-error': 'error',
175
- '@typescript-eslint/sort-type-constituents': 'error',
176
209
  '@typescript-eslint/switch-exhaustiveness-check': 'error',
177
- '@typescript-eslint/prefer-optional-chain': ['error', {
178
- checkAny: true,
179
- checkUnknown: true,
180
- checkString: true,
181
- checkNumber: true,
182
- checkBoolean: true,
183
- checkBigInt: true
184
- }],
185
- '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
186
- '@typescript-eslint/no-redundant-type-constituents': 'error',
187
- '@typescript-eslint/no-unsafe-unary-minus': 'error',
188
- '@typescript-eslint/no-useless-template-literals': 'error',
189
- '@typescript-eslint/prefer-find': 'error',
190
- '@typescript-eslint/consistent-type-exports': [
191
- 'error',
192
- { fixMixedExportsWithInlineTypeSpecifier: true }
193
- ],
194
- '@typescript-eslint/no-unnecessary-type-arguments': 'error',
195
- '@typescript-eslint/no-unsafe-argument': 'error',
196
- '@typescript-eslint/no-unsafe-member-access': 'error',
197
- '@typescript-eslint/prefer-includes': 'error',
198
- '@typescript-eslint/prefer-regexp-exec': 'error',
199
- '@typescript-eslint/promise-function-async': ['error', {
200
- checkArrowFunctions: true,
201
- checkFunctionDeclarations: true,
202
- checkFunctionExpressions: true,
203
- checkMethodDeclarations: true
204
- }]
210
+ '@typescript-eslint/unbound-method': 'off',
211
+ '@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
212
+ 'deprecation/deprecation': 'warn',
213
+ 'prettier/prettier': ['warn', { parser: 'typescript' }],
205
214
  },
206
215
  settings: {
207
216
  'import/parsers': {
@@ -241,8 +250,8 @@ const yaml = {
241
250
  files: ['*.yaml', '*.yml'],
242
251
  parser: 'yaml-eslint-parser',
243
252
  rules: {
244
- 'yml/quotes': ['warn', { prefer: 'double', avoidEscape: true }],
245
253
  'prettier/prettier': ['warn', { parser: 'yaml', singleQuote: false }],
254
+ 'yml/quotes': ['warn', { avoidEscape: true, prefer: 'double' }],
246
255
  },
247
256
  };
248
257
 
@@ -313,8 +322,8 @@ const mdJson = {
313
322
  };
314
323
 
315
324
  const html = {
316
- files: ['*.html'],
317
325
  extends: ['plugin:@html-eslint/recommended'],
326
+ files: ['*.html'],
318
327
  parser: '@html-eslint/parser',
319
328
  plugins: ['@html-eslint'],
320
329
  rules: {
@@ -326,9 +335,9 @@ const html = {
326
335
  'warn',
327
336
  { selfClosing: 'always' },
328
337
  ],
338
+ 'prettier/prettier': ['warn', { parser: 'html' }],
329
339
  'spaced-comment': 'off',
330
340
  strict: 'off',
331
- 'prettier/prettier': ['warn', { parser: 'html' }],
332
341
  },
333
342
  };
334
343
 
@@ -351,58 +360,58 @@ const json5 = {
351
360
  };
352
361
 
353
362
  const jestJs = {
363
+ env: {
364
+ jest: true,
365
+ },
366
+ extends: ['plugin:jest/all'],
354
367
  files: ['*.test.js', '**/__tests__/**/*.js'],
355
368
  plugins: {
356
369
  jest: jestPlugin,
357
370
  },
358
- extends: ['plugin:jest/all'],
359
- env: {
360
- jest: true,
361
- },
362
371
  rules: {
363
372
  'jest/prefer-spy-on': 'warn',
364
373
  'jest/require-top-level-describe': 'error',
365
- 'unicorn/no-array-callback-reference': 'off',
366
374
  'jest/unbound-method': 'off',
375
+ 'unicorn/no-array-callback-reference': 'off',
367
376
  'unicorn/prevent-abbreviations': [
368
377
  'warn',
369
378
  {
370
379
  ignore: [/e2e/],
371
- }
380
+ },
372
381
  ],
373
382
  },
374
383
  };
375
384
 
376
385
  const jestTs = {
386
+ env: {
387
+ jest: true,
388
+ },
389
+ extends: ['plugin:jest/all'],
377
390
  files: ['*.test.ts', '**/__tests__/**/*.ts'],
378
391
  parser: '@typescript-eslint/parser',
379
392
  plugins: {
380
393
  '@typescript-eslint': typeScriptPlugin,
381
394
  jest: jestPlugin,
382
395
  },
383
- extends: ['plugin:jest/all'],
384
- env: {
385
- jest: true,
386
- },
387
396
  rules: {
388
397
  'jest/prefer-spy-on': 'warn',
389
398
  'jest/require-top-level-describe': 'error',
390
- 'unicorn/no-array-callback-reference': 'off',
391
399
  'jest/unbound-method': 'off',
400
+ 'unicorn/no-array-callback-reference': 'off',
392
401
  'unicorn/prevent-abbreviations': [
393
402
  'warn',
394
403
  {
395
404
  ignore: [/e2e/],
396
- }
405
+ },
397
406
  ],
398
407
  },
399
408
  };
400
409
 
401
410
  const cypress = {
402
- mdJson,
411
+ extends: ['plugin:cypress/recommended'],
403
412
  files: ['*.cy.*'],
413
+ mdJson,
404
414
  plugins: ['cypress'],
405
- extends: ['plugin:cypress/recommended'],
406
415
  };
407
416
 
408
417
  export const baseOverrides = [
package/package.json CHANGED
@@ -1,56 +1,55 @@
1
1
  {
2
2
  "name": "@mikey-pro/eslint-config",
3
- "version": "8.0.19",
3
+ "version": "8.1.1",
4
4
  "description": "Mikey Pro ESLint configuration",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "sideEffects": false,
8
8
  "dependencies": {
9
- "@babel/core": "^7.26.7",
10
- "@babel/eslint-parser": "^7.26.5",
9
+ "@babel/core": "^7.26.8",
10
+ "@babel/eslint-parser": "^7.26.8",
11
11
  "@babel/eslint-plugin": "^7.25",
12
12
  "@babel/preset-env": "^7.26",
13
13
  "@cypress/eslint-plugin-json": "^3.2.3",
14
- "@html-eslint/eslint-plugin": "^0.33.1",
15
- "@html-eslint/parser": "^0.33.0",
16
- "@typescript-eslint/eslint-plugin": "^8.22.0",
17
- "@typescript-eslint/parser": "^8.22.0",
14
+ "@eslint/js": "^9.20.0",
15
+ "@html-eslint/eslint-plugin": "^0.34.0",
16
+ "@html-eslint/parser": "^0.34.0",
17
+ "@typescript-eslint/eslint-plugin": "^8.24.0",
18
+ "@typescript-eslint/parser": "^8.24.0",
19
+ "eslint": "^9.20.1",
18
20
  "eslint-config-prettier": "^10.0.1",
19
21
  "eslint-import-resolver-typescript": "^3.7.0",
22
+ "eslint-plugin-boundaries": "^5.0.1",
20
23
  "eslint-plugin-compat": "^6.0.2",
21
24
  "eslint-plugin-css-modules": "^2.12",
22
25
  "eslint-plugin-cypress": "^4.1.0",
23
26
  "eslint-plugin-import": "^2.31.0",
24
27
  "eslint-plugin-jest": "^28.11.0",
28
+ "eslint-plugin-jest-dom": "^5.5.0",
25
29
  "eslint-plugin-jsonc": "^2.19.1",
26
30
  "eslint-plugin-markdownlint": "^0.6.0",
27
31
  "eslint-plugin-n": "^17.15.1",
28
- "eslint-plugin-only-warn": "^1.1.0",
29
- "eslint-plugin-perfectionist": "^4.7.0",
30
- "eslint-plugin-no-secrets": "^2.1.1",
31
32
  "eslint-plugin-no-only-tests": "^3.3.0",
33
+ "eslint-plugin-no-secrets": "^2.2.1",
34
+ "eslint-plugin-only-warn": "^1.1.0",
35
+ "eslint-plugin-optimize-regex": "^1.2.1",
36
+ "eslint-plugin-perfectionist": "^4.8.0",
32
37
  "eslint-plugin-prettier": "^5.2.3",
33
38
  "eslint-plugin-promise": "^7.2.1",
39
+ "eslint-plugin-regexp": "^2.7.0",
34
40
  "eslint-plugin-security": "^3.0.1",
35
41
  "eslint-plugin-simple-import-sort": "^12.1.1",
42
+ "eslint-plugin-sonarjs": "^3.0.1",
43
+ "eslint-plugin-sort-destructure-keys": "^2.0.0",
44
+ "eslint-plugin-testing-library": "^7.1.1",
36
45
  "eslint-plugin-toml": "^0.12.0",
37
46
  "eslint-plugin-unicorn": "^56.0.1",
47
+ "eslint-plugin-write-good-comments": "^0.2.0",
38
48
  "eslint-plugin-yml": "^1.16.0",
39
- "eslint-plugin-testing-library": "^7.1.1",
40
- "eslint-plugin-jest-dom": "^5.5.0",
41
- "eslint-plugin-deprecation": "^3.0.0",
42
- "postcss": "^8.5.1",
49
+ "globals": "^15.15.0",
50
+ "postcss": "^8.5.2",
43
51
  "postcss-scss": "^4.0.9",
44
- "yaml-eslint-parser": "^1.2.3",
45
- "eslint-plugin-sonarjs": "^3.0.1",
46
- "eslint-plugin-regexp": "^2.7.0",
47
- "eslint-plugin-etc": "^2.0.3",
48
- "eslint-plugin-typescript-sort-keys": "^3.3.0",
49
- "eslint-plugin-sort-destructure-keys": "^2.0.0",
50
- "eslint-plugin-write-good-comments": "^0.2.0",
51
- "eslint-plugin-boundaries": "^5.0.1",
52
- "eslint-plugin-radar": "^0.2.1",
53
- "eslint-plugin-optimize-regex": "^1.2.1"
52
+ "yaml-eslint-parser": "^1.2.3"
54
53
  },
55
54
  "peerDependenciesMeta": {
56
55
  "typescript": {
package/rules.js CHANGED
@@ -1,23 +1,62 @@
1
1
  export const baseRules = {
2
+ 'boundaries/element-types': [
3
+ 'warn',
4
+ {
5
+ default: 'disallow',
6
+ rules: [
7
+ { allow: ['utils'], from: 'utils' },
8
+ { allow: ['features', 'shared', 'utils'], from: 'features' },
9
+ { allow: ['shared', 'utils'], from: 'shared' },
10
+ ],
11
+ },
12
+ ],
2
13
  camelcase: [
3
14
  'error',
4
15
  {
5
- properties: 'never',
6
16
  ignoreDestructuring: true,
7
- ignoreImports: true,
8
17
  ignoreGlobals: true,
18
+ ignoreImports: true,
19
+ properties: 'never',
9
20
  },
10
21
  ],
11
22
  'class-methods-use-this': 'off',
23
+ complexity: ['error', { max: 15 }],
12
24
  'constructor-super': 'warn',
13
25
  'dot-notation': 'warn',
26
+ 'filenames/match-regex': 'off',
14
27
  'func-names': 'off',
15
- 'import/extensions': ['warn', 'ignorePackages', { ts: 'never' }],
16
- 'import/no-commonjs': 'off',
28
+ 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
17
29
  'import/default': 'off',
30
+ 'import/extensions': ['warn', 'ignorePackages', { ts: 'never' }],
18
31
  'import/named': 'off',
19
32
  'import/namespace': 'off',
33
+ 'import/no-commonjs': 'off',
34
+ 'import/no-cycle': [
35
+ 'error',
36
+ {
37
+ ignoreExternal: true,
38
+ maxDepth: 1,
39
+ },
40
+ ],
41
+ 'import/no-duplicates': ['error', { 'prefer-inline': true }],
42
+ 'import/no-empty-named-blocks': 'error',
43
+ 'import/no-extraneous-dependencies': [
44
+ 'error',
45
+ {
46
+ devDependencies: ['**/*.test.{js,ts}', '**/*.spec.{js,ts}', '**/test/**'],
47
+ },
48
+ ],
49
+ 'import/no-import-module-exports': 'error',
20
50
  'import/no-named-as-default-member': 'off',
51
+ 'import/no-namespace': 'error',
52
+ 'import/no-relative-packages': 'error',
53
+ 'import/no-relative-parent-imports': [
54
+ 'error',
55
+ {
56
+ ignore: ['@/components', '@/utils', '@/types'],
57
+ },
58
+ ],
59
+ 'import/no-self-import': 'error',
21
60
  'import/no-unresolved': [
22
61
  'error',
23
62
  { amd: true, commonjs: true, ignore: ['^node:'] },
@@ -33,10 +72,27 @@ export const baseRules = {
33
72
  ],
34
73
  'jsx-quotes': 'warn',
35
74
  'keyword-spacing': 'warn',
75
+ 'logical-assignment-operators': [
76
+ 'warn',
77
+ 'always',
78
+ { enforceForIfStatements: true },
79
+ ],
80
+ 'max-classes-per-file': ['error', 1],
81
+ 'n/no-unsupported-features/es-syntax': [
82
+ 'error',
83
+ {
84
+ ignores: ['modules', 'dynamicImport'],
85
+ version: '>=18.0.0',
86
+ },
87
+ ],
88
+ 'no-array-constructor': 'error',
89
+ 'no-await-in-loop': 'warn',
36
90
  'no-caller': 'warn',
37
91
  'no-confusing-arrow': 'warn',
38
92
  'no-console': 'off',
39
93
  'no-const-assign': 'warn',
94
+ 'no-constant-binary-expression': 'error',
95
+ 'no-constant-condition': 'error',
40
96
  'no-delete-var': 'warn',
41
97
  'no-dupe-class-members': 'warn',
42
98
  'no-dupe-keys': 'warn',
@@ -44,16 +100,22 @@ export const baseRules = {
44
100
  'no-else-return': 'warn',
45
101
  'no-empty': 'off',
46
102
  'no-empty-pattern': 'off',
47
- 'no-extra-parens': 'off',
48
103
  'no-extra-bind': 'warn',
104
+ 'no-extra-parens': 'off',
49
105
  'no-extra-semi': 'warn',
50
106
  'no-floating-decimal': 'warn',
107
+ 'no-implicit-coercion': [
108
+ 'error',
109
+ { boolean: false, number: true, string: true },
110
+ ],
51
111
  'no-iterator': 'warn',
52
112
  'no-lonely-if': 'warn',
53
113
  'no-mixed-spaces-and-tabs': ['warn', 'smart-tabs'],
54
114
  'no-multi-str': 'warn',
115
+ 'no-new-object': 'error',
55
116
  'no-new-wrappers': 'warn',
56
117
  'no-process-exit': 'off',
118
+ 'no-promise-executor-return': ['error', { allowVoid: true }],
57
119
  'no-proto': 'warn',
58
120
  'no-redeclare': 'warn',
59
121
  'no-restricted-syntax': [
@@ -74,13 +136,14 @@ export const baseRules = {
74
136
  selector: 'WithStatement',
75
137
  },
76
138
  {
77
- selector: "CallExpression[callee.property.name='reduce'][arguments.length<2]",
78
- message: 'Provide initialValue to reduce'
139
+ message: 'Provide initialValue to reduce',
140
+ selector:
141
+ "CallExpression[callee.property.name='reduce'][arguments.length<2]",
79
142
  },
80
143
  {
144
+ message: 'Use for...of instead',
81
145
  selector: "CallExpression[callee.property.name='forEach']",
82
- message: 'Use for...of instead'
83
- }
146
+ },
84
147
  ],
85
148
  'no-shadow': 'off',
86
149
  'no-shadow-restricted-names': 'warn',
@@ -89,6 +152,9 @@ export const baseRules = {
89
152
  'no-undef-init': 'warn',
90
153
  'no-underscore-dangle': 'off',
91
154
  'no-unneeded-ternary': 'warn',
155
+ 'no-unreachable': 'error',
156
+ 'no-unsafe-optional-chaining': 'error',
157
+ 'no-unused-private-class-members': 'warn',
92
158
  'no-unused-vars': [
93
159
  'warn',
94
160
  {
@@ -107,7 +173,25 @@ export const baseRules = {
107
173
  'no-with': 'warn',
108
174
  'object-curly-spacing': ['off', 'always'],
109
175
  'object-shorthand': 'warn',
176
+ 'optimize-regex/optimize-regex': 'warn',
177
+ 'perfectionist/sort-named-imports': [
178
+ 'error',
179
+ {
180
+ 'ignore-case': true,
181
+ order: 'asc',
182
+ type: 'natural',
183
+ },
184
+ ],
185
+ 'perfectionist/sort-objects': [
186
+ 'error',
187
+ {
188
+ order: 'asc',
189
+ 'spread-last': true,
190
+ type: 'natural',
191
+ },
192
+ ],
110
193
  'prefer-arrow-callback': 'warn',
194
+ 'prefer-const': 'warn',
111
195
  'prefer-destructuring': [
112
196
  'warn',
113
197
  {
@@ -115,10 +199,16 @@ export const baseRules = {
115
199
  object: true,
116
200
  },
117
201
  ],
202
+ 'prefer-exponentiation-operator': 'error',
203
+ 'prefer-object-has-own': 'error',
118
204
  'prefer-rest-params': 'warn',
119
205
  'prefer-spread': 'warn',
120
206
  'prefer-template': 'warn',
121
- 'prefer-const': 'warn',
207
+ 'prettier/prettier': ['warn', { parser: 'babel' }],
208
+ 'promise/no-multiple-resolved': 'error',
209
+ 'promise/no-nesting': 'warn',
210
+ 'promise/prefer-await-to-callbacks': 'warn',
211
+ 'promise/prefer-await-to-then': 'warn',
122
212
  'quote-props': ['warn', 'as-needed'],
123
213
  quotes: [
124
214
  'off',
@@ -129,11 +219,20 @@ export const baseRules = {
129
219
  },
130
220
  ],
131
221
  radix: 'warn',
132
- 'filenames/match-regex': 'off',
222
+ 'regexp/no-missing-g-flag': 'error',
133
223
  'require-atomic-updates': ['error', { allowProperties: false }],
134
- 'sort-imports': 'off',
135
224
  'rest-spread-spacing': 'off',
225
+ 'security/detect-buffer-noassert': 'error',
226
+ 'security/detect-child-process': 'warn',
227
+ 'security/detect-disable-mustache-escape': 'error',
228
+ 'security/detect-non-literal-fs-filename': 'error',
229
+ 'security/detect-non-literal-regexp': 'error',
230
+ 'security/detect-non-literal-require': 'error',
231
+ 'security/detect-possible-timing-attacks': 'error',
232
+ 'security/detect-unsafe-regex': 'error',
136
233
  semi: 'off',
234
+ 'sort-destructure-keys/sort-destructure-keys': 'warn',
235
+ 'sort-imports': 'off',
137
236
  'sort-vars': 'warn',
138
237
  'space-before-function-paren': [
139
238
  'off',
@@ -157,6 +256,7 @@ export const baseRules = {
157
256
  ],
158
257
  strict: ['warn', 'never'],
159
258
  'unicode-bom': 'warn',
259
+ 'unicorn/catch-error-name': ['error', { name: 'error' }],
160
260
  'unicorn/filename-case': [
161
261
  'warn',
162
262
  {
@@ -167,144 +267,26 @@ export const baseRules = {
167
267
  ignore: ['.*.md'],
168
268
  },
169
269
  ],
270
+ 'unicorn/import-index': 'warn',
271
+ 'unicorn/no-useless-undefined': ['error', { checkArguments: true }],
272
+ 'unicorn/prefer-array-flat': ['error', { functions: ['flatten'] }],
273
+ 'unicorn/prefer-at': 'error',
274
+ 'unicorn/prefer-blob-reading-methods': 'error',
275
+ 'unicorn/prefer-string-replace-all': 'error',
276
+ 'unicorn/prefer-string-slice': 'error',
277
+ 'unicorn/prefer-type-error': 'error',
170
278
  'unicorn/prevent-abbreviations': [
171
279
  'warn',
172
280
  {
173
281
  allowList: {
174
282
  e2e: true,
283
+ params: true,
175
284
  props: true,
176
285
  ref: true,
177
- params: true
178
286
  },
179
- ignore: [/e2e/]
180
- }
287
+ ignore: [/e2e/],
288
+ },
181
289
  ],
182
- 'unicorn/import-index': 'warn',
183
- 'prettier/prettier': ['warn', { parser: 'babel' }],
184
-
185
- // Error handling
186
- 'no-await-in-loop': 'warn',
187
- 'no-promise-executor-return': ['error', { allowVoid: true }],
188
- 'no-unsafe-optional-chaining': 'error',
189
-
190
- // Modern practices
191
- 'logical-assignment-operators': ['warn', 'always', { enforceForIfStatements: true }],
192
- 'no-constant-binary-expression': 'error',
193
- 'no-unused-private-class-members': 'warn',
194
-
195
- // Import rules
196
- 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
197
- 'import/no-empty-named-blocks': 'error',
198
-
199
- // Better promises
200
- 'promise/no-multiple-resolved': 'error',
201
- 'promise/prefer-await-to-callbacks': 'warn',
202
-
203
- // Security
204
- 'security/detect-non-literal-fs-filename': 'error',
205
- 'security/detect-unsafe-regex': 'error',
206
- 'security/detect-buffer-noassert': 'error',
207
- 'security/detect-child-process': 'warn',
208
- 'security/detect-disable-mustache-escape': 'error',
209
- 'security/detect-possible-timing-attacks': 'error',
210
- 'security/detect-non-literal-regexp': 'error',
211
- 'security/detect-non-literal-require': 'error',
212
-
213
- 'no-unreachable': 'error',
214
- 'no-constant-condition': 'error',
215
- 'complexity': ['error', { max: 15 }],
216
-
217
- // RegExp
218
- 'regexp/no-missing-g-flag': 'error',
219
-
220
- // Enhanced TypeScript
221
- 'etc/prefer-interface': 'error',
222
-
223
- // Enhanced Import Rules
224
- 'import/no-relative-parent-imports': ['error', {
225
- ignore: ['@/components', '@/utils', '@/types']
226
- }],
227
- 'import/no-extraneous-dependencies': ['error', {
228
- devDependencies: ['**/*.test.{js,ts}', '**/*.spec.{js,ts}', '**/test/**']
229
- }],
230
-
231
- // Better Promise Handling
232
- 'promise/no-nesting': 'warn',
233
- 'promise/prefer-await-to-then': 'warn',
234
-
235
- // Code Organization
236
- 'typescript-sort-keys/interface': 'warn',
237
- 'typescript-sort-keys/string-enum': 'warn',
238
- 'sort-destructure-keys/sort-destructure-keys': 'warn',
239
-
240
- // Code Quality
290
+ 'unicorn/require-post-message-target-origin': 'error',
241
291
  'write-good-comments/write-good-comments': 'warn',
242
-
243
- // Import Safety
244
- 'import/no-cycle': ['error', {
245
- maxDepth: 1,
246
- ignoreExternal: true
247
- }],
248
- 'import/no-relative-packages': 'error',
249
- 'import/no-self-import': 'error',
250
- 'import/no-namespace': 'error',
251
- 'import/no-duplicates': ['error', { 'prefer-inline': true }],
252
- 'import/no-import-module-exports': 'error',
253
-
254
- // Architecture Boundaries
255
- 'boundaries/element-types': [
256
- 'warn',
257
- {
258
- default: 'disallow',
259
- rules: [
260
- { from: 'utils', allow: ['utils'] },
261
- { from: 'features', allow: ['features', 'shared', 'utils'] },
262
- { from: 'shared', allow: ['shared', 'utils'] }
263
- ]
264
- }
265
- ],
266
-
267
- // Performance
268
- 'optimize-regex/optimize-regex': 'warn',
269
-
270
- // Enhanced Security
271
- 'n/no-unsupported-features/es-syntax': ['error', {
272
- version: '>=18.0.0',
273
- ignores: ['modules', 'dynamicImport']
274
- }],
275
-
276
- // Modern JavaScript Features
277
- 'prefer-object-has-own': 'error',
278
- 'unicorn/prefer-string-slice': 'error',
279
- 'unicorn/prefer-array-flat': ['error', { functions: ['flatten'] }],
280
- 'unicorn/prefer-blob-reading-methods': 'error',
281
-
282
- // Memory Optimizations
283
- 'no-array-constructor': 'error',
284
- 'no-new-object': 'error',
285
- 'prefer-exponentiation-operator': 'error',
286
-
287
- // Better Error Handling
288
- 'max-classes-per-file': ['error', 1],
289
- 'unicorn/catch-error-name': ['error', { name: 'error' }],
290
- 'unicorn/no-useless-undefined': ['error', { checkArguments: true }],
291
- 'unicorn/prefer-type-error': 'error',
292
-
293
- // Code Style
294
- 'perfectionist/sort-named-imports': ['error', {
295
- type: 'natural',
296
- order: 'asc',
297
- 'ignore-case': true
298
- }],
299
- 'perfectionist/sort-objects': ['error', {
300
- type: 'natural',
301
- order: 'asc',
302
- 'spread-last': true
303
- }],
304
-
305
- // Advanced Performance
306
- 'no-implicit-coercion': ['error', { boolean: false, number: true, string: true }],
307
- 'unicorn/prefer-at': 'error',
308
- 'unicorn/prefer-string-replace-all': 'error',
309
- 'unicorn/require-post-message-target-origin': 'error'
310
292
  };