@vijayhardaha/dev-config 2.0.1 → 2.0.3
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 +1 -1
- package/package.json +8 -1
- package/src/eslint/lib/build-config.js +72 -12
- package/src/eslint/next.js +7 -2
- package/src/eslint/react.js +5 -3
- package/src/eslint/typescript.js +1 -0
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ v2 drops FlatCompat and uses native ESLint 10 flat configs throughout.
|
|
|
79
79
|
|
|
80
80
|
1. Install ESLint 10+: `bun add --dev eslint@10`
|
|
81
81
|
2. Replace `eslint-plugin-import` with `eslint-plugin-import-x`
|
|
82
|
-
3. Remove unused deps: `@eslint/
|
|
82
|
+
3. Remove unused deps: `@eslint/eslintrc`, `@eslint/js`, `eslint-config-prettier`, `eslint-import-resolver-typescript`
|
|
83
83
|
|
|
84
84
|
## Quick Start
|
|
85
85
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vijayhardaha/dev-config",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Reusable development configurations for Next.js + TypeScript projects",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint .",
|
|
@@ -36,10 +36,17 @@
|
|
|
36
36
|
},
|
|
37
37
|
"exports": {
|
|
38
38
|
".": "./src/index.js",
|
|
39
|
+
"./package.json": "./package.json",
|
|
39
40
|
"./eslint": "./src/eslint/index.js",
|
|
41
|
+
"./eslint/js": "./src/eslint/index.js",
|
|
42
|
+
"./eslint/base": "./src/eslint/index.js",
|
|
43
|
+
"./eslint/common": "./src/eslint/index.js",
|
|
40
44
|
"./eslint/ts": "./src/eslint/typescript.js",
|
|
45
|
+
"./eslint/typescript": "./src/eslint/typescript.js",
|
|
41
46
|
"./eslint/react": "./src/eslint/react.js",
|
|
47
|
+
"./eslint/reactjs": "./src/eslint/react.js",
|
|
42
48
|
"./eslint/next": "./src/eslint/next.js",
|
|
49
|
+
"./eslint/nextjs": "./src/eslint/next.js",
|
|
43
50
|
"./prettier": "./src/prettier/index.js",
|
|
44
51
|
"./commitlint": "./src/commitlint/index.js",
|
|
45
52
|
"./stylelint": "./src/stylelint/index.js",
|
|
@@ -3,7 +3,6 @@ import { defineConfig } from 'eslint/config';
|
|
|
3
3
|
import importX from 'eslint-plugin-import-x';
|
|
4
4
|
import jsdocPlugin from 'eslint-plugin-jsdoc';
|
|
5
5
|
import prettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
6
|
-
import tsEslint from 'typescript-eslint';
|
|
7
6
|
|
|
8
7
|
import { globalIgnores } from './ignores.js';
|
|
9
8
|
import { commonLanguageOptions } from './language-options.js';
|
|
@@ -11,7 +10,7 @@ import { commonRules } from './rules.js';
|
|
|
11
10
|
import { commonParser } from './setup.js';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
* Filters
|
|
13
|
+
* Filters conditional plugins based on user options.
|
|
15
14
|
*
|
|
16
15
|
* @param {object} conditionalPlugins - Plugin map keyed by option name.
|
|
17
16
|
* @param {object} options - User-provided options.
|
|
@@ -24,7 +23,7 @@ const getEnabledPlugins = (conditionalPlugins, options) =>
|
|
|
24
23
|
.flatMap(([, value]) => (Array.isArray(value) ? value : [value]));
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
|
-
* Flattens a mixed list of config arrays and objects
|
|
26
|
+
* Flattens a mixed list of config arrays and objects.
|
|
28
27
|
*
|
|
29
28
|
* @param {(Array|object)[]} plugins - Mixed list of flat config arrays and objects.
|
|
30
29
|
*
|
|
@@ -45,7 +44,7 @@ const flattenPlugins = (plugins) => {
|
|
|
45
44
|
};
|
|
46
45
|
|
|
47
46
|
/**
|
|
48
|
-
* Wraps plugin rules with fixupPluginRules for
|
|
47
|
+
* Wraps plugin rules with fixupPluginRules for backward compatibility.
|
|
49
48
|
*
|
|
50
49
|
* @param {object[]} flatConfigs - Flat config array.
|
|
51
50
|
*
|
|
@@ -65,9 +64,61 @@ const fixPlugins = (flatConfigs) =>
|
|
|
65
64
|
});
|
|
66
65
|
|
|
67
66
|
/**
|
|
68
|
-
*
|
|
67
|
+
* Removes centrally-registered plugins from individual configs to prevent
|
|
68
|
+
* "Cannot redefine plugin" errors.
|
|
69
69
|
*
|
|
70
|
-
* @param {
|
|
70
|
+
* @param {object[]} flatConfigs - Flat config array.
|
|
71
|
+
* @param {string[]} pluginNames - Plugin names to strip from configs.
|
|
72
|
+
*
|
|
73
|
+
* @returns {object[]} Config array with specified plugins removed.
|
|
74
|
+
*/
|
|
75
|
+
const stripPlugins = (flatConfigs, pluginNames) => {
|
|
76
|
+
if (pluginNames.length === 0) return flatConfigs;
|
|
77
|
+
|
|
78
|
+
const skip = new Set(pluginNames);
|
|
79
|
+
|
|
80
|
+
return flatConfigs.map((config) => {
|
|
81
|
+
if (!config.plugins) return config;
|
|
82
|
+
|
|
83
|
+
const plugins = { ...config.plugins };
|
|
84
|
+
|
|
85
|
+
for (const name of skip) {
|
|
86
|
+
delete plugins[name];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (Object.keys(plugins).length === 0) {
|
|
90
|
+
const { plugins: _, ...rest } = config;
|
|
91
|
+
|
|
92
|
+
return rest;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { ...config, plugins };
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Removes the parser from individual configs when the main config provides one.
|
|
101
|
+
* Prevents parser conflicts (e.g., eslint-config-next/parser vs `@typescript-eslint/parser`).
|
|
102
|
+
*
|
|
103
|
+
* @param {object[]} flatConfigs - Flat config array.
|
|
104
|
+
*
|
|
105
|
+
* @returns {object[]} Config array with parsers removed.
|
|
106
|
+
*/
|
|
107
|
+
const stripParser = (flatConfigs) =>
|
|
108
|
+
flatConfigs.map((config) => {
|
|
109
|
+
if (!config.languageOptions?.parser) return config;
|
|
110
|
+
|
|
111
|
+
const { parser: _, ...languageOptions } = config.languageOptions;
|
|
112
|
+
|
|
113
|
+
return Object.keys(languageOptions).length > 0
|
|
114
|
+
? { ...config, languageOptions }
|
|
115
|
+
: { ...config, languageOptions: undefined };
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Merges user-provided global ignores with common defaults.
|
|
120
|
+
*
|
|
121
|
+
* @param {string[]|undefined} userGlobalIgnores - User-provided ignore patterns.
|
|
71
122
|
*
|
|
72
123
|
* @returns {object} ESLint ignores config object.
|
|
73
124
|
*/
|
|
@@ -75,12 +126,14 @@ const mergeGlobalIgnores = (userGlobalIgnores) =>
|
|
|
75
126
|
Array.isArray(userGlobalIgnores) ? globalIgnores(userGlobalIgnores) : globalIgnores();
|
|
76
127
|
|
|
77
128
|
/**
|
|
78
|
-
* Builds the main ESLint config object with language options, settings,
|
|
129
|
+
* Builds the main ESLint config object with language options, settings, rules,
|
|
130
|
+
* and centrally-registered plugins.
|
|
79
131
|
*
|
|
80
132
|
* @param {object} ctx - Context object with all config parameters.
|
|
81
133
|
* @param {string[]} ctx.filePatterns - File patterns to apply the config to.
|
|
82
134
|
* @param {object} ctx.opts - Resolved user options.
|
|
83
135
|
* @param {boolean} ctx.typescript - Enable TypeScript support.
|
|
136
|
+
* @param {object} ctx.centralPlugins - Plugins to register on the main config.
|
|
84
137
|
* @param {object} ctx.extraLanguageOptions - Additional language options.
|
|
85
138
|
* @param {object} ctx.parserOptions - Parser options.
|
|
86
139
|
* @param {object} ctx.extraSettings - Additional settings.
|
|
@@ -92,6 +145,7 @@ const buildConfigObject = ({
|
|
|
92
145
|
filePatterns,
|
|
93
146
|
opts,
|
|
94
147
|
typescript,
|
|
148
|
+
centralPlugins = {},
|
|
95
149
|
extraLanguageOptions,
|
|
96
150
|
parserOptions,
|
|
97
151
|
extraSettings,
|
|
@@ -102,12 +156,13 @@ const buildConfigObject = ({
|
|
|
102
156
|
return {
|
|
103
157
|
files: [...filePatterns],
|
|
104
158
|
...(ignores && { ignores }),
|
|
105
|
-
|
|
159
|
+
plugins: Object.fromEntries(
|
|
160
|
+
Object.entries(centralPlugins).map(([name, plugin]) => [name, fixupPluginRules(plugin)])
|
|
161
|
+
),
|
|
106
162
|
languageOptions: {
|
|
107
163
|
...commonLanguageOptions,
|
|
108
164
|
...(typescript && commonParser),
|
|
109
165
|
...extraLanguageOptions,
|
|
110
|
-
...languageOptions,
|
|
111
166
|
...(typescript && { parserOptions: { tsconfigRootDir: process.cwd(), ...parserOptions } }),
|
|
112
167
|
},
|
|
113
168
|
settings: {
|
|
@@ -126,12 +181,13 @@ const buildConfigObject = ({
|
|
|
126
181
|
};
|
|
127
182
|
|
|
128
183
|
/**
|
|
129
|
-
* Builds a flat ESLint configuration
|
|
184
|
+
* Builds a flat ESLint configuration.
|
|
130
185
|
*
|
|
131
186
|
* @param {object} config - Configuration options.
|
|
132
187
|
* @param {string[]} config.files - File patterns to apply the config to.
|
|
133
188
|
* @param {(Array|object)[]} config.builtinPlugins - Flat config arrays or objects to always include.
|
|
134
189
|
* @param {object} config.conditionalPlugins - Conditional plugins based on options.
|
|
190
|
+
* @param {object} config.centralPlugins - Plugins registered on the main config object.
|
|
135
191
|
* @param {object} [config.languageOptions] - Additional language options.
|
|
136
192
|
* @param {object} [config.parserOptions] - Parser options.
|
|
137
193
|
* @param {object} [config.settings] - Settings object.
|
|
@@ -145,6 +201,7 @@ export const buildConfig = ({
|
|
|
145
201
|
files: filePatterns,
|
|
146
202
|
builtinPlugins = [],
|
|
147
203
|
conditionalPlugins = {},
|
|
204
|
+
centralPlugins = {},
|
|
148
205
|
languageOptions: extraLanguageOptions = {},
|
|
149
206
|
parserOptions = {},
|
|
150
207
|
settings: extraSettings = {},
|
|
@@ -166,18 +223,21 @@ export const buildConfig = ({
|
|
|
166
223
|
].filter(Boolean);
|
|
167
224
|
|
|
168
225
|
const flatConfigs = flattenPlugins(mergedPlugins);
|
|
169
|
-
const
|
|
226
|
+
const wrappedConfigs = fixPlugins(flatConfigs);
|
|
227
|
+
const strippedConfigs = stripPlugins(wrappedConfigs, Object.keys(centralPlugins));
|
|
228
|
+
const parsedConfigs = typescript ? stripParser(strippedConfigs) : strippedConfigs;
|
|
170
229
|
const mergedGlobalIgnores = mergeGlobalIgnores(opts.globalIgnores);
|
|
171
230
|
|
|
172
231
|
const configObject = buildConfigObject({
|
|
173
232
|
filePatterns,
|
|
174
233
|
opts,
|
|
175
234
|
typescript,
|
|
235
|
+
centralPlugins,
|
|
176
236
|
extraLanguageOptions,
|
|
177
237
|
parserOptions,
|
|
178
238
|
extraSettings,
|
|
179
239
|
extraRules,
|
|
180
240
|
});
|
|
181
241
|
|
|
182
|
-
return defineConfig([...mergedGlobalIgnores, ...
|
|
242
|
+
return defineConfig([...mergedGlobalIgnores, ...parsedConfigs, configObject]);
|
|
183
243
|
};
|
package/src/eslint/next.js
CHANGED
|
@@ -10,14 +10,18 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import nextCoreWebVitals from 'eslint-config-next/core-web-vitals';
|
|
13
|
+
import reactPlugin from 'eslint-plugin-react';
|
|
14
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
15
|
+
import tsEslint from 'typescript-eslint';
|
|
13
16
|
|
|
14
17
|
import { buildConfig, files } from './lib/index.js';
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Removes the next/typescript item from the core-web-vitals config array.
|
|
18
21
|
* The \@typescript-eslint plugin is registered on the main config object
|
|
19
|
-
*
|
|
20
|
-
*
|
|
22
|
+
* via centralPlugins, which avoids plugin redefinition errors. The
|
|
23
|
+
* next/typescript config is also removed to prevent parser conflicts with
|
|
24
|
+
* the centrally-managed TypeScript setup.
|
|
21
25
|
*
|
|
22
26
|
* @param {import('eslint').Linter.Config[]} configs - Config array to process.
|
|
23
27
|
*
|
|
@@ -52,6 +56,7 @@ export const createConfig = (options = {}) => {
|
|
|
52
56
|
return buildConfig({
|
|
53
57
|
files: files.withTs,
|
|
54
58
|
builtinPlugins: [...prepareNextConfig(nextCoreWebVitals)],
|
|
59
|
+
centralPlugins: { react: reactPlugin, 'react-hooks': reactHooks, '@typescript-eslint': tsEslint.plugin },
|
|
55
60
|
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
56
61
|
settings: { react: { version: 'detect' } },
|
|
57
62
|
rules: {
|
package/src/eslint/react.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
13
|
+
import reactPlugin from 'eslint-plugin-react';
|
|
13
14
|
import reactRecommended from 'eslint-plugin-react/configs/recommended.js';
|
|
14
15
|
import reactHooks from 'eslint-plugin-react-hooks';
|
|
15
16
|
import tsEslint from 'typescript-eslint';
|
|
@@ -42,11 +43,12 @@ export const createConfig = (options = {}) => {
|
|
|
42
43
|
return buildConfig({
|
|
43
44
|
files: files.withTs,
|
|
44
45
|
builtinPlugins: [
|
|
45
|
-
{ ...reactRecommended, files:
|
|
46
|
-
{ ...reactHooks.configs.flat.recommended, files:
|
|
46
|
+
{ ...reactRecommended, files: files.withTs },
|
|
47
|
+
{ ...reactHooks.configs.flat.recommended, files: files.withTs },
|
|
47
48
|
...tsEslint.configs.recommended,
|
|
48
49
|
],
|
|
49
|
-
|
|
50
|
+
centralPlugins: { react: reactPlugin, 'react-hooks': reactHooks, '@typescript-eslint': tsEslint.plugin },
|
|
51
|
+
conditionalPlugins: { a11y: { ...jsxA11y.flatConfigs.recommended, files: files.withTs } },
|
|
50
52
|
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
51
53
|
settings: { react: { version: 'detect' } },
|
|
52
54
|
rules: { 'react/react-in-jsx-scope': 'off', 'react/no-unknown-property': ['error', { ignore: ['jsx', 'global'] }] },
|
package/src/eslint/typescript.js
CHANGED
|
@@ -37,6 +37,7 @@ export const createConfig = (options = {}) => {
|
|
|
37
37
|
return buildConfig({
|
|
38
38
|
files: files.withTs,
|
|
39
39
|
builtinPlugins: [...tsEslint.configs.recommended],
|
|
40
|
+
centralPlugins: { '@typescript-eslint': tsEslint.plugin },
|
|
40
41
|
typescript: true,
|
|
41
42
|
options: { ...options, prettier, importOrder, jsdoc },
|
|
42
43
|
});
|