@fullstacksjs/eslint-config 11.3.3 → 11.5.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
@@ -18,7 +18,7 @@ $ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
18
18
 
19
19
  ## Usage
20
20
 
21
- To use the configuration all you need is exporting generated config by `init` function. The configuration reads the metadata from your root `package.json` file and automatically adds the rules and plugins that are needed.
21
+ To use the configuration, all you need is to export the generated config by the `init` function. The configuration reads the metadata from your root `package.json` file and automatically adds the rules and plugins that are needed.
22
22
 
23
23
  ### ESM
24
24
 
@@ -38,7 +38,7 @@ module.exports = init();
38
38
 
39
39
  ## Modules API
40
40
 
41
- You can fine tune module detection by overriding it, `init` function accepts options as its first argument to control enabled modules.
41
+ You can fine-tune module detection by overriding it, the `init` function accepts options as its first argument to control enabled modules.
42
42
 
43
43
  ```typescript
44
44
  interface Options {
@@ -62,7 +62,7 @@ interface Options {
62
62
  cypress?: boolean; // controls cypress plugin
63
63
  playwright?: boolean // controls playwright plugin
64
64
  storybook?: boolean; // controls storybook plugin
65
- tailwind?: boolean; // controls tailwindcss plugin
65
+ tailwind?: boolean | { callee?: string[] }; // controls tailwindcss plugin
66
66
  next?: boolean; // controls next plugin
67
67
  prettier?: boolean; // controls prettier plugin
68
68
  disableExpensiveRules?: boolean; // controls expensive rules
@@ -95,7 +95,7 @@ export default init(
95
95
 
96
96
  ## Speed Optimization!
97
97
 
98
- It's crucial to balance the benefits of linting rules against their performance impact. Below is a table highlighting the most resource-intensive linting rules encountered in a real-world React project:
98
+ Balancing the benefits of linting rules against their performance impact is crucial. Below is a table highlighting the most resource-intensive linting rules encountered in a real-world React project:
99
99
 
100
100
  | Rule | Time (ms) | Relative |
101
101
  | -------------------------------------- | --------- | -------- |
@@ -108,7 +108,7 @@ As illustrated, certain rules significantly increase linting time, potentially h
108
108
 
109
109
  To conditionally disable expensive linting rules, you can modify your configuration as follows:
110
110
 
111
- list of expensiveRules to be effected:
111
+ List of `expensiveRules` to be affected:
112
112
 
113
113
  ```
114
114
  @typescript-eslint/no-floating-promises
@@ -129,19 +129,17 @@ export default init({
129
129
  });
130
130
  ```
131
131
 
132
- This approach ensures a smoother development experience while still enforcing rigorous code quality checks in environments where performance is less of a concern.
132
+ ## Migration Guide
133
133
 
134
- ## Migration Guid
134
+ ### To v11
135
135
 
136
- ### to v10
137
-
138
- v10 drops support for ESLint v8 configuration and only ESLint v9 is supported, which means you should migrate to [ESlint Flat Config](https://eslint.org/docs/latest/extend/plugin-migration-flat-config):
136
+ v11 drops support for ESLint v8 configuration and only ESLint v9 is supported, which means you should migrate to [ESlint Flat Config](https://eslint.org/docs/latest/extend/plugin-migration-flat-config):
139
137
 
140
138
  1. Move your configs to `eslint.config.js` file.
141
139
  2. Use init API.
142
140
  ```diff
143
141
  -const { init } = require('@fullstacksjs/eslint-config/init');
144
- +import { init } from '@fullstacksjs/eslint-config/init'
142
+ +import { init } from '@fullstacksjs/eslint-config';
145
143
 
