@innovixx/eslint-config 2.0.3-alpha.3 → 3.0.0-alpha.2

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 (32) hide show
  1. package/config/configs/base/index.mjs +46 -0
  2. package/{configs/base/rules/best-practices.js → config/configs/base/rules/best-practices.mjs} +7 -1
  3. package/{configs/base/rules/errors.js → config/configs/base/rules/errors.mjs} +5 -1
  4. package/{configs/base/rules/es6.js → config/configs/base/rules/es6.mjs} +12 -4
  5. package/{configs/base/rules/imports.js → config/configs/base/rules/imports.mjs} +24 -18
  6. package/{configs/base/rules/style.js → config/configs/base/rules/style.mjs} +5 -1
  7. package/{configs/base/rules/variables.js → config/configs/base/rules/variables.mjs} +4 -4
  8. package/config/configs/jest/index.mjs +33 -0
  9. package/{configs/jest/rules/jest-dom.js → config/configs/jest/rules/jest-dom.mjs} +5 -1
  10. package/{configs/jest/rules/jest.js → config/configs/jest/rules/jest.mjs} +5 -1
  11. package/config/configs/react/index.mjs +52 -0
  12. package/{configs/react/rules/react-a11y.js → config/configs/react/rules/react-a11y.mjs} +5 -1
  13. package/config/configs/react/rules/react-hooks.mjs +13 -0
  14. package/{configs/react/rules/react.js → config/configs/react/rules/react.mjs} +5 -1
  15. package/config/configs/typescript/index.mjs +30 -0
  16. package/{configs/typescript/rules/variables.js → config/configs/typescript/rules/variables.mjs} +5 -1
  17. package/{configs/typescript/rules/typescript.js → config/configs/typescript/settings/typescript.mjs} +8 -1
  18. package/config/deepMerge.mjs +62 -0
  19. package/config/index.mjs +150 -0
  20. package/demo/components/AnotherComponentTest/index.tsx +3 -0
  21. package/demo/components/ComponentTest/index.tsx +3 -0
  22. package/demo/components/TestComponent/index.tsx +3 -0
  23. package/demo/components/index.ts +3 -0
  24. package/demo/index.ts +1 -0
  25. package/eslint.config.mjs +40 -31
  26. package/package.json +23 -13
  27. package/configs/base/index.js +0 -19
  28. package/configs/index.js +0 -9
  29. package/configs/jest/index.js +0 -14
  30. package/configs/react/index.js +0 -22
  31. package/configs/react/rules/react-hooks.js +0 -11
  32. package/configs/typescript/index.js +0 -14
