@vijayhardaha/dev-config 2.0.1 → 2.0.2

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
@@ -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/compat`, `@eslint/eslintrc`, `@eslint/js`, `eslint-config-prettier`, `eslint-import-resolver-typescript`
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.1",
3
+ "version": "2.0.2",
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,15 +3,13 @@ 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';
10
9
  import { commonRules } from './rules.js';
11
- import { commonParser } from './setup.js';
12
10
 
13
11
  /**
14
- * Filters and flattens conditional plugins based on user options.
12
+ * Filters conditional plugins based on user options.
15
13
  *
16
14
  * @param {object} conditionalPlugins - Plugin map keyed by option name.
17
15
  * @param {object} options - User-provided options.
@@ -24,7 +22,7 @@ const getEnabledPlugins = (conditionalPlugins, options) =>
24
22
  .flatMap(([, value]) => (Array.isArray(value) ? value : [value]));
25
23
 
26
24
  /**
27
- * Flattens a mixed list of config arrays and objects into a flat config array.
25
+ * Flattens a mixed list of config arrays and objects.
28
26
  *
29
27
  * @param {(Array|object)[]} plugins - Mixed list of flat config arrays and objects.
30
28
  *
@@ -45,7 +43,7 @@ const flattenPlugins = (plugins) => {
45
43
  };
46
44
 
47
45
  /**
48
- * Wraps plugin rules with fixupPluginRules for ESLint 10 backward compatibility.
46
+ * Wraps plugin rules with fixupPluginRules for backward compatibility.
49
47
  *
50
48
  * @param {object[]} flatConfigs - Flat config array.
51
49
  *
@@ -65,9 +63,42 @@ const fixPlugins = (flatConfigs) =>
65
63
  });
66
64
 
67
65
  /**
68
- * Merges user-provided global ignores with the common defaults.
66
+ * Removes centrally-registered plugins from individual configs to prevent
67
+ * "Cannot redefine plugin" errors.
69
68
  *
70
- * @param {string[]|undefined} userGlobalIgnores - User-provided global ignore patterns.
69
+ * @param {object[]} flatConfigs - Flat config array.
70
+ * @param {string[]} pluginNames - Plugin names to strip from configs.
71
+ *
72
+ * @returns {object[]} Config array with specified plugins removed.
73
+ */
74
+ const stripPlugins = (flatConfigs, pluginNames) => {
75
+ if (pluginNames.length === 0) return flatConfigs;
76
+
77
+ const skip = new Set(pluginNames);
78
+
79
+ return flatConfigs.map((config) => {
80
+ if (!config.plugins) return config;
81
+
82
+ const plugins = { ...config.plugins };
83
+
84
+ for (const name of skip) {
85
+ delete plugins[name];
86
+ }
87
+
88
+ if (Object.keys(plugins).length === 0) {
89
+ const { plugins: _, ...rest } = config;
90
+
91
+ return rest;
92
+ }
93
+
94
+ return { ...config, plugins };
95
+ });
96
+ };
97
+
98
+ /**
99
+ * Merges user-provided global ignores with common defaults.
100
+ *
101
+ * @param {string[]|undefined} userGlobalIgnores - User-provided ignore patterns.
71
102
  *
72
103
  * @returns {object} ESLint ignores config object.
73
104
  */
@@ -75,12 +106,14 @@ const mergeGlobalIgnores = (userGlobalIgnores) =>
75
106
  Array.isArray(userGlobalIgnores) ? globalIgnores(userGlobalIgnores) : globalIgnores();
76
107
 
77
108
  /**
78
- * Builds the main ESLint config object with language options, settings, and rules.
109
+ * Builds the main ESLint config object with language options, settings, rules,
110
+ * and centrally-registered plugins.
79
111
  *
80
112
  * @param {object} ctx - Context object with all config parameters.
81
113
  * @param {string[]} ctx.filePatterns - File patterns to apply the config to.
82
114
  * @param {object} ctx.opts - Resolved user options.
83
115
  * @param {boolean} ctx.typescript - Enable TypeScript support.
116
+ * @param {object} ctx.centralPlugins - Plugins to register on the main config.
84
117
  * @param {object} ctx.extraLanguageOptions - Additional language options.
85
118
  * @param {object} ctx.parserOptions - Parser options.
86
119
  * @param {object} ctx.extraSettings - Additional settings.
@@ -92,6 +125,7 @@ const buildConfigObject = ({
92
125
  filePatterns,
93
126
  opts,
94
127
  typescript,
128
+ centralPlugins = {},
95
129
  extraLanguageOptions,
96
130
  parserOptions,
97
131
  extraSettings,
@@ -102,12 +136,12 @@ const buildConfigObject = ({
102
136
  return {
103
137
  files: [...filePatterns],
104
138
  ...(ignores && { ignores }),
105
- ...(typescript && { plugins: { '@typescript-eslint': tsEslint.plugin } }),
139
+ plugins: Object.fromEntries(
140
+ Object.entries(centralPlugins).map(([name, plugin]) => [name, fixupPluginRules(plugin)])
141
+ ),
106
142
  languageOptions: {
107
143
  ...commonLanguageOptions,
108
- ...(typescript && commonParser),
109
144
  ...extraLanguageOptions,
110
- ...languageOptions,
111
145
  ...(typescript && { parserOptions: { tsconfigRootDir: process.cwd(), ...parserOptions } }),
112
146
  },
113
147
  settings: {
@@ -126,12 +160,13 @@ const buildConfigObject = ({
126
160
  };
127
161
 
128
162
  /**
129
- * Builds a flat ESLint configuration with support for various options.
163
+ * Builds a flat ESLint configuration.
130
164
  *
131
165
  * @param {object} config - Configuration options.
132
166
  * @param {string[]} config.files - File patterns to apply the config to.
133
167
  * @param {(Array|object)[]} config.builtinPlugins - Flat config arrays or objects to always include.
134
168
  * @param {object} config.conditionalPlugins - Conditional plugins based on options.
169
+ * @param {object} config.centralPlugins - Plugins registered on the main config object.
135
170
  * @param {object} [config.languageOptions] - Additional language options.
136
171
  * @param {object} [config.parserOptions] - Parser options.
137
172
  * @param {object} [config.settings] - Settings object.
@@ -145,6 +180,7 @@ export const buildConfig = ({
145
180
  files: filePatterns,
146
181
  builtinPlugins = [],
147
182
  conditionalPlugins = {},
183
+ centralPlugins = {},
148
184
  languageOptions: extraLanguageOptions = {},
149
185
  parserOptions = {},
150
186
  settings: extraSettings = {},
@@ -166,18 +202,20 @@ export const buildConfig = ({
166
202
  ].filter(Boolean);
167
203
 
168
204
  const flatConfigs = flattenPlugins(mergedPlugins);
169
- const fixedConfigs = fixPlugins(flatConfigs);
205
+ const wrappedConfigs = fixPlugins(flatConfigs);
206
+ const strippedConfigs = stripPlugins(wrappedConfigs, Object.keys(centralPlugins));
170
207
  const mergedGlobalIgnores = mergeGlobalIgnores(opts.globalIgnores);
171
208
 
172
209
  const configObject = buildConfigObject({
173
210
  filePatterns,
174
211
  opts,
175
212
  typescript,
213
+ centralPlugins,
176
214
  extraLanguageOptions,
177
215
  parserOptions,
178
216
  extraSettings,
179
217
  extraRules,
180
218
  });
181
219
 
182
- return defineConfig([...mergedGlobalIgnores, ...fixedConfigs, configObject]);
220
+ return defineConfig([...mergedGlobalIgnores, ...strippedConfigs, configObject]);
183
221
  };
@@ -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: ['**/*.{jsx,tsx}'] },
46
- { ...reactHooks.configs.flat.recommended, files: ['**/*.{jsx,tsx}'] },
46
+ { ...reactRecommended, files: files.withTs },
47
+ { ...reactHooks.configs.flat.recommended, files: files.withTs },
47
48
  ...tsEslint.configs.recommended,
48
49
  ],
49
- conditionalPlugins: { a11y: { ...jsxA11y.flatConfigs.recommended, files: ['**/*.{jsx,tsx}'] } },
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'] }] },
@@ -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
  });