@fullstacksjs/eslint-config 9.0.14 → 9.0.16

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
@@ -12,138 +12,158 @@
12
12
 
13
13
  ## Installation
14
14
 
15
- If you use [ESLint](https://eslint.org/) alongside [TypeScript](https://typescriptlang.org/)
16
-
17
- ### npm :
18
-
19
- ```sh
20
- $ npm install --save-dev @fullstacksjs/eslint-config eslint prettier typescript
21
- ```
22
-
23
- ### yarn :
24
-
25
- ```sh
26
- $ yarn add --dev @fullstacksjs/eslint-config eslint prettier typescript
27
- ```
28
-
29
- for JavaScript development
30
-
31
- ### npm :
32
-
33
15
  ```sh
34
16
  $ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
35
17
  ```
36
18
 
37
- ### yarn :
38
-
39
- ```sh
40
- $ yarn add --dev @fullstacksjs/eslint-config eslint prettier
41
- ```
19
+ ## Usage
42
20
 
43
- optional dependencies (if you need):
21
+ ### Method 1: Init API
44
22
 
45
- * react
46
- * jest
47
- * cypress
23
+ Create `.eslintrc.js` file and init the configuration.
48
24
 
49
- ## Usage
25
+ ```js
26
+ const { init } = require('@fullstacksjs/eslint-config/init');
50
27
 
51
- Just extend from `@fullstacksjs`:
28
+ module.exports = init({
29
+ modules: {
30
+ auto: true, // If you need auto module detection (refer to Auto Module Detection).
31
+ // Modules configuration check (optional). (refer to Module API)
32
+ },
33
+ // Your configurations
34
+ });
52
35
 
53
- ```json
54
- {
55
- "extends": ["@fullstacksjs"]
56
- }
57
36
  ```
58
37
 
59
- It reads your root `package.json` dependencies and includes necessary rules.
60
-
61
- ## NextJS
62
-
63
- Our index setup conflicts with the built-in ESLint [NextJS](https://nextjs.org/) configuration. To utilize it in a NextJS project, configure your eslintrc file as follows.
38
+ ### Method 2: Extends API
39
+ You can also use the configuration within a `json` or `yaml` files by extending from `@fullstacksjs`, the Auto Module Detection is enabled on this method
64
40
 
65
41
  ```json
66
42
  {
67
- "extends": ["next/core-web-vitals", "@fullstacksjs/eslint-config/nextjs"]
43
+ "extends": ["@fullstacksjs"]
68
44
  }
69
45
  ```
70
46
 
71
- ## Advanced Usage
72
-
73
- ```jsonc
74
- {
75
- "extends": [
76
- "@fullstacksjs/eslint-config/base",
77
- "@fullstacksjs/eslint-config/jest",
78
- "@fullstacksjs/eslint-config/react",
79
- "@fullstacksjs/eslint-config/typescript",
80
- "@fullstacksjs/eslint-config/strict",
81
- "@fullstacksjs/eslint-config/cypress",
82
- "@fullstacksjs/eslint-config/storybook",
83
- "@fullstacksjs/eslint-config/graphql", // Need extra config
84
- "@fullstacksjs/eslint-config/esm", // for native ESM modules
85
- "@fullstacksjs/eslint-config/typecheck" // ⚠️ Needs configurations (not included in default config)
86
- ]
47
+ ## Auto Module Detection
48
+
49
+ When auto module detection is turned on, the configuration reads the metadata from your root "package.json" file and automatically adds the rules and plugins that are needed. It's enabled for the `extends` API, and you should set `modules.auto` to `true` when you use the `init` API.
50
+
51
+ ## Modules API
52
+
53
+ ```typescript
54
+ interface Modules {
55
+ auto?: boolean; // Auto module detection
56
+ react?: 'next' | 'raw'; // controls react, react-hooks, jsx/a11y plugins
57
+ typescript?: { // controls typescript plugin
58
+ parserProject?: string[] | string; // controls parserOptions.project
59
+ resolverProject?: string[] | string // controls settings['import/resolver'].typescript.project
60
+ };
61
+ node?: boolean; // controls node plugin
62
+ strict?: boolean; // controls strict plugin
63
+ import?: boolean; // controls import plugin
64
+ esm?: boolean; // controls esm plugin
65
+ graphql?: boolean; // controls graphql plugin
66
+ test?: boolean; // controls jest/vitest plugin
67
+ cypress?: boolean; // controls cypress plugin
68
+ storybook?: boolean; // controls storybook plugin
87
69
  }
88
70
  ```
89
71
 
90
- ## Need more typescript rules?
72
+ ## Typescript configuration
91
73
 
92
- If you need more advanced `typescript-eslint` rules, then you can extend from `"@fullstacksjs/eslint-config/typecheck"` and set `parserOptions.project` option:
74
+ If you need more advanced typescript-eslint rule you need to specify `modules.typescript.resolverProject`.
93
75
 
94
- ```json
95
- {
96
- "extends": [
97
- "@fullstacksjs",
98
- "@fullstacksjs/eslint-config/typecheck"
99
- ],
100
- "parserOptions": {
101
- "project": "<PATH_TO_TSCONFIG>"
102
- }
103
- }
76
+ ```js
77
+ module.exports = init({
78
+ modules: {
79
+ typescript: { resolverProject: "<PATH_TO_TSCONFIG>" }
80
+ },
81
+ });
104
82
  ```
105
83
 
106
- ## Graphql
84
+ ## React/NextJS configuration
107
85
 
108
- To enable graphql module you need to extends from `@fullstacksjs/eslint-config/graphql` and configure schema and operations in you eslint config or graphql config. for more information checkout [here](https://github.com/B2o5T/graphql-eslint#configuration).
86
+ React/NextJS configuration should automatically work with Auto Module Detection, but if you need to have more control over the rules you can configure it through `modules.react`.
109
87
 
110
- Here is an example:
111
-
112
- ```jsonc
113
- // eslintrc
114
-
115
- {
116
- "extends": [
117
- ...
118
- "@fullstacksjs/eslint-config/graphql"
119
- ],
120
- }
88
+ ```js
89
+ module.exports = init({
90
+ modules: {
91
+ react: 'raw' // for React/CRA/Vite
92
+ },
93
+ });
121
94
  ```
122
95
 
123
- ```yaml
124
- # .graphqlrc.yml
96
+ and
125
97
 
126
- schema: 'path/to/schema'
98
+ ```js
99
+ module.exports = init({
100
+ modules: {
101
+ react: 'next' // for NextJS
102
+ },
103
+ });
127
104
  ```
128
105
 
106
+ ## Migration Guid
107
+
108
+ ### to v9
109
+
110
+ v9 does not have any breaking change, which means the current configuration you have should work without any problem, but in order to migrate to new Module API:
111
+
112
+ 1. Move your configs to `.eslintrc.js` file.
113
+ 2. Use init API.
114
+ ```diff
115
+ -module.exports = {
116
+ - extends: [
117
+ - "@fullstacksjs",
118
+ - "@fullstacksjs/eslint-config/esm",
119
+ - "@fullstacksjs/eslint-config/typecheck",
120
+ - "@fullstacksjs/eslint-config/graphql"
121
+ - ],
122
+ - "parserOptions": {
123
+ - "project": ["./tsconfig.eslint.json"]
124
+ - },
125
+ - "settings": {
126
+ - "import/resolver": {
127
+ - "typescript": {
128
+ - "project": ["./tsconfig.json"]
129
+ - },
130
+ - },
131
+ - },
132
+ - // your configuration
133
+ -};
134
+ +const { init } = require('@fullstacksjs/eslint-config/init');
135
+ +
136
+ +module.exports = init({
137
+ + modules: {
138
+ + auto: true,
139
+ + esm: true,
140
+ + graphql: true,
141
+ + typescript: {
142
+ + parserProject: ['./tsconfig.eslint.json'],
143
+ + resolverProject: ['./tsconfig.json'],
144
+ + },
145
+ + },
146
+ + // your configuration
147
+ +});
148
+ ```
129
149
 
130
150
  ## What's included?
131
151
 
132
- * @typescript-eslint/eslint-plugin
133
- * eslint-plugin-import
134
- * eslint-plugin-jest
135
- * eslint-plugin-jest-formatting
136
- * eslint-plugin-cypress
137
- * eslint-plugin-jsx-a11y
138
- * eslint-plugin-prettier
139
- * eslint-plugin-react
140
- * eslint-plugin-react-hooks
141
- * eslint-plugin-simple-import-sort
142
- * eslint-plugin-fp
143
- * eslint-plugin-node
144
- * eslint-plugin-promise
145
- * eslint-plugin-storybook
146
- * eslint-plugin-graphql
152
+ * [@typescript-eslint/eslint-plugin](https://typescript-eslint.io/)
153
+ * [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import)
154
+ * [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest)
155
+ * [eslint-plugin-jest-formatting](https://github.com/dangreenisrael/eslint-plugin-jest-formatting)
156
+ * [eslint-plugin-cypress](https://github.com/cypress-io/eslint-plugin-cypress)
157
+ * [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
158
+ * [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)
159
+ * [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react)
160
+ * [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks)
161
+ * [eslint-plugin-simple-import-sort](https://github.com/lydell/eslint-plugin-simple-import-sort)
162
+ * [eslint-plugin-fp](https://github.com/jfmengels/eslint-plugin-fp)
163
+ * [eslint-plugin-node](https://github.com/mysticatea/eslint-plugin-node)
164
+ * [eslint-plugin-promise](https://github.com/eslint-community/eslint-plugin-promise)
165
+ * [eslint-plugin-storybook](https://github.com/storybookjs/eslint-plugin-storybook#readme)
166
+ * [eslint-plugin-graphql](https://github.com/apollographql/eslint-plugin-graphql)
147
167
 
148
168
  That's all. Feel free to use 💛
149
169
 
package/cypress.js CHANGED
@@ -6,7 +6,7 @@ const { exts } = require('./utils');
6
6
  module.exports = {
7
7
  overrides: [
8
8
  {
9
- files: [`**/cypress/**/*.${exts}`, `**/*.cy.+${exts}`],
9
+ files: [`**/cypress/**/*.${exts}`, `**/*.cy.${exts}`],
10
10
  plugins: ['jest', 'jest-formatting', 'cypress'],
11
11
  env: {
12
12
  'cypress/globals': true,
package/esm.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /** @type { import('eslint').Linter.Config } */
2
2
  module.exports = {
3
3
  rules: {
4
- 'import/extensions': ['error', { mjs: 'ignorePackages' }],
4
+ ...(global.fullstacksjs?.import && { 'import/extensions': ['error', { mjs: 'ignorePackages' }] }),
5
5
  },
6
6
  overrides: [
7
7
  {
8
8
  files: ['*.ts', '*.tsx'],
9
9
  rules: {
10
- 'import/no-unresolved': ['error', { ignore: ['.js$'], caseSensitiveStrict: true }],
10
+ ...(global.fullstacksjs?.import && { 'import/no-unresolved': ['error', { ignore: ['.js$'], caseSensitiveStrict: true }] }),
11
11
  },
12
12
  },
13
13
  ],
package/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  require('./registerOpts');
2
- const { compact } = require('@fullstacksjs/toolbox');
3
2
 
4
3
  /** @type { import('eslint').Linter.Config } */
5
4
  module.exports = {
6
- extends: compact([
5
+ extends: [
7
6
  require.resolve('./base'),
8
7
  require.resolve('./fp'),
9
8
  require.resolve('./import'),
@@ -15,5 +14,5 @@ module.exports = {
15
14
  global.fullstacksjs?.typescript && require.resolve('./typescript'),
16
15
  global.fullstacksjs?.cypress && require.resolve('./cypress'),
17
16
  require.resolve('./prettier'),
18
- ]),
17
+ ].filter(Boolean),
19
18
  };
package/init.d.ts CHANGED
@@ -1,15 +1,18 @@
1
- export interface Options {
2
- react: 'next' | 'raw';
3
- typescript: { parserProject: string[] | string; resolverProject: string[] | string };
4
- node: boolean;
5
- strict: boolean;
6
- import: boolean;
7
- esm: boolean;
8
- graphql: boolean;
9
- test: boolean;
10
- cypress: boolean;
11
- storybook: boolean;
12
- overrides: import('eslint').Linter.Config;
1
+ type Config = import('eslint').Linter.Config;
2
+ export interface Options extends Config {
3
+ modules: {
4
+ auto?: boolean;
5
+ react?: 'next' | 'raw';
6
+ typescript?: { parserProject: string[] | string; resolverProject: string[] | string };
7
+ node?: boolean;
8
+ strict?: boolean;
9
+ import?: boolean;
10
+ esm?: boolean;
11
+ graphql?: boolean;
12
+ test?: boolean;
13
+ cypress?: boolean;
14
+ storybook?: boolean;
15
+ };
13
16
  }
14
17
 
15
18
  export declare const init: (opts: Options) => import('eslint').Linter.Config;
package/init.js CHANGED
@@ -1,34 +1,38 @@
1
- require('./registerOpts');
2
- const { compact } = require('@fullstacksjs/toolbox');
3
1
  const merge = require('deepmerge');
4
2
 
5
3
  /** @param { import('./init.d').Options } opts */
6
4
  // eslint-disable-next-line complexity
7
5
  function init(opts = {}) {
8
- const { extends: extendsOverrides, ...overrides } = opts.overrides;
9
- global.fullstacksjs = merge(global.fullstacksjs, opts);
6
+ const { modules = {}, extends: extraExtends = [], ...eslintConfig } = opts;
7
+ if (modules.auto) {
8
+ require('./registerOpts');
9
+ global.fullstacksjs = merge(global.fullstacksjs, modules);
10
+ } else {
11
+ global.fullstacksjs = modules;
12
+ }
13
+ opts = global.fullstacksjs;
10
14
 
11
15
  /** @type { import('eslint').Linter.Config } */
12
16
  const config = {
13
- extends: compact([
17
+ extends: [
14
18
  require.resolve('./base'),
15
19
  require.resolve('./promise'),
16
20
  require.resolve('./fp'),
17
21
  opts.node && require.resolve('./node'),
18
- opts.cypress && require.resolve('./cypress'),
19
- opts.test && require.resolve('./jest'),
20
22
  opts.graphql && require.resolve('./graphql'),
21
- opts.storybook && require.resolve('./storybook'),
22
- opts.importModule && require.resolve('./import'),
23
+ opts.import && require.resolve('./import'),
23
24
  opts.typescript && require.resolve('./typescript'),
25
+ opts.storybook && require.resolve('./storybook'),
26
+ opts.cypress && require.resolve('./cypress'),
27
+ opts.test && require.resolve('./jest'),
24
28
  opts.esm && require.resolve('./esm'),
25
29
  opts.strict && require.resolve('./strict'),
26
30
  require.resolve('./prettier'),
27
- ...(extendsOverrides ?? []),
28
- ]),
31
+ ...extraExtends,
32
+ ].filter(Boolean),
29
33
  parserOptions: {},
30
34
  settings: {},
31
- ...overrides,
35
+ ...eslintConfig,
32
36
  };
33
37
 
34
38
  if (opts.react === 'raw') config.extends.push(require.resolve('./react.js'));
package/jest.js CHANGED
@@ -68,7 +68,7 @@ module.exports = {
68
68
  'jest/no-deprecated-functions': 'error',
69
69
  }),
70
70
 
71
- ...(global.fullstacksjs?.typescript && {
71
+ ...(global.fullstacksjs?.typescript?.resolverProject && {
72
72
  '@typescript-eslint/unbound-method': 'off',
73
73
  'jest/unbound-method': 'error',
74
74
  'jest/no-untyped-mock-factory': 'warn',
@@ -2,6 +2,10 @@ module.exports = [
2
2
  {
3
3
  selector: 'default',
4
4
  format: ['camelCase'],
5
+ filter: {
6
+ regex: '^_+$',
7
+ match: false,
8
+ },
5
9
  },
6
10
  {
7
11
  selector: 'function',
@@ -11,11 +15,19 @@ module.exports = [
11
15
  {
12
16
  selector: 'variable',
13
17
  format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
18
+ filter: {
19
+ regex: '^_+$',
20
+ match: false,
21
+ },
14
22
  },
15
23
  {
16
24
  selector: 'parameter',
17
25
  format: ['camelCase', 'PascalCase'],
18
- leadingUnderscore: 'allowSingleOrDouble',
26
+ leadingUnderscore: 'allow',
27
+ filter: {
28
+ regex: '^_+$',
29
+ match: false,
30
+ },
19
31
  },
20
32
  {
21
33
  selector: 'memberLike',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "9.0.14",
3
+ "version": "9.0.16",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
package/registerOpts.js CHANGED
@@ -6,7 +6,7 @@ const defaultOptions = {
6
6
  cypress: hasDep('cypress'),
7
7
  graphql: hasDep('graphql'),
8
8
  react: hasDep('react') && !hasDep('next'),
9
- storybook: hasDep('storybook'),
9
+ storybook: hasDep('@storybook/react'),
10
10
  test: hasDep('jest') || hasDep('vitest'),
11
11
  typescript: hasDep('typescript'),
12
12
  import: true,
package/storybook.js CHANGED
@@ -2,8 +2,8 @@
2
2
  module.exports = {
3
3
  overrides: [
4
4
  {
5
+ files: ['**/*.stories.+(ts|tsx|js|jsx|mjs|cjs|mdx)', '**/*.story.+(ts|tsx|js|jsx|mjs|cjs|mdx)'],
5
6
  plugins: ['storybook'],
6
- files: ['*.stories.+(ts|tsx|js|jsx|mjs|cjs|mdx)', '*.story.+(ts|tsx|js|jsx|mjs|cjs|mdx)'],
7
7
  rules: {
8
8
  'storybook/await-interactions': 'error',
9
9
  'storybook/context-in-play-function': 'error',
package/typescript.js CHANGED
@@ -89,7 +89,7 @@ module.exports = {
89
89
  '@typescript-eslint/no-unused-vars-experimental': 'off', // Why two rules?
90
90
  '@typescript-eslint/no-unused-vars': [
91
91
  'warn',
92
- { argsIgnorePattern: '^_', varsIgnorePattern: '^[iI]gnore(d)?', args: 'after-used', ignoreRestSiblings: true },
92
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^([iI]gnore(d)?)|(_+)', args: 'after-used', ignoreRestSiblings: true },
93
93
  ],
94
94
  '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: true }],
95
95
  '@typescript-eslint/no-useless-constructor': 'error',