@fullstacksjs/eslint-config 13.2.1 → 13.3.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/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  ## Installation
14
14
 
15
15
  ```sh
16
- $ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
16
+ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
17
17
  ```
18
18
 
19
19
  ⚡️ That's it, you don't need to install any eslint-plugin! If you already have some plugins installed, please remove them.
@@ -27,11 +27,7 @@ To use the configuration, all you need is to export the generated config by the
27
27
  ```js
28
28
  import { defineConfig } from '@fullstacksjs/eslint-config';
29
29
 
30
- export default defineConfig({
31
- typescript: {
32
- tsconfigRootDir: import.meta.dirname, // If you are using TypeScript
33
- }
34
- });
30
+ export default defineConfig();
35
31
  ```
36
32
 
37
33
  ### CJS
@@ -39,9 +35,7 @@ export default defineConfig({
39
35
  ```js
40
36
  const { defineConfig } = require('@fullstacksjs/eslint-config');
41
37
 
42
- module.exports = defineConfig({
43
- tsconfigRootDir: import.meta.dirname, // If you are using TypeScript
44
- });
38
+ module.exports = defineConfig();
45
39
  ```
46
40
 
47
41
  ## How Module Detection Works
package/cjs/index.d.ts CHANGED
@@ -93,7 +93,7 @@ export interface Options extends Linter.Config {
93
93
  * Controls [TypeScript plugin](https://www.npmjs.com/package/typescript-eslint).
94
94
  * @default true - If you have `typescript` in your dependencies.
95
95
  */
96
- typescript?: { projectService?: boolean | ProjectService; tsconfigRootDir: string; cacheLifetime?: number };
96
+ typescript?: { projectService?: boolean | ProjectService; tsconfigRootDir?: string; cacheLifetime?: number };
97
97
  /**
98
98
  * Disables expensive rules.
99
99
  * @default false
@@ -18,9 +18,35 @@ function playwright() {
18
18
  'jest/no-standalone-expect': ['error', {
19
19
  additionalTestBlockFunctions: ['test.jestPlaywrightDebug', 'it.jestPlaywrightDebug', 'test.jestPlaywrightSkip', 'it.jestPlaywrightSkip', 'test.jestPlaywrightConfig', 'it.jestPlaywrightConfig']
20
20
  }],
21
+ 'playwright/expect-expect': 'error',
21
22
  'playwright/missing-playwright-await': 'error',
23
+ 'playwright/max-nested-describe': ['warn', {
24
+ max: 5
25
+ }],
26
+ 'playwright/no-duplicate-hooks': 'error',
27
+ 'playwright/no-element-handle': 'warn',
28
+ 'playwright/no-eval': 'warn',
22
29
  'playwright/no-page-pause': 'warn',
23
- 'playwright/no-slowed-test': 'warn'
30
+ 'playwright/no-slowed-test': 'warn',
31
+ 'playwright/no-skipped-test': 'warn',
32
+ 'playwright/no-standalone-expect': 'warn',
33
+ 'playwright/no-focused-test': 'warn',
34
+ 'playwright/no-force-option': 'warn',
35
+ 'playwright/no-conditional-expect': 'warn',
36
+ 'playwright/no-conditional-in-test': 'warn',
37
+ 'playwright/no-nested-step': 'warn',
38
+ 'playwright/no-networkidle': 'warn',
39
+ 'playwright/no-useless-await': 'error',
40
+ 'playwright/no-unsafe-references': 'warn',
41
+ 'playwright/no-useless-not': 'warn',
42
+ 'playwright/no-wait-for-navigation': 'warn',
43
+ 'playwright/no-wait-for-selector': 'warn',
44
+ 'playwright/no-wait-for-timeout': 'warn',
45
+ 'playwright/prefer-web-first-assertions': 'warn',
46
+ 'playwright/valid-describe-callback': 'warn',
47
+ 'playwright/valid-expect-in-promise': 'warn',
48
+ 'playwright/valid-expect': 'warn',
49
+ 'playwright/valid-title': 'warn'
24
50
  }
25
51
  };
26
52
  }
@@ -23,11 +23,12 @@ function react() {
23
23
  }
24
24
  },
25
25
  rules: {
26
- '@eslint-react/dom/no-children-in-void-dom-elements': 'warn',
26
+ '@eslint-react/dom/no-void-elements-with-children': 'warn',
27
27
  '@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
28
28
  '@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
29
29
  '@eslint-react/dom/no-find-dom-node': 'error',
30
30
  '@eslint-react/dom/no-flush-sync': 'off',
31
+ '@eslint-react/dom/no-use-form-state': 'warn',
31
32
  '@eslint-react/dom/no-hydrate': 'warn',
32
33
  '@eslint-react/dom/no-missing-button-type': 'warn',
33
34
  '@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
@@ -37,9 +38,9 @@ function react() {
37
38
  '@eslint-react/dom/no-script-url': 'warn',
38
39
  '@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
39
40
  '@eslint-react/dom/no-unsafe-target-blank': 'warn',
40
- '@eslint-react/ensure-forward-ref-using-ref': 'off',
41
41
  '@eslint-react/jsx-key-before-spread': 'error',
42
42
  '@eslint-react/jsx-no-undef': 'off',
43
+ '@eslint-react/jsx-no-iife': 'warn',
43
44
  '@eslint-react/jsx-uses-react': 'off',
44
45
  '@eslint-react/no-access-state-in-setstate': 'error',
45
46
  '@eslint-react/no-array-index-key': 'warn',
@@ -54,11 +55,15 @@ function react() {
54
55
  '@eslint-react/no-component-will-mount': 'error',
55
56
  '@eslint-react/no-component-will-receive-props': 'error',
56
57
  '@eslint-react/no-component-will-update': 'error',
58
+ '@eslint-react/no-context-provider': 'warn',
57
59
  '@eslint-react/no-create-ref': 'error',
58
60
  '@eslint-react/no-direct-mutation-state': 'error',
59
61
  '@eslint-react/no-duplicate-key': 'error',
62
+ '@eslint-react/no-default-props': 'warn',
63
+ '@eslint-react/jsx-no-duplicate-props': 'error',
64
+ '@eslint-react/no-forward-ref': 'warn',
60
65
  '@eslint-react/no-implicit-key': 'error',
61
- '@eslint-react/no-missing-context-display-name': 'off',
66
+ '@eslint-react/no-missing-context-display-name': 'warn',
62
67
  '@eslint-react/no-missing-key': 'error',
63
68
  '@eslint-react/no-misused-capture-owner-stack': 'error',
64
69
  '@eslint-react/no-nested-component-definitions': 'warn',
@@ -75,17 +80,18 @@ function react() {
75
80
  '@eslint-react/no-unstable-default-props': 'error',
76
81
  '@eslint-react/no-unused-class-component-members': 'warn',
77
82
  '@eslint-react/no-unused-state': 'warn',
78
- '@eslint-react/no-useless-forward-ref': 'warn',
83
+ '@eslint-react/no-useless-forward-ref': 'off',
79
84
  '@eslint-react/no-useless-fragment': 'warn',
85
+ '@eslint-react/no-use-context': 'warn',
80
86
  '@eslint-react/prefer-destructuring-assignment': 'warn',
81
87
  '@eslint-react/prefer-shorthand-boolean': 'warn',
82
88
  '@eslint-react/avoid-shorthand-boolean': 'off',
83
89
  '@eslint-react/prefer-shorthand-fragment': 'warn',
84
90
  '@eslint-react/avoid-shorthand-fragment': 'off',
85
- '@eslint-react/hooks-extra/ensure-custom-hooks-using-other-hooks': 'warn',
86
- '@eslint-react/hooks-extra/ensure-use-memo-has-non-empty-deps': 'warn',
87
91
  '@eslint-react/hooks-extra/prefer-use-state-lazy-initialization': 'warn',
88
- '@eslint-react/hooks-extra/no-useless-custom-hooks': 'warn',
92
+ '@eslint-react/hooks-extra/no-unnecessary-use-callback': 'warn',
93
+ '@eslint-react/hooks-extra/no-unnecessary-use-prefix': 'warn',
94
+ '@eslint-react/hooks-extra/no-unnecessary-use-memo': 'warn',
89
95
  '@eslint-react/naming-convention/component-name': 'warn',
90
96
  '@eslint-react/naming-convention/context-name': 'warn',
91
97
  '@eslint-react/naming-convention/filename-extension': ['error', {
@@ -94,6 +100,10 @@ function react() {
94
100
  }],
95
101
  '@eslint-react/naming-convention/filename': 'off',
96
102
  '@eslint-react/naming-convention/use-state': 'off',
103
+ '@eslint-react/web-api/no-leaked-timeout': 'error',
104
+ '@eslint-react/web-api/no-leaked-event-listener': 'error',
105
+ '@eslint-react/web-api/no-leaked-interval': 'error',
106
+ '@eslint-react/web-api/no-leaked-resize-observer': 'error',
97
107
  'react-hooks/exhaustive-deps': 'warn',
98
108
  'react-hooks/rules-of-hooks': 'error',
99
109
  'jsx-a11y/alt-text': 'warn',
@@ -25,10 +25,13 @@ async function tailwind(options = {}) {
25
25
  },
26
26
  rules: {
27
27
  'better-tailwindcss/no-duplicate-classes': 'error',
28
+ 'better-tailwindcss/no-deprecated-classes': 'warn',
28
29
  'better-tailwindcss/no-conflicting-classes': 'error',
29
30
  'better-tailwindcss/no-unnecessary-whitespace': 'warn',
30
31
  'better-tailwindcss/enforce-consistent-class-order': 'warn',
31
- 'better-tailwindcss/enforce-consistent-variable-syntax': 'error'
32
+ 'better-tailwindcss/enforce-consistent-variable-syntax': 'error',
33
+ 'better-tailwindcss/enforce-shorthand-classes': 'warn',
34
+ 'better-tailwindcss/enforce-consistent-important-position': 'warn'
32
35
  }
33
36
  };
34
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "13.2.1",
3
+ "version": "13.3.0",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
@@ -35,47 +35,47 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@eslint-react/eslint-plugin": "1.50.0",
39
- "@eslint/compat": "1.3.1",
40
- "@next/eslint-plugin-next": "15.3.4",
41
- "@stylistic/eslint-plugin": "5.1.0",
38
+ "@eslint-react/eslint-plugin": "1.53.1",
39
+ "@eslint/compat": "1.3.2",
40
+ "@next/eslint-plugin-next": "15.5.3",
41
+ "@stylistic/eslint-plugin": "5.3.1",
42
42
  "deepmerge": "4.3.1",
43
- "eslint-plugin-better-tailwindcss": "3.4.3",
44
- "eslint-plugin-cypress": "5.1.0",
43
+ "eslint-plugin-better-tailwindcss": "3.7.8",
44
+ "eslint-plugin-cypress": "5.1.1",
45
45
  "eslint-plugin-import-x": "4.16.1",
46
46
  "eslint-plugin-jest": "29.0.1",
47
47
  "eslint-plugin-jest-formatting": "3.1.0",
48
48
  "eslint-plugin-jsx-a11y": "6.10.2",
49
- "eslint-plugin-n": "17.20.0",
50
- "eslint-plugin-perfectionist": "4.13.0",
51
- "eslint-plugin-playwright": "2.2.0",
52
- "eslint-plugin-prettier": "5.5.1",
49
+ "eslint-plugin-n": "17.21.3",
50
+ "eslint-plugin-perfectionist": "4.15.0",
51
+ "eslint-plugin-playwright": "2.2.2",
52
+ "eslint-plugin-prettier": "5.5.4",
53
53
  "eslint-plugin-promise": "7.2.1",
54
54
  "eslint-plugin-react-hooks": "5.2.0",
55
- "eslint-plugin-regexp": "2.9.0",
55
+ "eslint-plugin-regexp": "2.10.0",
56
56
  "eslint-plugin-storybook": "0.12.0",
57
57
  "eslint-plugin-vitest": "0.5.4",
58
- "globals": "16.3.0",
59
- "local-pkg": "1.1.1",
60
- "typescript-eslint": "8.35.1"
58
+ "globals": "16.4.0",
59
+ "local-pkg": "1.1.2",
60
+ "typescript-eslint": "8.43.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint/eslintrc": "3.3.1",
64
- "@eslint/js": "9.30.1",
65
- "@semantic-release/github": "11.0.3",
64
+ "@eslint/js": "9.35.0",
65
+ "@semantic-release/github": "11.0.6",
66
66
  "@semantic-release/npm": "12.0.2",
67
- "@semantic-release/release-notes-generator": "14.0.3",
67
+ "@semantic-release/release-notes-generator": "14.1.0",
68
68
  "@types/eslint": "9.6.1",
69
- "cspell": "9.1.2",
70
- "eslint": "9.30.1",
69
+ "cspell": "9.2.1",
70
+ "eslint": "9.35.0",
71
71
  "husky": "9.1.7",
72
- "jest": "30.0.3",
73
- "lint-staged": "16.1.2",
72
+ "jest": "30.1.3",
73
+ "lint-staged": "16.1.6",
74
74
  "pinst": "3.0.0",
75
75
  "prettier": "3.6.2",
76
- "semantic-release": "24.2.6",
77
- "typescript": "5.8.3",
78
- "unbuild": "3.5.0"
76
+ "semantic-release": "24.2.8",
77
+ "typescript": "5.9.2",
78
+ "unbuild": "3.6.1"
79
79
  },
80
80
  "peerDependencies": {
81
81
  "cypress": ">=8",
package/src/index.d.ts CHANGED
@@ -93,7 +93,7 @@ export interface Options extends Linter.Config {
93
93
  * Controls [TypeScript plugin](https://www.npmjs.com/package/typescript-eslint).
94
94
  * @default true - If you have `typescript` in your dependencies.
95
95
  */
96
- typescript?: { projectService?: boolean | ProjectService; tsconfigRootDir: string; cacheLifetime?: number };
96
+ typescript?: { projectService?: boolean | ProjectService; tsconfigRootDir?: string; cacheLifetime?: number };
97
97
  /**
98
98
  * Disables expensive rules.
99
99
  * @default false
@@ -21,9 +21,33 @@ function playwright() {
21
21
  ],
22
22
  },
23
23
  ],
24
+ 'playwright/expect-expect': 'error',
24
25
  'playwright/missing-playwright-await': 'error',
26
+ 'playwright/max-nested-describe': ['warn', { max: 5 }],
27
+ 'playwright/no-duplicate-hooks': 'error',
28
+ 'playwright/no-element-handle': 'warn',
29
+ 'playwright/no-eval': 'warn',
25
30
  'playwright/no-page-pause': 'warn',
26
31
  'playwright/no-slowed-test': 'warn',
32
+ 'playwright/no-skipped-test': 'warn',
33
+ 'playwright/no-standalone-expect': 'warn',
34
+ 'playwright/no-focused-test': 'warn',
35
+ 'playwright/no-force-option': 'warn',
36
+ 'playwright/no-conditional-expect': 'warn',
37
+ 'playwright/no-conditional-in-test': 'warn',
38
+ 'playwright/no-nested-step': 'warn',
39
+ 'playwright/no-networkidle': 'warn',
40
+ 'playwright/no-useless-await': 'error',
41
+ 'playwright/no-unsafe-references': 'warn',
42
+ 'playwright/no-useless-not': 'warn',
43
+ 'playwright/no-wait-for-navigation': 'warn',
44
+ 'playwright/no-wait-for-selector': 'warn',
45
+ 'playwright/no-wait-for-timeout': 'warn',
46
+ 'playwright/prefer-web-first-assertions': 'warn',
47
+ 'playwright/valid-describe-callback': 'warn',
48
+ 'playwright/valid-expect-in-promise': 'warn',
49
+ 'playwright/valid-expect': 'warn',
50
+ 'playwright/valid-title': 'warn',
27
51
  },
28
52
  };
29
53
  }
@@ -17,11 +17,12 @@ function react() {
17
17
  },
18
18
  },
19
19
  rules: {
20
- '@eslint-react/dom/no-children-in-void-dom-elements': 'warn',
20
+ '@eslint-react/dom/no-void-elements-with-children': 'warn',
21
21
  '@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
22
22
  '@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
23
23
  '@eslint-react/dom/no-find-dom-node': 'error',
24
24
  '@eslint-react/dom/no-flush-sync': 'off',
25
+ '@eslint-react/dom/no-use-form-state': 'warn',
25
26
  '@eslint-react/dom/no-hydrate': 'warn',
26
27
  '@eslint-react/dom/no-missing-button-type': 'warn',
27
28
  '@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
@@ -31,9 +32,10 @@ function react() {
31
32
  '@eslint-react/dom/no-script-url': 'warn',
32
33
  '@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
33
34
  '@eslint-react/dom/no-unsafe-target-blank': 'warn',
34
- '@eslint-react/ensure-forward-ref-using-ref': 'off',
35
+
35
36
  '@eslint-react/jsx-key-before-spread': 'error',
36
37
  '@eslint-react/jsx-no-undef': 'off',
38
+ '@eslint-react/jsx-no-iife': 'warn',
37
39
  '@eslint-react/jsx-uses-react': 'off',
38
40
  '@eslint-react/no-access-state-in-setstate': 'error',
39
41
  '@eslint-react/no-array-index-key': 'warn',
@@ -48,11 +50,15 @@ function react() {
48
50
  '@eslint-react/no-component-will-mount': 'error',
49
51
  '@eslint-react/no-component-will-receive-props': 'error',
50
52
  '@eslint-react/no-component-will-update': 'error',
53
+ '@eslint-react/no-context-provider': 'warn',
51
54
  '@eslint-react/no-create-ref': 'error',
52
55
  '@eslint-react/no-direct-mutation-state': 'error',
53
56
  '@eslint-react/no-duplicate-key': 'error',
57
+ '@eslint-react/no-default-props': 'warn',
58
+ '@eslint-react/jsx-no-duplicate-props': 'error',
59
+ '@eslint-react/no-forward-ref': 'warn',
54
60
  '@eslint-react/no-implicit-key': 'error',
55
- '@eslint-react/no-missing-context-display-name': 'off',
61
+ '@eslint-react/no-missing-context-display-name': 'warn',
56
62
  '@eslint-react/no-missing-key': 'error',
57
63
  '@eslint-react/no-misused-capture-owner-stack': 'error',
58
64
  '@eslint-react/no-nested-component-definitions': 'warn',
@@ -69,8 +75,9 @@ function react() {
69
75
  '@eslint-react/no-unstable-default-props': 'error',
70
76
  '@eslint-react/no-unused-class-component-members': 'warn',
71
77
  '@eslint-react/no-unused-state': 'warn',
72
- '@eslint-react/no-useless-forward-ref': 'warn',
78
+ '@eslint-react/no-useless-forward-ref': 'off',
73
79
  '@eslint-react/no-useless-fragment': 'warn',
80
+ '@eslint-react/no-use-context': 'warn',
74
81
  '@eslint-react/prefer-destructuring-assignment': 'warn',
75
82
 
76
83
  '@eslint-react/prefer-shorthand-boolean': 'warn',
@@ -79,10 +86,10 @@ function react() {
79
86
  '@eslint-react/prefer-shorthand-fragment': 'warn',
80
87
  '@eslint-react/avoid-shorthand-fragment': 'off',
81
88
 
82
- '@eslint-react/hooks-extra/ensure-custom-hooks-using-other-hooks': 'warn',
83
- '@eslint-react/hooks-extra/ensure-use-memo-has-non-empty-deps': 'warn',
84
89
  '@eslint-react/hooks-extra/prefer-use-state-lazy-initialization': 'warn',
85
- '@eslint-react/hooks-extra/no-useless-custom-hooks': 'warn',
90
+ '@eslint-react/hooks-extra/no-unnecessary-use-callback': 'warn',
91
+ '@eslint-react/hooks-extra/no-unnecessary-use-prefix': 'warn',
92
+ '@eslint-react/hooks-extra/no-unnecessary-use-memo': 'warn',
86
93
 
87
94
  '@eslint-react/naming-convention/component-name': 'warn',
88
95
  '@eslint-react/naming-convention/context-name': 'warn',
@@ -90,6 +97,11 @@ function react() {
90
97
  '@eslint-react/naming-convention/filename': 'off',
91
98
  '@eslint-react/naming-convention/use-state': 'off',
92
99
 
100
+ '@eslint-react/web-api/no-leaked-timeout': 'error',
101
+ '@eslint-react/web-api/no-leaked-event-listener': 'error',
102
+ '@eslint-react/web-api/no-leaked-interval': 'error',
103
+ '@eslint-react/web-api/no-leaked-resize-observer': 'error',
104
+
93
105
  'react-hooks/exhaustive-deps': 'warn',
94
106
  'react-hooks/rules-of-hooks': 'error',
95
107
 
@@ -17,10 +17,13 @@ async function tailwind(options = {}) {
17
17
  },
18
18
  rules: {
19
19
  'better-tailwindcss/no-duplicate-classes': 'error',
20
+ 'better-tailwindcss/no-deprecated-classes': 'warn',
20
21
  'better-tailwindcss/no-conflicting-classes': 'error',
21
22
  'better-tailwindcss/no-unnecessary-whitespace': 'warn',
22
23
  'better-tailwindcss/enforce-consistent-class-order': 'warn',
23
24
  'better-tailwindcss/enforce-consistent-variable-syntax': 'error',
25
+ 'better-tailwindcss/enforce-shorthand-classes': 'warn',
26
+ 'better-tailwindcss/enforce-consistent-important-position': 'warn',
24
27
  },
25
28
  };
26
29
  }