@fullstacksjs/eslint-config 14.6.0 → 14.8.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.
Files changed (48) hide show
  1. package/README.md +1 -1
  2. package/cjs/modules/base.js +3 -1
  3. package/cjs/modules/cypress.js +3 -1
  4. package/cjs/modules/imports.js +3 -1
  5. package/cjs/modules/jest.js +3 -1
  6. package/cjs/modules/next.js +3 -1
  7. package/cjs/modules/node.js +4 -2
  8. package/cjs/modules/perfectionist.js +3 -1
  9. package/cjs/modules/playwright.js +3 -1
  10. package/cjs/modules/prettier.js +3 -7
  11. package/cjs/modules/promise.js +3 -1
  12. package/cjs/modules/react.js +46 -28
  13. package/cjs/modules/regex.js +8 -2
  14. package/cjs/modules/storybook.js +3 -1
  15. package/cjs/modules/stylistic.js +3 -1
  16. package/cjs/modules/tailwind.js +11 -3
  17. package/cjs/modules/tests.js +3 -1
  18. package/cjs/modules/typescript.js +4 -12
  19. package/cjs/modules/vitest.js +3 -2
  20. package/cjs/types/modules/react.d.ts +5 -0
  21. package/cjs/types/modules/regex.d.ts +1 -1
  22. package/cjs/types/modules/tailwind.d.ts +2 -9
  23. package/cjs/utils/nextAllowExportNames.js +7 -0
  24. package/cjs/utils/objectOrEmpty.js +14 -0
  25. package/package.json +26 -26
  26. package/src/modules/base.mjs +4 -1
  27. package/src/modules/cypress.mjs +4 -1
  28. package/src/modules/imports.mjs +3 -1
  29. package/src/modules/jest.mjs +3 -1
  30. package/src/modules/next.mjs +5 -1
  31. package/src/modules/node.mjs +5 -2
  32. package/src/modules/perfectionist.mjs +5 -1
  33. package/src/modules/playwright.mjs +4 -1
  34. package/src/modules/prettier.mjs +5 -7
  35. package/src/modules/promise.mjs +4 -1
  36. package/src/modules/react.mjs +49 -27
  37. package/src/modules/regex.mjs +10 -2
  38. package/src/modules/storybook.mjs +4 -1
  39. package/src/modules/stylistic.mjs +5 -1
  40. package/src/modules/tailwind.mjs +13 -4
  41. package/src/modules/tests.mjs +4 -1
  42. package/src/modules/typescript.mjs +3 -8
  43. package/src/modules/vitest.mjs +4 -2
  44. package/src/types/modules/react.d.ts +5 -0
  45. package/src/types/modules/regex.d.ts +1 -1
  46. package/src/types/modules/tailwind.d.ts +2 -9
  47. package/src/utils/nextAllowExportNames.mjs +17 -0
  48. package/src/utils/objectOrEmpty.mjs +8 -0