146
144
  -module.exports = init({
147
145
  - modules: {
package/cjs/index.js CHANGED
@@ -62,6 +62,9 @@ const defaultOptions = {
62
62
  */
63
63
  function init(initOptions = {}, ...extend) {
64
64
  const options = (0, _deepmerge.default)(defaultOptions, initOptions);
65
+ if (options.tailwind === true) {
66
+ options.tailwind = {};
67
+ }
65
68
  if (options.typescript === true) {
66
69
  options.typescript = {};
67
70
  }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
+ var _eslintImportResolverTypescript = require("eslint-import-resolver-typescript");
7
8
  var _eslintPluginImportX = _interopRequireDefault(require("eslint-plugin-import-x"));
8
9
  var _conditions = require("../utils/conditions.js");
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -35,9 +36,10 @@ function imports(options = {}) {
35
36
  'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
36
37
  'import-x/ignore': ['node_modules', '\\.(scss|css|svg|json)$'],
37
38
  ...(0, _conditions.predicate)(options.typescript, {
38
- 'import-x/resolver': {
39
- typescript: true
40
- },
39
+ 'import-x/resolver-next': [(0, _eslintImportResolverTypescript.createTypeScriptImportResolver)({
40
+ alwaysTryTypes: true,
41
+ project: options.typescript.projects
42
+ })],
41
43
  'import-x/parsers': {
42
44
  '@typescript-eslint/parser': tsExtensions
43
45
  },
@@ -38,13 +38,11 @@ function perfectionist() {
38
38
  'perfectionist/sort-object-types': 'off',
39
39
  'perfectionist/sort-objects': 'off',
40
40
  'perfectionist/sort-sets': 'warn',
41
- 'perfectionist/sort-svelte-attributes': 'warn',
42
41
  'perfectionist/sort-switch-case': 'off',
43
42
  'perfectionist/sort-union-types': ['warn', {
44
43
  groups: ['conditional', 'function', 'import', 'intersection', 'keyword', 'literal', 'named', 'object', 'operator', 'tuple', 'union', 'nullish']
45
44
  }],
46
- 'perfectionist/sort-variable-declarations': 'warn',
47
- 'perfectionist/sort-vue-attributes': 'warn'
45
+ 'perfectionist/sort-variable-declarations': 'warn'
48
46
  }
49
47
  };
50
48
  }
@@ -4,13 +4,21 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- /** @return { Promise<import('eslint').Linter.Config> } */
8
- async function tailwind() {
7
+ /**
8
+ * @param { import('../option').Options } options
9
+ * @return { Promise<import('eslint').Linter.Config> }
10
+ */
11
+ async function tailwind(options = {}) {
9
12
  const plugin = await Promise.resolve().then(() => require('eslint-plugin-tailwindcss'));
10
13
  return {
11
14
  plugins: {
12
15
  tailwindcss: plugin.default ?? plugin
13
16
  },
17
+ settings: {
18
+ tailwindcss: {
19
+ callees: options.callees ?? ['cva', 'classnames', 'classNames', 'class', 'clsx', 'cn', 'cns', 'cx']
20
+ }
21
+ },
14
22
  rules: {
15
23
  'tailwindcss/classnames-order': 'warn',
16
24
  'tailwindcss/enforces-negative-arbitrary-values': 'warn',
@@ -232,6 +232,7 @@ function typescript(options = {}) {
232
232
  allowRegExp: false,
233
233
  allowNever: false
234
234
  }],
235
+ '@typescript-eslint/related-getter-setter-pairs': 'error',
235
236
  '@typescript-eslint/require-array-sort-compare': ['error', {
236
237
  ignoreStringArrays: true
237
238
  }],
package/cjs/option.d.ts CHANGED
@@ -4,7 +4,7 @@ export interface Options extends Linter.Config {
4
4
  react?: boolean;
5
5
  sort?: boolean;
6
6
  next?: boolean;
7
- tailwind?: boolean;
7
+ tailwind?: boolean | { callees: string[] };
8
8
  node?: boolean;
9
9
  strict?: boolean;
10
10
  import?: { internalRegExp?: string; lifetime?: number; projects?: string | string[] } | boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "11.3.3",
3
+ "version": "11.5.0",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
@@ -34,48 +34,48 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
- "@eslint-react/eslint-plugin": "1.15.0",
38
- "@next/eslint-plugin-next": "14.2.15",
37
+ "@eslint-react/eslint-plugin": "1.19.0",
38
+ "@next/eslint-plugin-next": "15.1.0",
39
39
  "deepmerge": "4.3.1",
40
- "eslint-import-resolver-typescript": "3.6.3",
41
- "eslint-plugin-cypress": "4.0.0",
42
- "eslint-plugin-import-x": "4.3.1",
43
- "eslint-plugin-jest": "28.8.3",
40
+ "eslint-import-resolver-typescript": "3.7.0",
41
+ "eslint-plugin-cypress": "4.1.0",
42
+ "eslint-plugin-import-x": "4.5.0",
43
+ "eslint-plugin-jest": "28.9.0",
44
44
  "eslint-plugin-jest-formatting": "3.1.0",
45
- "eslint-plugin-jsx-a11y": "6.10.0",
46
- "eslint-plugin-n": "17.11.1",
47
- "eslint-plugin-perfectionist": "3.9.1",
48
- "eslint-plugin-playwright": "1.7.0",
45
+ "eslint-plugin-jsx-a11y": "6.10.2",
46
+ "eslint-plugin-n": "17.15.0",
47
+ "eslint-plugin-perfectionist": "4.3.0",
48
+ "eslint-plugin-playwright": "2.1.0",
49
49
  "eslint-plugin-prettier": "5.2.1",
50
- "eslint-plugin-promise": "7.1.0",
51
- "eslint-plugin-react-hooks": "5.0.0",
52
- "eslint-plugin-storybook": "0.9.0",
50
+ "eslint-plugin-promise": "7.2.1",
51
+ "eslint-plugin-react-hooks": "5.1.0",
52
+ "eslint-plugin-storybook": "0.11.1",
53
53
  "eslint-plugin-tailwindcss": "3.17.5",
54
54
  "eslint-plugin-vitest": "0.5.4",
55
- "globals": "15.11.0",
56
- "local-pkg": "0.5.0",
57
- "typescript-eslint": "8.10.0"
55
+ "globals": "15.13.0",
56
+ "local-pkg": "0.5.1",
57
+ "typescript-eslint": "8.18.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@eslint/eslintrc": "3.1.0",
61
- "@eslint/js": "9.12.0",
62
- "@semantic-release/github": "11.0.0",
60
+ "@eslint/eslintrc": "3.2.0",
61
+ "@eslint/js": "9.17.0",
62
+ "@semantic-release/github": "11.0.1",
63
63
  "@semantic-release/npm": "12.0.1",
64
64
  "@semantic-release/release-notes-generator": "14.0.1",
65
65
  "@types/eslint": "9.6.1",
66
- "cspell": "8.15.3",
67
- "eslint": "9.12.0",
66
+ "cspell": "8.16.1",
67
+ "eslint": "9.17.0",
68
68
  "eslint-find-rules": "4.2.0",
69
- "husky": "9.1.6",
69
+ "husky": "9.1.7",
70
70
  "jest": "29.7.0",
71
- "lint-staged": "15.2.10",
72
- "np": "10.0.7",
71
+ "lint-staged": "15.2.11",
72
+ "np": "10.1.0",
73
73
  "npm-run-all": "4.1.5",
74
74
  "pinst": "3.0.0",
75
- "prettier": "3.3.3",
76
- "semantic-release": "24.1.2",
77
- "typescript": "^5.4",
78
- "unbuild": "2.0.0"
75
+ "prettier": "3.4.2",
76
+ "semantic-release": "24.2.0",
77
+ "typescript": "5.7.2",
78
+ "unbuild": "^2"
79
79
  },
80
80
  "peerDependencies": {
81
81
  "cypress": ">=8",
package/src/index.mjs CHANGED
@@ -55,6 +55,10 @@ const defaultOptions = {
55
55
  */
56
56
  export function init(initOptions = {}, ...extend) {
57
57
  const options = merge(defaultOptions, initOptions);
58
+
59
+ if (options.tailwind === true) {
60
+ options.tailwind = {};
61
+ }
58
62
  if (options.typescript === true) {
59
63
  options.typescript = {};
60
64
  }
@@ -1,3 +1,4 @@
1
+ import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
1
2
  import plugin from 'eslint-plugin-import-x';
2
3
 
3
4
  import { predicate } from '../utils/conditions.mjs';
@@ -31,7 +32,12 @@ function imports(options = {}) {
31
32
  'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
32
33
  'import-x/ignore': ['node_modules', '\\.(scss|css|svg|json)$'],
33
34
  ...predicate(options.typescript, {
34
- 'import-x/resolver': { typescript: true },
35
+ 'import-x/resolver-next': [
36
+ createTypeScriptImportResolver({
37
+ alwaysTryTypes: true,
38
+ project: options.typescript.projects,
39
+ }),
40
+ ],
35
41
  'import-x/parsers': { '@typescript-eslint/parser': tsExtensions },
36
42
  'import-x/extensions': allExtensions,
37
43
  }),
@@ -45,7 +45,6 @@ function perfectionist() {
45
45
  'perfectionist/sort-object-types': 'off',
46
46
  'perfectionist/sort-objects': 'off',
47
47
  'perfectionist/sort-sets': 'warn',
48
- 'perfectionist/sort-svelte-attributes': 'warn',
49
48
  'perfectionist/sort-switch-case': 'off',
50
49
  'perfectionist/sort-union-types': [
51
50
  'warn',
@@ -67,7 +66,6 @@ function perfectionist() {
67
66
  },
68
67
  ],
69
68
  'perfectionist/sort-variable-declarations': 'warn',
70
- 'perfectionist/sort-vue-attributes': 'warn',
71
69
  },
72
70
  };
73
71
  }
@@ -1,8 +1,16 @@
1
- /** @return { Promise<import('eslint').Linter.Config> } */
2
- async function tailwind() {
1
+ /**
2
+ * @param { import('../option').Options } options
3
+ * @return { Promise<import('eslint').Linter.Config> }
4
+ */
5
+ async function tailwind(options = {}) {
3
6
  const plugin = await import('eslint-plugin-tailwindcss');
4
7
  return {
5
8
  plugins: { tailwindcss: plugin.default ?? plugin },
9
+ settings: {
10
+ tailwindcss: {
11
+ callees: options.callees ?? ['cva', 'classnames', 'classNames', 'class', 'clsx', 'cn', 'cns', 'cx'],
12
+ },
13
+ },
6
14
  rules: {
7
15
  'tailwindcss/classnames-order': 'warn',
8
16
  'tailwindcss/enforces-negative-arbitrary-values': 'warn',
@@ -207,6 +207,7 @@ function typescript(options = {}) {
207
207
  'warn',
208
208
  { allowNumber: true, allowBoolean: false, allowAny: false, allowNullish: false, allowRegExp: false, allowNever: false },
209
209
  ],
210
+ '@typescript-eslint/related-getter-setter-pairs': 'error',
210
211
  '@typescript-eslint/require-array-sort-compare': ['error', { ignoreStringArrays: true }],
211
212
  '@typescript-eslint/require-await': 'error',
212
213
  '@typescript-eslint/return-await': 'error',
package/src/option.d.ts CHANGED
@@ -4,7 +4,7 @@ export interface Options extends Linter.Config {
4
4
  react?: boolean;
5
5
  sort?: boolean;
6
6
  next?: boolean;
7
- tailwind?: boolean;
7
+ tailwind?: boolean | { callees: string[] };
8
8
  node?: boolean;
9
9
  strict?: boolean;
10
10
  import?: { internalRegExp?: string; lifetime?: number; projects?: string | string[] } | boolean;