@@ -0,0 +1,46 @@
1
+ import { configs as regexpPluginConfigs } from 'eslint-plugin-regexp';
2
+ import * as esPluginImport from 'eslint-plugin-import';
3
+ import sortExportAllPlugin from 'eslint-plugin-sort-export-all';
4
+
5
+ import { deepMerge } from '../../deepMerge.mjs';
6
+ import bestPracticesRules from './rules/best-practices.mjs';
7
+ import errorRules from './rules/errors.mjs';
8
+ import es6Rules from './rules/es6.mjs';
9
+ import importRules from './rules/imports.mjs';
10
+ import styleRules from './rules/style.mjs';
11
+ import variableRules from './rules/variables.mjs';
12
+
13
+ /** @type {import('eslint').Linter.Config} */
14
+
15
+ export const index = deepMerge(
16
+ {
17
+ rules: bestPracticesRules.rules,
18
+ },
19
+ {
20
+ rules: errorRules.rules,
21
+ },
22
+ {
23
+ rules: es6Rules.rules,
24
+ },
25
+ {
26
+ rules: importRules.rules,
27
+ },
28
+ {
29
+ rules: styleRules.rules,
30
+ },
31
+ {
32
+ rules: variableRules.rules,
33
+ },
34
+ {
35
+ plugins: {
36
+ regexp: regexpPluginConfigs,
37
+ import: esPluginImport,
38
+ 'sort-export-all': sortExportAllPlugin,
39
+ },
40
+ },
41
+ {
42
+ settings: importRules.settings,
43
+ },
44
+ );
45
+
46
+ export default index;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const bestPracticesRules = {
2
4
  rules: {
3
5
  // enforces getter/setter pairs in objects
4
6
  'accessor-pairs': 'off',
@@ -343,6 +345,8 @@ module.exports = {
343
345
  // https://eslint.org/docs/rules/require-unicode-regexp
344
346
  'require-unicode-regexp': 'off',
345
347
 
348
+ 'sort-export-all/sort-export-all': 'warn',
349
+
346
350
  // requires to declare all vars on top of their containing scope
347
351
  'vars-on-top': 'error',
348
352
 
@@ -354,3 +358,5 @@ module.exports = {
354
358
  yoda: 'error',
355
359
  },
356
360
  };
361
+
362
+ export default bestPracticesRules;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const errorRules = {
2
4
  rules: {
3
5
  // Enforce “for” loop update clause moving the counter in the right direction
4
6
  // https://eslint.org/docs/rules/for-direction
@@ -152,3 +154,5 @@ module.exports = {
152
154
  'valid-typeof': ['error', { requireStringLiterals: true }],
153
155
  },
154
156
  };
157
+
158
+ export default errorRules;
@@ -1,9 +1,15 @@
1
- module.exports = {
2
- env: {
3
- es6: true,
1
+ import globals from 'globals';
2
+
3
+ /** @type {import('eslint').Linter.Config} */
4
+
5
+ const es6Rules = {
6
+ languageOptions: {
7
+ globals: {
8
+ ...globals.es2015,
9
+ },
4
10
  },
5
11
  parserOptions: {
6
- ecmaVersion: 6,
12
+ ecmaVersion: 'latest',
7
13
  sourceType: 'module',
8
14
  ecmaFeatures: {
9
15
  generators: false,
@@ -174,3 +180,5 @@ module.exports = {
174
180
  'yield-star-spacing': ['error', 'after'],
175
181
  },
176
182
  };
183
+
184
+ export default es6Rules;
@@ -1,30 +1,34 @@
1
- module.exports = {
2
- env: {
3
- es6: true,
1
+ import globals from "globals";
2
+ import importPlugin from "eslint-plugin-import";
3
+
4
+ /** @type {import('eslint').Linter.Config} */
5
+
6
+ const importRules = {
7
+ languageOptions: {
8
+ globals: {
9
+ globals: {
10
+ ...globals.es2015,
11
+ }
12
+ }
4
13
  },
5
14
  parserOptions: {
6
- ecmaVersion: 6,
15
+ ecmaVersion: 'latest',
7
16
  sourceType: 'module',
8
17
  },
9
- plugins: [
10
- 'import',
11
- ],
18
+ plugins: {
19
+ import: importPlugin,
20
+ },
12
21
  settings: {
13
22
  'import/resolver': {
14
23
  node: {
15
- extensions: ['.mjs', '.js', '.json'],
24
+ extensions: [
25
+ '.ts',
26
+ '.tsx',
27
+ '.jsx',
28
+ '.js',
29
+ ],
16
30
  },
17
31
  },
18
- 'import/extensions': [
19
- '.js',
20
- '.mjs',
21
- '.jsx',
22
- ],
23
- 'import/core-modules': [],
24
- 'import/ignore': [
25
- 'node_modules',
26
- '\\.(coffee|scss|css|less|hbs|svg|json)$',
27
- ],
28
32
  },
29
33
  rules: {
30
34
  // Static analysis:
@@ -237,3 +241,5 @@ module.exports = {
237
241
  }],
238
242
  },
239
243
  };
244
+
245
+ export default importRules;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const styleRules = {
2
4
  rules: {
3
5
  // enforce line breaks after opening and before closing array brackets
4
6
  // https://eslint.org/docs/rules/array-bracket-newline
@@ -518,3 +520,5 @@ module.exports = {
518
520
  'wrap-regex': 'off',
519
521
  },
520
522
  };
523
+
524
+ export default styleRules;
@@ -1,6 +1,4 @@
1
- const confusingBrowserGlobals = require('confusing-browser-globals');
2
-
3
- module.exports = {
1
+ const variableRules = {
4
2
  rules: {
5
3
  // enforce or disallow variable initializations at definition
6
4
  'init-declarations': 'off',
@@ -16,7 +14,7 @@ module.exports = {
16
14
  'no-label-var': 'error',
17
15
 
18
16
  // disallow specific globals
19
- 'no-restricted-globals': ['error', 'isFinite', 'isNaN'].concat(confusingBrowserGlobals),
17
+ 'no-restricted-globals': ['error', 'isFinite', 'isNaN'],
20
18
 
21
19
  // disallow declaration of variables already declared in the outer scope
22
20
  'no-shadow': 'error',
@@ -42,3 +40,5 @@ module.exports = {
42
40
  'no-use-before-define': ['error', { functions: true, classes: true, variables: true }],
43
41
  },
44
42
  };
43
+
44
+ export default variableRules;
@@ -0,0 +1,33 @@
1
+ import jestPlugin from 'eslint-plugin-jest';
2
+ import jestDomPlugin from 'eslint-plugin-jest-dom';
3
+ import globals from 'globals';
4
+ import jestRules from './rules/jest.mjs';
5
+ import jestDomRules from './rules/jest-dom.mjs';
6
+
7
+ import { deepMerge } from '../../deepMerge.mjs';
8
+
9
+ /** @type {import ('eslint').Linter.Config} */
10
+
11
+ export const index = deepMerge(
12
+ {
13
+ languageOptions: {
14
+ globals: {
15
+ ...globals.jest,
16
+ },
17
+ },
18
+ },
19
+ {
20
+ rules: jestRules.rules,
21
+ },
22
+ {
23
+ rules: jestDomRules.rules,
24
+ },
25
+ {
26
+ plugins: {
27
+ jest: jestPlugin,
28
+ 'jest-dom': jestDomPlugin,
29
+ },
30
+ },
31
+ );
32
+
33
+ export default index;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import ('eslint').Linter.Config} */
2
+
3
+ const jestDomRules = {
2
4
  rules: {
3
5
  'jest-dom/prefer-checked': 'error',
4
6
  'jest-dom/prefer-enabled-disabled': 'error',
@@ -7,3 +9,5 @@ module.exports = {
7
9
  'jest-dom/prefer-to-have-attribute': 'error',
8
10
  },
9
11
  };
12
+
13
+ export default jestDomRules;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import ('eslint').Linter.Config} */
2
+
3
+ const jestRules = {
2
4
  rules: {
3
5
  'jest/consistent-test-it': ['error', { fn: 'it' }],
4
6
  'jest/expect-expect': 'error',
@@ -32,3 +34,5 @@ module.exports = {
32
34
  'jest/valid-title': 'error',
33
35
  },
34
36
  };
37
+
38
+ export default jestRules;
@@ -0,0 +1,52 @@
1
+ import react from 'eslint-plugin-react';
2
+ import jsxA11y from 'eslint-plugin-jsx-a11y';
3
+ import reactHooks from 'eslint-plugin-react-hooks';
4
+ import globals from 'globals';
5
+ import reactRules from './rules/react.mjs';
6
+ import reactA11yRules from './rules/react-a11y.mjs';
7
+ import { deepMerge } from '../../deepMerge.mjs';
8
+ import reactHooksRules from './rules/react-hooks.mjs';
9
+
10
+ /** @type {import ('eslint').Linter.Config} */
11
+
12
+ export const index = deepMerge(
13
+ react.configs['recommended-type-checked'],
14
+ {
15
+ rules: reactRules.rules,
16
+ },
17
+ {
18
+ rules: reactA11yRules.rules,
19
+ },
20
+ {
21
+ rules: reactHooksRules,
22
+ },
23
+ {
24
+ rules: {
25
+ ...reactHooks.configs.recommended.rules,
26
+ },
27
+ },
28
+ {
29
+ languageOptions: {
30
+ globals: {
31
+ ...globals.browser,
32
+ },
33
+ parserOptions: {
34
+ ecmaFeatures: {
35
+ jsx: true,
36
+ },
37
+ },
38
+ },
39
+ plugins: {
40
+ react,
41
+ 'jsx-a11y': jsxA11y,
42
+ 'react-hooks': reactHooks,
43
+ },
44
+ settings: {
45
+ react: {
46
+ version: 'detect',
47
+ },
48
+ },
49
+ },
50
+ );
51
+
52
+ export default index;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const reactA11yRules = {
2
4
  rules: {
3
5
  // Enforce that anchors have content
4
6
  // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
@@ -227,3 +229,5 @@ module.exports = {
227
229
  }],
228
230
  },
229
231
  };
232
+
233
+ export default reactA11yRules;
@@ -0,0 +1,13 @@
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const reactHooksRules = {
4
+ // Enforce Rules of Hooks
5
+ // https://github.com/facebook/react/blob/c11015ff4f610ac2924d1fc6d569a17657a404fd/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
6
+ 'react-hooks/rules-of-hooks': 'error',
7
+
8
+ // Verify the list of the dependencies for Hooks like useEffect and similar
9
+ // https://github.com/facebook/react/blob/1204c789776cb01fbaf3e9f032e7e2ba85a44137/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js
10
+ 'react-hooks/exhaustive-deps': 'error',
11
+ };
12
+
13
+ export default reactHooksRules;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const reactRules = {
2
4
  rules: {
3
5
  // View link below for react rules documentation
4
6
  // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules
@@ -495,3 +497,5 @@ module.exports = {
495
497
  ],
496
498
  },
497
499
  };
500
+
501
+ export default reactRules;
@@ -0,0 +1,30 @@
1
+ import tsPlugin from '@typescript-eslint/eslint-plugin';
2
+ import tsParser from '@typescript-eslint/parser';
3
+ import * as tsImportResolver from 'eslint-import-resolver-typescript';
4
+ import typeScriptSettings from './settings/typescript.mjs';
5
+ import variableRules from './rules/variables.mjs';
6
+ import { deepMerge } from '../../deepMerge.mjs';
7
+
8
+ /** @type {import('eslint').Linter.Config} */
9
+
10
+ export const index = deepMerge(
11
+ {
12
+ settings: typeScriptSettings.settings,
13
+ },
14
+ {
15
+ rules: variableRules.rules,
16
+ },
17
+ {
18
+ plugins: {
19
+ '@typescript-eslint': tsPlugin,
20
+ 'eslint-import-resolver-typescript': tsImportResolver,
21
+ },
22
+ },
23
+ {
24
+ languageOptions: {
25
+ parser: tsParser,
26
+ },
27
+ },
28
+ );
29
+
30
+ export default index;
@@ -1,6 +1,10 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const variableRules = {
2
4
  rules: {
3
5
  // Disallow unused variables.
4
6
  '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
5
7
  },
6
8
  };
9
+
10
+ export default variableRules;
@@ -1,4 +1,6 @@
1
- module.exports = {
1
+ /** @type {import('eslint').Linter.Config} */
2
+
3
+ const typeScriptSettings = {
2
4
  settings: {
3
5
  'import/resolver': {
4
6
  node: {
@@ -6,5 +8,10 @@ module.exports = {
6
8
  },
7
9
  typescript: {},
8
10
  },
11
+ react: {
12
+ version: 'detect',
13
+ },
9
14
  },
10
15
  };
16
+
17
+ export default typeScriptSettings;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * obj2 has priority over obj1
3
+ *
4
+ * Merges obj2 into obj1
5
+ */
6
+ export function _deepMerge(obj1, obj2, doNotMergeInNulls = true) {
7
+ const output = { ...obj1 };
8
+
9
+ // eslint-disable-next-line no-restricted-syntax
10
+ for (const key in obj2) {
11
+ if (Object.prototype.hasOwnProperty.call(obj2, key)) {
12
+ if (doNotMergeInNulls) {
13
+ if (
14
+ (obj2[key] === null || obj2[key] === undefined)
15
+ && obj1[key] !== null
16
+ && obj1[key] !== undefined
17
+ ) {
18
+ // eslint-disable-next-line no-continue
19
+ continue;
20
+ }
21
+ }
22
+
23
+ // Check if both are arrays
24
+ if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
25
+ // Merge each element in the arrays
26
+
27
+ // We need the Array.from, map rather than a normal map because this handles holes in arrays properly. A simple .map would skip holes.
28
+ output[key] = Array.from(obj2[key], (item, index) => {
29
+ if (doNotMergeInNulls) {
30
+ if (
31
+ (item === undefined || item === null)
32
+ && obj1[key][index] !== null
33
+ && obj1[key][index] !== undefined
34
+ ) {
35
+ return obj1[key][index];
36
+ }
37
+ }
38
+
39
+ if (typeof item === 'object' && !Array.isArray(item) && obj1[key][index]) {
40
+ // Deep merge for objects in arrays
41
+ // eslint-disable-next-line no-use-before-define
42
+ return deepMerge(obj1[key][index], item, doNotMergeInNulls);
43
+ }
44
+ return item;
45
+ });
46
+ } else if (typeof obj2[key] === 'object' && !Array.isArray(obj2[key]) && obj1[key]) {
47
+ // Existing behavior for objects
48
+ // eslint-disable-next-line no-use-before-define
49
+ output[key] = deepMerge(obj1[key], obj2[key], doNotMergeInNulls);
50
+ } else {
51
+ // Direct assignment for values
52
+ output[key] = obj2[key];
53
+ }
54
+ }
55
+ }
56
+
57
+ return output;
58
+ }
59
+
60
+ export function deepMerge(...objs) {
61
+ return objs.reduce((acc, obj) => _deepMerge(acc, obj), {});
62
+ }
@@ -0,0 +1,150 @@
1
+ import tseslint from 'typescript-eslint'
2
+ import { configs as regexpPluginConfigs } from 'eslint-plugin-regexp'
3
+ import reactExtends from './configs/react/index.mjs'
4
+ import jestExtends from './configs/jest/index.mjs'
5
+ import globals from 'globals'
6
+ import typescriptParser from '@typescript-eslint/parser'
7
+ import { deepMerge } from './deepMerge.mjs'
8
+
9
+ const baseRules = {
10
+ 'class-methods-use-this': 'off',
11
+ curly: ['warn', 'all'],
12
+ 'arrow-body-style': ['error', 'as-needed', {
13
+ requireReturnForObjectLiteral: false,
14
+ }],
15
+ 'no-restricted-exports': ['warn', { restrictDefaultExports: { direct: true } }],
16
+ 'no-console': 'warn',
17
+ 'no-sparse-arrays': 'off',
18
+ 'no-underscore-dangle': 'off',
19
+ 'no-use-before-define': 'off',
20
+ 'object-shorthand': 'warn',
21
+ 'no-useless-escape': 'warn',
22
+ }
23
+
24
+ const reactA11yRules = {
25
+ 'jsx-a11y/anchor-is-valid': 'warn',
26
+ 'jsx-a11y/control-has-associated-label': 'warn',
27
+ 'jsx-a11y/no-static-element-interactions': 'warn',
28
+ 'jsx-a11y/label-has-associated-control': 'warn',
29
+ }
30
+
31
+ const typeScriptRules = {
32
+ '@typescript-eslint/no-use-before-define': 'off',
33
+
34
+ // Type-aware any rules:
35
+ '@typescript-eslint/no-unsafe-assignment': 'off',
36
+ '@typescript-eslint/no-unsafe-member-access': 'off',
37
+ '@typescript-eslint/no-unsafe-call': 'off',
38
+ '@typescript-eslint/no-unsafe-argument': 'off',
39
+ '@typescript-eslint/no-unsafe-return': 'off',
40
+ '@typescript-eslint/unbound-method': 'warn',
41
+ '@typescript-eslint/consistent-type-imports': 'warn',
42
+ '@typescript-eslint/no-explicit-any': 'warn',
43
+ // Type-aware any rules end
44
+
45
+ // ts-expect preferred over ts-ignore. It will error if the expected error is no longer present.
46
+ '@typescript-eslint/ban-ts-comment': 'warn', // Recommended over deprecated @typescript-eslint/prefer-ts-expect-error: https://github.com/typescript-eslint/typescript-eslint/issues/8333. Set to warn to ease migration.
47
+ // By default, it errors for unused variables. This is annoying, warnings are enough.
48
+ '@typescript-eslint/no-unused-vars': [
49
+ 'warn',
50
+ {
51
+ vars: 'all',
52
+ args: 'after-used',
53
+ ignoreRestSiblings: false,
54
+ argsIgnorePattern: '^_',
55
+ varsIgnorePattern: '^_',
56
+ destructuredArrayIgnorePattern: '^_',
57
+ caughtErrorsIgnorePattern: '^(_|ignore)',
58
+ },
59
+ ],
60
+ '@typescript-eslint/no-base-to-string': 'warn',
61
+ '@typescript-eslint/restrict-template-expressions': 'warn',
62
+ '@typescript-eslint/no-redundant-type-constituents': 'warn',
63
+ '@typescript-eslint/no-unnecessary-type-constraint': 'warn',
64
+ '@typescript-eslint/no-misused-promises': [
65
+ 'error',
66
+ {
67
+ // See https://github.com/typescript-eslint/typescript-eslint/issues/4619 and https://github.com/typescript-eslint/typescript-eslint/pull/4623
68
+ // Don't want something like <button onClick={someAsyncFunction}> to error
69
+ checksVoidReturn: {
70
+ attributes: false,
71
+ arguments: false,
72
+ },
73
+ },
74
+ ],
75
+ '@typescript-eslint/no-empty-object-type': 'warn',
76
+ }
77
+
78
+ /** @typedef {import('eslint').Linter.Config} Config */
79
+
80
+ /** @type {FlatConfig} */
81
+ const baseExtends = deepMerge(
82
+ regexpPluginConfigs['flat/recommended'],
83
+ )
84
+
85
+ /** @type {Config[]} */
86
+ export const rootEslintConfig = [
87
+ {
88
+ name: 'Settings',
89
+ languageOptions: {
90
+ parserOptions: {
91
+ ecmaFeatures: {
92
+ jsx: true,
93
+ }
94
+ },
95
+ ecmaVersion: 'latest',
96
+ sourceType: 'module',
97
+ globals: {
98
+ ...globals.node
99
+ },
100
+ parser: typescriptParser,
101
+ },
102
+ },
103
+ {
104
+ name: 'TypeScript',
105
+ // has 3 entries: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/src/configs/recommended-type-checked.ts
106
+ ...deepMerge(
107
+ baseExtends,
108
+ tseslint.configs.recommendedTypeCheckedOnly[0],
109
+ tseslint.configs.recommendedTypeCheckedOnly[1],
110
+ tseslint.configs.recommendedTypeCheckedOnly[2],
111
+ {
112
+ rules: {
113
+ ...baseRules,
114
+ ...typeScriptRules,
115
+ }
116
+ }
117
+ ),
118
+ files: ['**/*.ts'],
119
+ },
120
+ {
121
+ name: 'TypeScript-React',
122
+ ...deepMerge(
123
+ baseExtends,
124
+ tseslint.configs.recommendedTypeCheckedOnly[0],
125
+ tseslint.configs.recommendedTypeCheckedOnly[1],
126
+ tseslint.configs.recommendedTypeCheckedOnly[2],
127
+ reactExtends,
128
+ {
129
+ rules: {
130
+ ...baseRules,
131
+ ...typeScriptRules,
132
+ ...reactA11yRules,
133
+ }
134
+ }
135
+ ),
136
+ files: ['**/*.tsx'],
137
+ },
138
+ {
139
+ name: 'Unit Tests',
140
+ ...deepMerge(jestExtends, {
141
+ rules: {
142
+ ...baseRules,
143
+ ...typeScriptRules,
144
+ }
145
+ }),
146
+ files: ['**/*.test.ts', '**/*.test.tsx'],
147
+ }
148
+ ]
149
+
150
+ export default rootEslintConfig
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const AnotherComponentTest: React.FC = () => <div>AnotherComponentTest</div>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const ComponentTest: React.FC = () => <div>ComponentTest</div>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const TestComponent: React.FC = () => <div>ComponentTest</div>;
@@ -0,0 +1,3 @@
1
+ export * from './AnotherComponentTest';
2
+ export * from './ComponentTest';
3
+ export * from './TestComponent';
package/demo/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './components';
package/eslint.config.mjs CHANGED
@@ -1,35 +1,44 @@
1
- import path from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
- import { FlatCompat } from '@eslint/eslintrc';
4
- import tsParser from '@typescript-eslint/parser';
5
- import js from '@eslint/js';
1
+ /** @typedef {import('eslint').Linter.Config} Config */
6
2
 
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
- const compat = new FlatCompat({
10
- allConfig: js.configs.all,
11
- baseDirectory: __dirname,
12
- recommendedConfig: js.configs.recommended,
13
- });
3
+ import baseConfig from './config/configs/base/index.mjs';
4
+ import reactConfig from './config/configs/react/index.mjs';
5
+ import typescriptConfig from './config/configs/typescript/index.mjs';
6
+ import jestConfig from './config/configs/jest/index.mjs';
14
7
 
15
- export default [...compat.extends('.'), {
16
- languageOptions: {
17
- ecmaVersion: 2020,
18
- parser: tsParser,
19
- parserOptions: {
20
- ecmaFeatures: {
21
- jsx: true,
22
- },
23
- project: './tsconfig.json',
24
- },
25
- sourceType: 'module',
8
+ export const defaultESLintIgnores = [
9
+ '**/.temp',
10
+ '**/.*',
11
+ '**/.git',
12
+ '**/.hg',
13
+ '**/.pnp.*',
14
+ '**/jest.config.js',
15
+ '**/tsconfig.tsbuildinfo',
16
+ '**/README.md',
17
+ '**/payload-types.ts',
18
+ '**/dist/',
19
+ '**/.yarn/',
20
+ '**/build/',
21
+ '**/node_modules/',
22
+ '**/temp/',
23
+ 'next-env.d.ts',
24
+ ];
25
+
26
+ /** @type {Config[]} */
27
+ export const rootEslintConfig = [
28
+ baseConfig,
29
+ reactConfig,
30
+ typescriptConfig,
31
+ jestConfig,
32
+ {
33
+ ignores: [
34
+ ...defaultESLintIgnores,
35
+ ],
26
36
  },
27
- settings: {
28
- 'import/resolver': {
29
- node: {
30
- extensions: ['.mjs', '.js', '.jsx', '.ts', '.tsx', '.json'],
31
- },
32
- typescript: {},
33
- },
37
+ {
38
+ files: [`**/*.{js,jsx,ts,tsx}`],
34
39
  },
35
- }];
40
+ ];
41
+
42
+ export default [
43
+ ...rootEslintConfig,
44
+ ];
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@innovixx/eslint-config",
3
- "version": "2.0.3-alpha.3",
4
- "main": "configs/index.js",
5
- "repository": "git@github.com:Innovixx-Development/eslint-config.git",
3
+ "version": "3.0.0-alpha.2",
4
+ "main": "configs/index.mjs",
5
+ "repository": "git@github.com:innovixx/eslint-config.git",
6
6
  "description": "Opinionated ESLint config for JavaScript developers",
7
7
  "author": "service@innovixx.co.uk",
8
8
  "license": "MIT",
@@ -12,27 +12,37 @@
12
12
  "eslint-config",
13
13
  "style-guide"
14
14
  ],
15
+ "scripts": {
16
+ "lint": "eslint demo/**/*.{js,jsx,ts,tsx}"
17
+ },
15
18
  "dependencies": {
16
- "@eslint/eslintrc": "^3.2.0",
17
- "@eslint/js": "9.17.0",
18
- "@typescript-eslint/eslint-plugin": "^8.22.0",
19
- "@typescript-eslint/parser": "^8.22.0",
20
- "confusing-browser-globals": "^1.0.11",
21
- "eslint": "9.17.0",
19
+ "@eslint-react/eslint-plugin": "1.16.1",
20
+ "@eslint/js": "9.19.0",
21
+ "@types/eslint": "9.6.1",
22
+ "@types/eslint__js": "8.42.3",
23
+ "@types/node": "^22.12.0",
24
+ "@types/react": "^19.0.8",
25
+ "@types/react-dom": "^19.0.3",
26
+ "@typescript-eslint/eslint-plugin": "^8.23.0",
27
+ "@typescript-eslint/parser": "^8.23.0",
28
+ "eslint": "9.19.0",
22
29
  "eslint-plugin-import": "^2.31.0",
23
30
  "eslint-plugin-jest": "^28.11.0",
24
31
  "eslint-plugin-jest-dom": "^5.5.0",
25
32
  "eslint-plugin-jsx-a11y": "^6.10.2",
26
- "eslint-plugin-node": "^11.1.0",
27
33
  "eslint-plugin-react": "^7.37.4",
28
34
  "eslint-plugin-react-hooks": "^5.1.0",
29
35
  "eslint-plugin-react-refresh": "^0.4.18",
36
+ "eslint-plugin-regexp": "2.6.0",
30
37
  "eslint-plugin-sort-export-all": "^1.4.1",
31
38
  "eslint-plugin-sort-keys-fix": "^1.1.2",
32
- "object.assign": "^4.1.7",
33
- "object.entries": "^1.1.8"
39
+ "globals": "15.12.0",
40
+ "react": "^19.0.0",
41
+ "react-dom": "^19.0.0",
42
+ "typescript": "5.7.3",
43
+ "typescript-eslint": "8.23.0"
34
44
  },
35
45
  "devDependencies": {
36
- "@types/node": "^22.12.0"
46
+ "eslint-import-resolver-typescript": "^3.7.0"
37
47
  }
38
48
  }
@@ -1,19 +0,0 @@
1
- module.exports = {
2
- plugins: [
3
- 'node',
4
- 'eslint-plugin-sort-export-all',
5
- 'eslint-plugin-sort-keys-fix',
6
- ],
7
- env: {
8
- node: true,
9
- },
10
- extends: [
11
- './rules/best-practices',
12
- './rules/errors',
13
- './rules/es6',
14
- './rules/imports',
15
- './rules/style',
16
- './rules/variables',
17
- ].map(require.resolve),
18
- rules: {},
19
- };
package/configs/index.js DELETED
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- './base',
4
- './jest',
5
- './react',
6
- './typescript',
7
- ].map(require.resolve),
8
- rules: {},
9
- };
@@ -1,14 +0,0 @@
1
- module.exports = {
2
- env: {
3
- jest: true,
4
- },
5
- plugins: [
6
- 'jest',
7
- 'jest-dom',
8
- ],
9
- extends: [
10
- './rules/jest',
11
- './rules/jest-dom',
12
- ].map(require.resolve),
13
- rules: {},
14
- };
@@ -1,22 +0,0 @@
1
- module.exports = {
2
- env: {
3
- browser: true,
4
- },
5
- plugins: [
6
- 'jsx-a11y',
7
- 'react-hooks',
8
- 'react',
9
- 'eslint-plugin-react-refresh',
10
- ],
11
- settings: {
12
- react: {
13
- version: 'detect',
14
- },
15
- },
16
- extends: [
17
- './rules/react-a11y',
18
- './rules/react-hooks',
19
- './rules/react',
20
- ].map(require.resolve),
21
- rules: {},
22
- };
@@ -1,11 +0,0 @@
1
- module.exports = {
2
- rules: {
3
- // Enforce Rules of Hooks
4
- // https://github.com/facebook/react/blob/c11015ff4f610ac2924d1fc6d569a17657a404fd/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
5
- 'react-hooks/rules-of-hooks': 'error',
6
-
7
- // Verify the list of the dependencies for Hooks like useEffect and similar
8
- // https://github.com/facebook/react/blob/1204c789776cb01fbaf3e9f032e7e2ba85a44137/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js
9
- 'react-hooks/exhaustive-deps': 'error',
10
- },
11
- };
@@ -1,14 +0,0 @@
1
- module.exports = {
2
- plugins: ['@typescript-eslint'],
3
- extends: [
4
- './rules/typescript',
5
- './rules/variables',
6
- 'plugin:@typescript-eslint/recommended',
7
- ].map((requirePath) => {
8
- if (requirePath.startsWith('./')) {
9
- return require.resolve(requirePath);
10
- }
11
- return requirePath;
12
- }),
13
- rules: {},
14
- };