@@ -7,12 +7,14 @@ Object.defineProperty(exports, "__esModule", {
7
7
  var _eslintPlugin = _interopRequireDefault(require("@vitest/eslint-plugin"));
8
8
  var _eslintFlatConfigUtils = require("eslint-flat-config-utils");
9
9
  var _globs = require("../utils/globs.js");
10
+ var _objectOrEmpty = require("../utils/objectOrEmpty.js");
10
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
12
  /**
12
13
  * @param { import('../types').Options } options
13
14
  * @return { import('eslint').Linter.Config }
14
15
  */
15
16
  function vitest(options = {}) {
17
+ const overrides = (0, _objectOrEmpty.objectOrEmpty)(options.vitest.overrides);
16
18
  const vitestConfig = {
17
19
  name: 'vitest',
18
20
  files: _globs.globs.test,
@@ -53,7 +55,6 @@ function vitest(options = {}) {
53
55
  'vitest/no-conditional-in-test': 'off',
54
56
  'vitest/no-conditional-tests': 'warn',
55
57
  'vitest/no-disabled-tests': 'warn',
56
- 'vitest/no-done-callback': 'off',
57
58
  'vitest/no-duplicate-hooks': 'error',
58
59
  'vitest/no-focused-tests': 'warn',
59
60
  'vitest/no-hooks': 'off',
@@ -110,6 +111,6 @@ function vitest(options = {}) {
110
111
  'vitest/warn-todo': 'warn'
111
112
  }
112
113
  };
113
- return (0, _eslintFlatConfigUtils.mergeConfigs)(vitestConfig, options.vitest.overrides ?? {});
114
+ return (0, _eslintFlatConfigUtils.mergeConfigs)(vitestConfig, overrides);
114
115
  }
115
116
  module.exports = vitest;
@@ -1,5 +1,10 @@
1
1
  import type { ConfigWithOverrides } from '..';
2
2
 
3
3
  interface ReactOptions extends ConfigWithOverrides {
4
+ version?: string;
5
+ importSource?: string;
6
+ compilationMode?: 'all' | 'annotation' | 'infer' | 'syntax'; // Use the same compilationMode as the React Compiler config for consistent analysis
7
+ polymorphicPropName?: string;
8
+ additionalStateHooks?: string;
4
9
  additionalEffectHooks?: string;
5
10
  }
@@ -1,5 +1,5 @@
1
1
  import type { ConfigWithOverrides } from '..';
2
2
 
3
3
  interface RegexOptions extends ConfigWithOverrides {
4
- allowedCharacterRanges: string[];
4
+ allowedCharacterRanges?: string[];
5
5
  }
@@ -1,18 +1,11 @@
1
1
  import type { ConfigWithOverrides } from '..';
2
2
 
3
- interface TailwindOptionsBase extends ConfigWithOverrides {
4
- callees?: string[];
5
- variables?: string[];
6
- attributes?: string[];
7
- tags?: string[];
8
- }
9
-
10
- interface TailwindOptionsWithEntryPoint extends TailwindOptionsBase {
3
+ interface TailwindOptionsWithEntryPoint extends ConfigWithOverrides {
11
4
  entryPoint: string;
12
5
  tailwindConfig?: string;
13
6
  }
14
7
 
15
- interface TailwindOptionsWithConfig extends TailwindOptionsBase {
8
+ interface TailwindOptionsWithConfig extends ConfigWithOverrides {
16
9
  entryPoint?: string;
17
10
  tailwindConfig: string;
18
11
  }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.nextAllowExportNames = void 0;
7
+ const nextAllowExportNames = exports.nextAllowExportNames = ['experimental_ppr', 'dynamic', 'dynamicParams', 'revalidate', 'fetchCache', 'runtime', 'preferredRegion', 'maxDuration', 'metadata', 'generateMetadata', 'viewport', 'generateViewport', 'generateImageMetadata', 'generateSitemaps', 'generateStaticParams'];
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.objectOrEmpty = objectOrEmpty;
7
+ /**
8
+ * @template T
9
+ * @param {T | null | undefined} value
10
+ * @returns {T | {}}
11
+ */
12
+ function objectOrEmpty(value) {
13
+ return typeof value === 'object' && value !== null ? value : {};
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "14.6.0",
3
+ "version": "14.8.0",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
@@ -16,7 +16,7 @@
16
16
  "src",
17
17
  "cjs"
18
18
  ],
19
- "packageManager": "npm@11.13.0",
19
+ "packageManager": "npm@12.0.1",
20
20
  "scripts": {
21
21
  "lint": "eslint .",
22
22
  "spell": "cspell ./* --no-progress",
@@ -38,46 +38,46 @@
38
38
  }
39
39
  },
40
40
  "dependencies": {
41
- "@eslint-react/eslint-plugin": "5.8.3",
41
+ "@eslint-react/eslint-plugin": "5.17.2",
42
42
  "@eslint/compat": "2.1.0",
43
- "@next/eslint-plugin-next": "16.2.6",
43
+ "@next/eslint-plugin-next": "16.2.10",
44
44
  "@stylistic/eslint-plugin": "5.10.0",
45
- "@vitest/eslint-plugin": "1.6.17",
45
+ "@vitest/eslint-plugin": "1.6.23",
46
46
  "deepmerge": "4.3.1",
47
47
  "eslint-flat-config-utils": "3.2.0",
48
- "eslint-plugin-better-tailwindcss": "4.5.0",
49
- "eslint-plugin-cypress": "6.4.1",
50
- "eslint-plugin-import-x": "4.16.2",
51
- "eslint-plugin-jest": "29.15.2",
48
+ "eslint-plugin-better-tailwindcss": "4.7.0",
49
+ "eslint-plugin-cypress": "6.4.3",
50
+ "eslint-plugin-import-x": "4.17.1",
51
+ "eslint-plugin-jest": "29.15.4",
52
52
  "eslint-plugin-jsx-a11y": "6.10.2",
53
- "eslint-plugin-n": "18.0.1",
54
- "eslint-plugin-perfectionist": "5.9.0",
55
- "eslint-plugin-playwright": "2.10.4",
56
- "eslint-plugin-prettier": "5.5.5",
53
+ "eslint-plugin-n": "18.2.1",
54
+ "eslint-plugin-perfectionist": "5.10.0",
55
+ "eslint-plugin-playwright": "2.10.5",
56
+ "eslint-plugin-prettier": "5.5.6",
57
57
  "eslint-plugin-promise": "7.3.0",
58
- "eslint-plugin-react-hooks": "7.1.1",
59
- "eslint-plugin-regexp": "3.1.0",
60
- "eslint-plugin-storybook": "10.4.0",
61
- "globals": "17.6.0",
58
+ "eslint-plugin-react-refresh": "0.5.3",
59
+ "eslint-plugin-regexp": "3.1.1",
60
+ "eslint-plugin-storybook": "10.5.2",
61
+ "globals": "17.7.0",
62
62
  "local-pkg": "1.2.1",
63
- "typescript-eslint": "8.59.4"
63
+ "typescript-eslint": "8.65.0"
64
64
  },
65
65
  "devDependencies": {
66
- "@eslint/eslintrc": "3.3.5",
66
+ "@eslint/eslintrc": "3.3.6",
67
67
  "@eslint/js": "10.0.1",
68
- "@semantic-release/github": "12.0.8",
68
+ "@semantic-release/github": "12.0.9",
69
69
  "@semantic-release/npm": "13.1.5",
70
70
  "@semantic-release/release-notes-generator": "14.1.1",
71
71
  "@types/eslint": "9.6.1",
72
- "cspell": "10.0.0",
73
- "eslint": "10.4.0",
72
+ "cspell": "10.0.1",
73
+ "eslint": "10.7.0",
74
74
  "husky": "9.1.7",
75
75
  "jest": "30.4.2",
76
- "lint-staged": "17.0.5",
76
+ "lint-staged": "17.1.0",
77
77
  "pinst": "3.0.0",
78
- "prettier": "3.8.3",
79
- "semantic-release": "25.0.3",
80
- "storybook": "10.4.0",
78
+ "prettier": "3.9.5",
79
+ "semantic-release": "25.0.8",
80
+ "storybook": "10.5.2",
81
81
  "typescript": "6.0.3",
82
82
  "unbuild": "3.6.1"
83
83
  },
@@ -2,12 +2,15 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import globals from 'globals';
3
3
 
4
4
  import { strict } from '../utils/conditions.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  /**
7
8
  * @param { import('../types').Options } options
8
9
  * @return { import('eslint').Linter.Config }
9
10
  */
10
11
  function base(options = {}) {
12
+ const overrides = objectOrEmpty(options.base.overrides);
13
+
11
14
  const baseConfig = {
12
15
  name: 'base',
13
16
  languageOptions: {
@@ -197,7 +200,7 @@ function base(options = {}) {
197
200
  },
198
201
  };
199
202
 
200
- return mergeConfigs(baseConfig, options.base.overrides ?? {});
203
+ return mergeConfigs(baseConfig, overrides);
201
204
  }
202
205
 
203
206
  export default base;
@@ -2,12 +2,15 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-cypress';
3
3
 
4
4
  import { globs } from '../utils/globs.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  /**
7
8
  * @param { import('../types').Options } options
8
9
  * @return { import('eslint').Linter.Config }
9
10
  */
10
11
  function cypress(options = {}) {
12
+ const overrides = objectOrEmpty(options.cypress.overrides);
13
+
11
14
  const cypressConfig = {
12
15
  name: 'cypress',
13
16
  files: globs.e2e,
@@ -26,7 +29,7 @@ function cypress(options = {}) {
26
29
  },
27
30
  };
28
31
 
29
- return mergeConfigs(cypressConfig, options.cypress.overrides ?? {});
32
+ return mergeConfigs(cypressConfig, overrides);
30
33
  }
31
34
 
32
35
  export default cypress;
@@ -2,6 +2,7 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-import-x';
3
3
 
4
4
  import { predicate } from '../utils/conditions.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  const tsExtensions = ['.ts', '.tsx', '.cts', '.mts', '.ctsx', '.mtsx'];
7
8
  const jsExtensions = ['.mjs', '.js', '.jsx', '.cjs'];
@@ -13,6 +14,7 @@ const allExtensions = [...jsExtensions, ...tsExtensions];
13
14
  */
14
15
  function imports(options = {}) {
15
16
  const isObject = typeof options.import === 'object';
17
+ const overrides = objectOrEmpty(options.import.overrides);
16
18
 
17
19
  const importsConfig = {
18
20
  name: 'imports',
@@ -106,7 +108,7 @@ function imports(options = {}) {
106
108
  },
107
109
  };
108
110
 
109
- return mergeConfigs(importsConfig, options.import.overrides ?? {});
111
+ return mergeConfigs(importsConfig, overrides);
110
112
  }
111
113
 
112
114
  export default imports;
@@ -4,12 +4,14 @@ import globals from 'globals';
4
4
 
5
5
  import { predicate } from '../utils/conditions.mjs';
6
6
  import { globs } from '../utils/globs.mjs';
7
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
7
8
 
8
9
  /**
9
10
  * @param { import('../types').Options } options
10
11
  * @return { import('eslint').Linter.Config } */
11
12
  function jest(options = {}) {
12
13
  const projectService = options.typescript && options.typescript.tsconfigRootDir && options.typescript.projectService;
14
+ const overrides = objectOrEmpty(options.jest.overrides);
13
15
 
14
16
  const jestConfig = {
15
17
  name: 'jest',
@@ -86,7 +88,7 @@ function jest(options = {}) {
86
88
  },
87
89
  };
88
90
 
89
- return mergeConfigs(jestConfig, options.jest.overrides ?? {});
91
+ return mergeConfigs(jestConfig, overrides);
90
92
  }
91
93
 
92
94
  export default jest;
@@ -1,11 +1,15 @@
1
1
  import plugin from '@next/eslint-plugin-next';
2
2
  import { mergeConfigs } from 'eslint-flat-config-utils';
3
3
 
4
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
+
4
6
  /**
5
7
  * @param { import('../types').Options } options
6
8
  * @return { import('eslint').Linter.Config }
7
9
  */
8
10
  function next(options = {}) {
11
+ const overrides = objectOrEmpty(options.next.overrides);
12
+
9
13
  const nextConfig = {
10
14
  name: 'next',
11
15
  plugins: { next: plugin },
@@ -34,7 +38,7 @@ function next(options = {}) {
34
38
  },
35
39
  };
36
40
 
37
- return mergeConfigs(nextConfig, options.next.overrides ?? {});
41
+ return mergeConfigs(nextConfig, overrides);
38
42
  }
39
43
 
40
44
  export default next;
@@ -2,12 +2,15 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-n';
3
3
 
4
4
  import { strict } from '../utils/conditions.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  /**
7
8
  * @param { import('../types').Options } options
8
9
  * @return { import('eslint').Linter.Config }
9
10
  */
10
11
  function node(options = {}) {
12
+ const overrides = objectOrEmpty(options.node.overrides);
13
+
11
14
  const nodeConfig = {
12
15
  name: 'node',
13
16
  plugins: { n: plugin },
@@ -30,7 +33,7 @@ function node(options = {}) {
30
33
  'n/no-sync': strict(options, 'warn'),
31
34
  'n/no-top-level-await': 'off',
32
35
  'n/no-unpublished-bin': 'warn',
33
- 'n/no-unpublished-import': 'warn',
36
+ 'n/no-unpublished-import': 'off',
34
37
  'n/no-unpublished-require': 'warn',
35
38
  'n/no-unsupported-features/es-builtins': 'off', // Nice but not a general rule
36
39
  'n/no-unsupported-features/es-syntax': 'off', // Nice but not a general rule
@@ -58,7 +61,7 @@ function node(options = {}) {
58
61
  },
59
62
  };
60
63
 
61
- return mergeConfigs(nodeConfig, options.node.overrides ?? {});
64
+ return mergeConfigs(nodeConfig, overrides);
62
65
  }
63
66
 
64
67
  export default node;
@@ -1,11 +1,15 @@
1
1
  import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-perfectionist';
3
3
 
4
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
+
4
6
  /**
5
7
  * @param { import('../types').Options } options
6
8
  * @return { Promise<import('eslint').Linter.Config> }
7
9
  */
8
10
  function perfectionist(options = {}) {
11
+ const overrides = objectOrEmpty(options.sort.overrides);
12
+
9
13
  const perfectionistConfig = {
10
14
  name: 'perfectionist',
11
15
  plugins: { perfectionist: plugin },
@@ -72,7 +76,7 @@ function perfectionist(options = {}) {
72
76
  },
73
77
  };
74
78
 
75
- return mergeConfigs(perfectionistConfig, options.sort.overrides ?? {});
79
+ return mergeConfigs(perfectionistConfig, overrides);
76
80
  }
77
81
 
78
82
  export default perfectionist;
@@ -2,12 +2,15 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-playwright';
3
3
 
4
4
  import { globs } from '../utils/globs.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  /**
7
8
  * @param { import('../types').Options } options
8
9
  * @return { Promise<import('eslint').Linter.Config> }
9
10
  */
10
11
  function playwright(options = {}) {
12
+ const overrides = objectOrEmpty(options.playwright.overrides);
13
+
11
14
  const playwrightConfig = {
12
15
  name: 'playwright',
13
16
  plugins: { playwright: plugin },
@@ -74,7 +77,7 @@ function playwright(options = {}) {
74
77
  },
75
78
  };
76
79
 
77
- return mergeConfigs(playwrightConfig, options.playwright.overrides ?? {});
80
+ return mergeConfigs(playwrightConfig, overrides);
78
81
  }
79
82
 
80
83
  export default playwright;
@@ -1,11 +1,15 @@
1
1
  import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-prettier';
3
3
 
4
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
+
4
6
  /**
5
7
  * @param { import('../types').Options } options
6
8
  * @return { Promise<import('eslint').Linter.Config> }
7
9
  */
8
10
  function prettier(options = {}) {
11
+ const overrides = objectOrEmpty(options.prettier.overrides);
12
+
9
13
  const prettierConfig = {
10
14
  name: 'prettier',
11
15
  plugins: { prettier: plugin },
@@ -13,24 +17,20 @@ function prettier(options = {}) {
13
17
  'prettier/prettier': 'error',
14
18
 
15
19
  'curly': 'off',
16
- 'brace-style': 'off',
17
20
  'no-unexpected-multiline': 'off',
18
21
 
19
22
  '@typescript-eslint/lines-around-comment': 'off',
20
23
  '@typescript-eslint/quotes': 'off',
21
24
  '@typescript-eslint/block-spacing': 'off',
22
- '@typescript-eslint/brace-style': 'off',
23
25
  '@typescript-eslint/comma-dangle': 'off',
24
26
  '@typescript-eslint/comma-spacing': 'off',
25
27
  '@typescript-eslint/func-call-spacing': 'off',
26
28
  '@typescript-eslint/indent': 'off',
27
- '@typescript-eslint/key-spacing': 'off',
28
29
  '@typescript-eslint/keyword-spacing': 'off',
29
30
  '@typescript-eslint/member-delimiter-style': 'off',
30
31
  '@typescript-eslint/no-extra-parens': 'off',
31
32
  '@typescript-eslint/no-extra-semi': 'off',
32
33
  '@typescript-eslint/semi': 'off',
33
- '@typescript-eslint/space-before-blocks': 'off',
34
34
  '@typescript-eslint/space-before-function-paren': 'off',
35
35
  '@typescript-eslint/space-infix-ops': 'off',
36
36
  '@typescript-eslint/type-annotation-spacing': 'off',
@@ -42,12 +42,10 @@ function prettier(options = {}) {
42
42
  '@stylistic/jsx-curly-spacing': 'off',
43
43
  '@stylistic/jsx-equals-spacing': 'off',
44
44
  '@stylistic/jsx-first-prop-new-line': 'off',
45
- '@stylistic/jsx-indent': 'off',
46
45
  '@stylistic/jsx-indent-props': 'off',
47
46
  '@stylistic/jsx-max-props-per-line': 'off',
48
47
  '@stylistic/jsx-newline': 'off',
49
48
  '@stylistic/jsx-one-expression-per-line': 'off',
50
- '@stylistic/jsx-props-no-multi-spaces': 'off',
51
49
  '@stylistic/jsx-tag-spacing': 'off',
52
50
  '@stylistic/jsx-wrap-multilines': 'off',
53
51
 
@@ -93,7 +91,7 @@ function prettier(options = {}) {
93
91
  },
94
92
  };
95
93
 
96
- return mergeConfigs(prettierConfig, options.prettier.overrides ?? {});
94
+ return mergeConfigs(prettierConfig, overrides);
97
95
  }
98
96
 
99
97
  export default prettier;
@@ -2,12 +2,15 @@ import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import plugin from 'eslint-plugin-promise';
3
3
 
4
4
  import { strict } from '../utils/conditions.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
5
6
 
6
7
  /**
7
8
  * @param { import('../types').Options } options
8
9
  * @return { Promise<import('eslint').Linter.Config> }
9
10
  */
10
11
  function promise(options = {}) {
12
+ const overrides = objectOrEmpty(options.promise.overrides);
13
+
11
14
  const promiseConfig = {
12
15
  name: 'promise',
13
16
  plugins: { promise: plugin },
@@ -32,7 +35,7 @@ function promise(options = {}) {
32
35
  },
33
36
  };
34
37
 
35
- return mergeConfigs(promiseConfig, options.promise.overrides ?? {});
38
+ return mergeConfigs(promiseConfig, overrides);
36
39
  }
37
40
 
38
41
  export default promise;
@@ -1,11 +1,14 @@
1
1
  import reactPlugin from '@eslint-react/eslint-plugin';
2
2
  import { mergeConfigs } from 'eslint-flat-config-utils';
3
3
  import a11yPlugin from 'eslint-plugin-jsx-a11y';
4
- import hooksPlugin from 'eslint-plugin-react-hooks';
4
+ import { reactRefresh } from 'eslint-plugin-react-refresh';
5
+ import { isPackageExists } from 'local-pkg';
5
6
  import { parser } from 'typescript-eslint';
6
7
 
7
8
  import { predicate, strict } from '../utils/conditions.mjs';
8
9
  import { globs } from '../utils/globs.mjs';
10
+ import { nextAllowExportNames } from '../utils/nextAllowExportNames.mjs';
11
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
9
12
 
10
13
  /**
11
14
  * @param { import('../types').Options } options
@@ -13,14 +16,16 @@ import { globs } from '../utils/globs.mjs';
13
16
  */
14
17
  function react(options = {}) {
15
18
  const projectService = options.typescript && options.typescript.tsconfigRootDir && options.typescript.projectService;
19
+ const isObject = typeof options.react === 'object';
20
+ const overrides = objectOrEmpty(options.react.overrides);
16
21
 
17
22
  const reactConfig = {
18
23
  name: 'react',
19
24
  files: [globs.js, globs.jsx, globs.ts, globs.tsx],
20
25
  plugins: {
21
26
  ...reactPlugin.configs.all.plugins,
22
- 'react-hooks': hooksPlugin,
23
27
  'jsx-a11y': a11yPlugin,
28
+ 'react-refresh': reactRefresh.plugin,
24
29
  },
25
30
  ...predicate(projectService, {
26
31
  languageOptions: {
@@ -29,12 +34,25 @@ function react(options = {}) {
29
34
  },
30
35
  }),
31
36
  settings: {
32
- 'react': {
33
- pragma: 'React',
34
- version: 'detect',
35
- },
36
- 'react-hooks': {
37
- additionalEffectHooks: options.react.additionalEffectHooks,
37
+ 'react-x': {
38
+ ...predicate(isObject && 'version' in options.react, {
39
+ version: options.react.version,
40
+ }),
41
+ ...predicate(isObject && 'importSource' in options.react, {
42
+ importSource: options.react.importSource,
43
+ }),
44
+ ...predicate(isObject && 'compilationMode' in options.react, {
45
+ compilationMode: options.react.compilationMode,
46
+ }),
47
+ ...predicate(isObject && 'polymorphicPropName' in options.react, {
48
+ polymorphicPropName: options.react.polymorphicPropName,
49
+ }),
50
+ ...predicate(isObject && 'additionalStateHooks' in options.react, {
51
+ additionalStateHooks: options.react.additionalStateHooks,
52
+ }),
53
+ ...predicate(isObject && 'additionalEffectHooks' in options.react, {
54
+ additionalEffectHooks: options.react.additionalEffectHooks,
55
+ }),
38
56
  },
39
57
  },
40
58
  rules: {
@@ -115,27 +133,22 @@ function react(options = {}) {
115
133
  '@eslint-react/web-api-no-leaked-interval': 'error',
116
134
  '@eslint-react/web-api-no-leaked-resize-observer': 'error',
117
135
  '@eslint-react/web-api-no-leaked-fetch': 'error',
136
+ '@eslint-react/web-api-no-leaked-intersection-observer': 'error',
118
137
 
119
138
  '@eslint-react/rsc-function-definition': 'error',
120
139
 
121
- 'react-hooks/rules-of-hooks': 'error',
122
- 'react-hooks/exhaustive-deps': 'warn',
123
-
124
- 'react-hooks/config': 'error',
125
- 'react-hooks/error-boundaries': 'error',
126
- 'react-hooks/component-hook-factories': 'error',
127
- 'react-hooks/gating': 'error',
128
- 'react-hooks/globals': 'error',
129
- 'react-hooks/immutability': 'error',
130
- 'react-hooks/preserve-manual-memoization': 'error',
131
- 'react-hooks/purity': 'error',
132
- 'react-hooks/refs': 'error',
133
- 'react-hooks/set-state-in-effect': strict('error'),
134
- 'react-hooks/set-state-in-render': 'error',
135
- 'react-hooks/static-components': strict('error'),
136
- 'react-hooks/unsupported-syntax': 'warn',
137
- 'react-hooks/use-memo': 'error',
138
- 'react-hooks/incompatible-library': 'warn',
140
+ '@eslint-react/rules-of-hooks': 'error',
141
+ '@eslint-react/exhaustive-deps': 'error',
142
+ '@eslint-react/error-boundaries': 'error',
143
+ '@eslint-react/globals': 'error',
144
+ '@eslint-react/immutability': 'error',
145
+ '@eslint-react/purity': 'error',
146
+ '@eslint-react/refs': 'error',
147
+ '@eslint-react/set-state-in-effect': strict('error'),
148
+ '@eslint-react/set-state-in-render': 'error',
149
+ '@eslint-react/static-components': strict('error'),
150
+ '@eslint-react/unsupported-syntax': 'error',
151
+ '@eslint-react/use-memo': 'error',
139
152
 
140
153
  'jsx-a11y/alt-text': 'warn',
141
154
  'jsx-a11y/anchor-has-content': 'error',
@@ -173,10 +186,19 @@ function react(options = {}) {
173
186
  'jsx-a11y/tabindex-no-positive': 'warn',
174
187
  'jsx-a11y/anchor-ambiguous-text': 'off',
175
188
  'jsx-a11y/prefer-tag-over-role': 'off',
189
+
190
+ 'react-refresh/only-export-components': [
191
+ 'error',
192
+ {
193
+ allowExportNames: isPackageExists('next') ? nextAllowExportNames : [],
194
+
195
+ allowConstantExport: isPackageExists('vite'),
196
+ },
197
+ ],
176
198
  },
177
199
  };
178
200
 
179
- return mergeConfigs(reactConfig, options.react.overrides ?? {});
201
+ return mergeConfigs(reactConfig, overrides);
180
202
  }
181
203
 
182
204
  export default react;
@@ -1,17 +1,25 @@
1
1
  import { mergeConfigs } from 'eslint-flat-config-utils';
2
2
  import * as plugin from 'eslint-plugin-regexp';
3
3
 
4
+ import { predicate } from '../utils/conditions.mjs';
5
+ import { objectOrEmpty } from '../utils/objectOrEmpty.mjs';
6
+
4
7
  /**
5
8
  * @param { import('../types').Options } options
6
9
  * @return { Promise<import('eslint').Linter.Config> }
7
10
  */
8
11
  function regex(options = {}) {
12
+ const isObject = typeof options.regex === 'object';
13
+ const overrides = objectOrEmpty(options.regex.overrides);
14
+
9
15
  const regexConfig = {
10
16
  name: 'regex',
11
17
  plugins: { regexp: plugin },
12
18
  settings: {
13
19
  regexp: {
14
- allowedCharacterRanges: options.regex.allowedCharacterRanges,
20
+ ...predicate(isObject && 'allowedCharacterRanges' in options.regex, {
21
+ allowedCharacterRanges: options.regex.allowedCharacterRanges,
22
+ }),
15
23
  },
16
24
  },
17
25
  rules: {
@@ -104,7 +112,7 @@ function regex(options = {}) {
104
112
  },
105
113
  };
106
114
 
107
- return mergeConfigs(regexConfig, options.regex.overrides ?? {});
115
+ return mergeConfigs(regexConfig, overrides);
108
116
  }
109
117
 
110
118
  export default regex;