@fullstacksjs/eslint-config 13.11.2 → 13.13.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
@@ -27,7 +27,10 @@ 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();
30
+ export default defineConfig({
31
+ typescript: {
32
+ tsconfigRootDir: import.meta.dirname, // Recommended when using TypeScript
33
+ });
31
34
  ```
32
35
 
33
36
  ### CJS
@@ -35,7 +38,11 @@ export default defineConfig();
35
38
  ```js
36
39
  const { defineConfig } = require('@fullstacksjs/eslint-config');
37
40
 
38
- module.exports = defineConfig();
41
+ module.exports = defineConfig({
42
+ typescript: {
43
+ tsconfigRootDir: __dirname, // Recommended when using TypeScript
44
+ }
45
+ });
39
46
  ```
40
47
 
41
48
  ## How Module Detection Works
@@ -192,7 +192,7 @@ function base(options = {}) {
192
192
  }]),
193
193
  'prefer-destructuring': ['warn', {
194
194
  object: true,
195
- array: true
195
+ array: false
196
196
  }],
197
197
  'prefer-exponentiation-operator': 'warn',
198
198
  'prefer-numeric-literals': 'error',
@@ -50,6 +50,7 @@ function jest() {
50
50
  'jest/no-test-callback': 'off',
51
51
  'jest/no-test-prefixes': 'error',
52
52
  'jest/no-test-return-statement': 'off',
53
+ 'jest/no-unneeded-async-expect-function': 'warn',
53
54
  'jest/no-truthy-falsy': 'off',
54
55
  'jest/prefer-called-with': 'error',
55
56
  'jest/prefer-each': 'warn',
@@ -19,18 +19,25 @@ function perfectionist() {
19
19
  'perfectionist/sort-classes': 'off',
20
20
  'perfectionist/sort-enums': 'off',
21
21
  'perfectionist/sort-exports': 'warn',
22
- 'perfectionist/sort-imports': ['warn', {}],
22
+ 'perfectionist/sort-export-attributes': 'warn',
23
+ 'perfectionist/sort-imports': 'warn',
24
+ 'perfectionist/sort-import-attributes': 'warn',
23
25
  'perfectionist/sort-interfaces': 'off',
24
26
  'perfectionist/sort-intersection-types': ['warn', {
25
27
  groups: ['conditional', 'function', 'import', 'intersection', 'keyword', 'literal', 'named', 'object', 'operator', 'tuple', 'union', 'nullish']
26
28
  }],
27
29
  'perfectionist/sort-jsx-props': ['warn', {
28
30
  groups: ['attr', 'shorthand', 'size', 'unknown', 'callback', 'multiline'],
29
- customGroups: {
30
- callback: 'on*',
31
- size: ['width', 'size', 'height'],
32
- attr: ['dir', 'lang']
33
- }
31
+ customGroups: [{
32
+ groupName: 'callback',
33
+ elementNamePattern: '^on.+'
34
+ }, {
35
+ groupName: 'size',
36
+ elementNamePattern: ['width', 'size', 'height']
37
+ }, {
38
+ groupName: 'attr',
39
+ elementNamePattern: ['dir', 'lang']
40
+ }]
34
41
  }],
35
42
  'perfectionist/sort-maps': 'off',
36
43
  'perfectionist/sort-named-exports': 'warn',
@@ -20,6 +20,67 @@ function stylistic() {
20
20
  props: 'never',
21
21
  children: 'never',
22
22
  propElementValues: 'always'
23
+ }],
24
+ '@stylistic/jsx-self-closing-comp': ['warn', {
25
+ component: true,
26
+ html: true
27
+ }],
28
+ '@stylistic/no-mixed-operators': 'error',
29
+ '@stylistic/padding-line-between-statements': ['warn', {
30
+ blankLine: 'always',
31
+ prev: ['case', 'default'],
32
+ next: '*'
33
+ }, {
34
+ blankLine: 'always',
35
+ prev: '*',
36
+ next: 'multiline-block-like'
37
+ }, {
38
+ blankLine: 'always',
39
+ prev: 'multiline-block-like',
40
+ next: '*'
41
+ }, {
42
+ blankLine: 'always',
43
+ prev: ['type', 'interface'],
44
+ next: '*'
45
+ }, {
46
+ blankLine: 'always',
47
+ prev: 'directive',
48
+ next: '*'
49
+ }, {
50
+ blankLine: 'never',
51
+ prev: 'directive',
52
+ next: 'directive'
53
+ }, {
54
+ blankLine: 'always',
55
+ prev: 'import',
56
+ next: '*'
57
+ }, {
58
+ blankLine: 'any',
59
+ prev: '*',
60
+ next: 'import'
61
+ }, {
62
+ blankLine: 'always',
63
+ prev: 'directive',
64
+ next: 'import'
65
+ }, {
66
+ blankLine: 'any',
67
+ prev: ['if'],
68
+ next: ['if']
69
+ }],
70
+ '@stylistic/lines-between-class-members': ['warn', {
71
+ enforce: [{
72
+ blankLine: 'never',
73
+ prev: 'field',
74
+ next: 'field'
75
+ }, {
76
+ blankLine: 'always',
77
+ prev: '*',
78
+ next: 'method'
79
+ }, {
80
+ blankLine: 'always',
81
+ prev: 'method',
82
+ next: '*'
83
+ }]
23
84
  }]
24
85
  }
25
86
  };
@@ -128,6 +128,7 @@ function typescript(options = {}) {
128
128
  classes: true
129
129
  }],
130
130
  '@typescript-eslint/no-useless-constructor': 'error',
131
+ '@typescript-eslint/no-useless-default-assignment': 'warn',
131
132
  '@typescript-eslint/no-useless-empty-export': 'warn',
132
133
  '@typescript-eslint/parameter-properties': 'off',
133
134
  '@typescript-eslint/prefer-as-const': 'warn',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "13.11.2",
3
+ "version": "13.13.0",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
@@ -15,6 +15,7 @@
15
15
  "src",
16
16
  "cjs"
17
17
  ],
18
+ "packageManager": "npm@11.7.0",
18
19
  "scripts": {
19
20
  "lint": "eslint .",
20
21
  "spell": "cspell ./* --no-progress",
@@ -35,45 +36,45 @@
35
36
  }
36
37
  },
37
38
  "dependencies": {
38
- "@eslint-react/eslint-plugin": "2.3.9",
39
+ "@eslint-react/eslint-plugin": "2.3.13",
39
40
  "@eslint/compat": "2.0.0",
40
- "@next/eslint-plugin-next": "16.0.6",
41
+ "@next/eslint-plugin-next": "16.0.10",
41
42
  "@stylistic/eslint-plugin": "5.6.1",
42
- "@vitest/eslint-plugin": "1.5.1",
43
+ "@vitest/eslint-plugin": "1.5.2",
43
44
  "deepmerge": "4.3.1",
44
- "eslint-plugin-better-tailwindcss": "3.7.11",
45
+ "eslint-plugin-better-tailwindcss": "3.8.0",
45
46
  "eslint-plugin-cypress": "5.2.0",
46
47
  "eslint-plugin-import-x": "4.16.1",
47
- "eslint-plugin-jest": "29.2.1",
48
+ "eslint-plugin-jest": "29.5.0",
48
49
  "eslint-plugin-jsx-a11y": "6.10.2",
49
50
  "eslint-plugin-n": "17.23.1",
50
- "eslint-plugin-perfectionist": "4.15.1",
51
- "eslint-plugin-playwright": "2.3.0",
51
+ "eslint-plugin-perfectionist": "5.0.0",
52
+ "eslint-plugin-playwright": "2.4.0",
52
53
  "eslint-plugin-prettier": "5.5.4",
53
54
  "eslint-plugin-promise": "7.2.1",
54
55
  "eslint-plugin-react-hooks": "7.0.1",
55
56
  "eslint-plugin-regexp": "2.10.0",
56
- "eslint-plugin-storybook": "10.1.2",
57
+ "eslint-plugin-storybook": "10.1.10",
57
58
  "globals": "16.5.0",
58
59
  "local-pkg": "1.1.2",
59
- "typescript-eslint": "8.48.0"
60
+ "typescript-eslint": "8.50.0"
60
61
  },
61
62
  "devDependencies": {
62
63
  "@eslint/eslintrc": "3.3.3",
63
- "@eslint/js": "9.39.1",
64
+ "@eslint/js": "9.39.2",
64
65
  "@semantic-release/github": "12.0.2",
65
- "@semantic-release/npm": "13.1.2",
66
+ "@semantic-release/npm": "13.1.3",
66
67
  "@semantic-release/release-notes-generator": "14.1.0",
67
68
  "@types/eslint": "9.6.1",
68
69
  "cspell": "9.4.0",
69
- "eslint": "9.39.1",
70
+ "eslint": "9.39.2",
70
71
  "husky": "9.1.7",
71
72
  "jest": "30.2.0",
72
73
  "lint-staged": "16.2.7",
73
74
  "pinst": "3.0.0",
74
- "prettier": "3.7.3",
75
+ "prettier": "3.7.4",
75
76
  "semantic-release": "25.0.2",
76
- "storybook": "10.1.2",
77
+ "storybook": "10.1.10",
77
78
  "typescript": "5.9.3",
78
79
  "unbuild": "3.6.1"
79
80
  },
@@ -99,7 +100,6 @@
99
100
  }
100
101
  },
101
102
  "volta": {
102
- "node": "22.20.0",
103
- "npm": "11.6.2"
103
+ "node": "24.12.0"
104
104
  }
105
105
  }
@@ -165,7 +165,7 @@ function base(options = {}) {
165
165
  requireCatchParameter: true,
166
166
  },
167
167
  ]),
168
- 'prefer-destructuring': ['warn', { object: true, array: true }],
168
+ 'prefer-destructuring': ['warn', { object: true, array: false }],
169
169
  'prefer-exponentiation-operator': 'warn',
170
170
  'prefer-numeric-literals': 'error',
171
171
  'prefer-object-has-own': 'warn',
@@ -39,6 +39,7 @@ function jest() {
39
39
  'jest/no-test-callback': 'off',
40
40
  'jest/no-test-prefixes': 'error',
41
41
  'jest/no-test-return-statement': 'off',
42
+ 'jest/no-unneeded-async-expect-function': 'warn',
42
43
  'jest/no-truthy-falsy': 'off',
43
44
  'jest/prefer-called-with': 'error',
44
45
  'jest/prefer-each': 'warn',
@@ -11,7 +11,9 @@ function perfectionist() {
11
11
  'perfectionist/sort-classes': 'off',
12
12
  'perfectionist/sort-enums': 'off',
13
13
  'perfectionist/sort-exports': 'warn',
14
- 'perfectionist/sort-imports': ['warn', {}],
14
+ 'perfectionist/sort-export-attributes': 'warn',
15
+ 'perfectionist/sort-imports': 'warn',
16
+ 'perfectionist/sort-import-attributes': 'warn',
15
17
  'perfectionist/sort-interfaces': 'off',
16
18
  'perfectionist/sort-intersection-types': [
17
19
  'warn',
@@ -36,7 +38,20 @@ function perfectionist() {
36
38
  'warn',
37
39
  {
38
40
  groups: ['attr', 'shorthand', 'size', 'unknown', 'callback', 'multiline'],
39
- customGroups: { callback: 'on*', size: ['width', 'size', 'height'], attr: ['dir', 'lang'] },
41
+ customGroups: [
42
+ {
43
+ groupName: 'callback',
44
+ elementNamePattern: '^on.+',
45
+ },
46
+ {
47
+ groupName: 'size',
48
+ elementNamePattern: ['width', 'size', 'height'],
49
+ },
50
+ {
51
+ groupName: 'attr',
52
+ elementNamePattern: ['dir', 'lang'],
53
+ },
54
+ ],
40
55
  },
41
56
  ],
42
57
  'perfectionist/sort-maps': 'off',
@@ -9,6 +9,37 @@ function stylistic() {
9
9
  plugins: { '@stylistic': stylisticPlugin },
10
10
  rules: {
11
11
  '@stylistic/jsx-curly-brace-presence': ['warn', { props: 'never', children: 'never', propElementValues: 'always' }],
12
+ '@stylistic/jsx-self-closing-comp': [
13
+ 'warn',
14
+ {
15
+ component: true,
16
+ html: true,
17
+ },
18
+ ],
19
+ '@stylistic/no-mixed-operators': 'error',
20
+ '@stylistic/padding-line-between-statements': [
21
+ 'warn',
22
+ { blankLine: 'always', prev: ['case', 'default'], next: '*' },
23
+ { blankLine: 'always', prev: '*', next: 'multiline-block-like' },
24
+ { blankLine: 'always', prev: 'multiline-block-like', next: '*' },
25
+ { blankLine: 'always', prev: ['type', 'interface'], next: '*' },
26
+ { blankLine: 'always', prev: 'directive', next: '*' },
27
+ { blankLine: 'never', prev: 'directive', next: 'directive' },
28
+ { blankLine: 'always', prev: 'import', next: '*' },
29
+ { blankLine: 'any', prev: '*', next: 'import' },
30
+ { blankLine: 'always', prev: 'directive', next: 'import' },
31
+ { blankLine: 'any', prev: ['if'], next: ['if'] },
32
+ ],
33
+ '@stylistic/lines-between-class-members': [
34
+ 'warn',
35
+ {
36
+ enforce: [
37
+ { blankLine: 'never', prev: 'field', next: 'field' },
38
+ { blankLine: 'always', prev: '*', next: 'method' },
39
+ { blankLine: 'always', prev: 'method', next: '*' },
40
+ ],
41
+ },
42
+ ],
12
43
  },
13
44
  };
14
45
  }
@@ -117,6 +117,7 @@ function typescript(options = {}) {
117
117
  ],
118
118
  '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: true }],
119
119
  '@typescript-eslint/no-useless-constructor': 'error',
120
+ '@typescript-eslint/no-useless-default-assignment': 'warn',
120
121
  '@typescript-eslint/no-useless-empty-export': 'warn',
121
122
  '@typescript-eslint/parameter-properties': 'off',
122
123
  '@typescript-eslint/prefer-as-const': 'warn',