@vijayhardaha/dev-config 2.0.2 → 2.0.4
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 +20 -5
- package/package.json +54 -12
- package/src/eslint/lib/build-config.js +38 -4
- package/src/eslint/lib/build-config.test.js +28 -0
- package/src/eslint/next.js +7 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Reusable development configuration package for Next.js + TypeScript projects.
|
|
8
8
|
|
|
9
|
-
> **v2.0.
|
|
9
|
+
> **v2.0.4** — Requires ESLint >=10. Native flat config only. No FlatCompat.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -21,17 +21,25 @@ Reusable development configuration package for Next.js + TypeScript projects.
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
bun
|
|
24
|
+
bun add --dev @vijayhardaha/dev-config
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
### Install Required Packages
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
bun add --dev eslint @eslint/compat prettier @prettier/plugin-xml eslint-plugin-prettier globals eslint-plugin-jsdoc eslint-plugin-import-x
|
|
30
|
+
bun add --dev eslint @eslint/compat eslint-config-prettier prettier @prettier/plugin-xml eslint-plugin-prettier globals eslint-plugin-jsdoc eslint-plugin-import-x @typescript-eslint/eslint-plugin @typescript-eslint/parser typescript typescript-eslint husky
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
### Install Optional Packages
|
|
34
34
|
|
|
35
|
+
Only install what you need based on your project setup.
|
|
36
|
+
|
|
37
|
+
#### TypeScript Import Resolution
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
bun add --dev eslint-import-resolver-typescript
|
|
41
|
+
```
|
|
42
|
+
|
|
35
43
|
#### Stylelint
|
|
36
44
|
|
|
37
45
|
```bash
|
|
@@ -53,7 +61,7 @@ bun add --dev @next/eslint-plugin-next eslint-config-next
|
|
|
53
61
|
#### Commitlint
|
|
54
62
|
|
|
55
63
|
```bash
|
|
56
|
-
bun add --dev
|
|
64
|
+
bun add --dev @commitlint/cli @commitlint/config-conventional @commitlint/types
|
|
57
65
|
```
|
|
58
66
|
|
|
59
67
|
#### Next Sitemap
|
|
@@ -79,7 +87,14 @@ v2 drops FlatCompat and uses native ESLint 10 flat configs throughout.
|
|
|
79
87
|
|
|
80
88
|
1. Install ESLint 10+: `bun add --dev eslint@10`
|
|
81
89
|
2. Replace `eslint-plugin-import` with `eslint-plugin-import-x`
|
|
82
|
-
3. Remove unused deps: `@eslint/eslintrc`, `@eslint/js
|
|
90
|
+
3. Remove unused deps: `@eslint/eslintrc`, `@eslint/js`
|
|
91
|
+
|
|
92
|
+
### What's new in v2.0.4
|
|
93
|
+
|
|
94
|
+
- **`eslint-config-prettier` restored** — added back to peer deps (required by `eslint-plugin-prettier/recommended`)
|
|
95
|
+
- **`eslint-import-resolver-typescript` restored** — added back as optional peer for TypeScript import resolution
|
|
96
|
+
- **All packages declared as peer deps** — every config module's dependencies are declared with proper `peerDependenciesMeta`
|
|
97
|
+
- **Flat config resolver fix** — switched from string-based `import-x/resolver` to `import-x/resolver-next` with `createTypeScriptImportResolver` for ESLint 10 compatibility
|
|
83
98
|
|
|
84
99
|
## Quick Start
|
|
85
100
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vijayhardaha/dev-config",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Reusable development configurations for Next.js + TypeScript projects",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint .",
|
|
@@ -68,32 +68,55 @@
|
|
|
68
68
|
"@commitlint/cli": "^21.0.2",
|
|
69
69
|
"@commitlint/config-conventional": "^21.0.2",
|
|
70
70
|
"@commitlint/types": "^21.0.1",
|
|
71
|
-
"@
|
|
72
|
-
"eslint-
|
|
71
|
+
"@typescript-eslint/parser": "^8.60.1",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "^8.60.1",
|
|
73
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
74
|
+
"eslint": "^10.4.1",
|
|
75
|
+
"eslint-config-next": "^16.2.7",
|
|
76
|
+
"eslint-config-prettier": "^10.1.8",
|
|
77
|
+
"eslint-plugin-import-x": "^4.16.2",
|
|
78
|
+
"eslint-plugin-jsdoc": "^63.0.1",
|
|
73
79
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
80
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
74
81
|
"eslint-plugin-react": "^7.37.5",
|
|
75
82
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
+
"globals": "^17.6.0",
|
|
84
|
+
"husky": "^9.1.7",
|
|
85
|
+
"prettier": "^3.8.3",
|
|
86
|
+
"@prettier/plugin-xml": "^3.4.2",
|
|
87
|
+
"release-it": "^20.2.0",
|
|
88
|
+
"typescript": "^6.0.3",
|
|
89
|
+
"typescript-eslint": "^8.60.1",
|
|
90
|
+
"vitest": "^4.1.8"
|
|
83
91
|
},
|
|
84
92
|
"peerDependencies": {
|
|
93
|
+
"@commitlint/cli": ">=21",
|
|
94
|
+
"@commitlint/config-conventional": ">=21",
|
|
95
|
+
"@commitlint/types": ">=21",
|
|
85
96
|
"@eslint/compat": ">=2",
|
|
97
|
+
"@next/eslint-plugin-next": ">=16",
|
|
86
98
|
"@prettier/plugin-xml": ">=3",
|
|
87
99
|
"@typescript-eslint/eslint-plugin": ">=8",
|
|
88
100
|
"@typescript-eslint/parser": ">=8",
|
|
89
101
|
"eslint": ">=10",
|
|
102
|
+
"eslint-config-next": ">=16",
|
|
103
|
+
"eslint-config-prettier": ">=10",
|
|
104
|
+
"eslint-import-resolver-typescript": ">=4",
|
|
90
105
|
"eslint-plugin-import-x": ">=4",
|
|
91
106
|
"eslint-plugin-jsdoc": ">=62",
|
|
107
|
+
"eslint-plugin-jsx-a11y": ">=6",
|
|
92
108
|
"eslint-plugin-prettier": ">=5",
|
|
109
|
+
"eslint-plugin-react": ">=7",
|
|
110
|
+
"eslint-plugin-react-hooks": ">=5",
|
|
93
111
|
"globals": ">=17",
|
|
94
112
|
"husky": ">=9",
|
|
95
|
-
"
|
|
96
|
-
"
|
|
113
|
+
"next-sitemap": ">=4",
|
|
114
|
+
"prettier": ">=3",
|
|
115
|
+
"stylelint": ">=17",
|
|
116
|
+
"stylelint-config-property-sort-order-smacss": ">=11",
|
|
117
|
+
"stylelint-config-standard-scss": ">=17",
|
|
118
|
+
"stylelint-order": ">=8",
|
|
119
|
+
"typescript": ">=5",
|
|
97
120
|
"typescript-eslint": ">=8"
|
|
98
121
|
},
|
|
99
122
|
"peerDependenciesMeta": {
|
|
@@ -109,9 +132,18 @@
|
|
|
109
132
|
"@next/eslint-plugin-next": {
|
|
110
133
|
"optional": true
|
|
111
134
|
},
|
|
135
|
+
"@typescript-eslint/eslint-plugin": {
|
|
136
|
+
"optional": true
|
|
137
|
+
},
|
|
138
|
+
"@typescript-eslint/parser": {
|
|
139
|
+
"optional": true
|
|
140
|
+
},
|
|
112
141
|
"eslint-config-next": {
|
|
113
142
|
"optional": true
|
|
114
143
|
},
|
|
144
|
+
"eslint-import-resolver-typescript": {
|
|
145
|
+
"optional": true
|
|
146
|
+
},
|
|
115
147
|
"eslint-plugin-jsx-a11y": {
|
|
116
148
|
"optional": true
|
|
117
149
|
},
|
|
@@ -121,6 +153,9 @@
|
|
|
121
153
|
"eslint-plugin-react-hooks": {
|
|
122
154
|
"optional": true
|
|
123
155
|
},
|
|
156
|
+
"husky": {
|
|
157
|
+
"optional": true
|
|
158
|
+
},
|
|
124
159
|
"next-sitemap": {
|
|
125
160
|
"optional": true
|
|
126
161
|
},
|
|
@@ -135,12 +170,19 @@
|
|
|
135
170
|
},
|
|
136
171
|
"stylelint-order": {
|
|
137
172
|
"optional": true
|
|
173
|
+
},
|
|
174
|
+
"typescript": {
|
|
175
|
+
"optional": true
|
|
176
|
+
},
|
|
177
|
+
"typescript-eslint": {
|
|
178
|
+
"optional": true
|
|
138
179
|
}
|
|
139
180
|
},
|
|
140
181
|
"overrides": {
|
|
141
182
|
"undici": "^7.0.0"
|
|
142
183
|
},
|
|
143
184
|
"trustedDependencies": [
|
|
185
|
+
"sharp",
|
|
144
186
|
"unrs-resolver"
|
|
145
187
|
]
|
|
146
188
|
}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { fixupPluginRules } from '@eslint/compat';
|
|
2
2
|
import { defineConfig } from 'eslint/config';
|
|
3
|
-
import
|
|
3
|
+
import { createNodeResolver, flatConfigs as importXFlatConfigs } from 'eslint-plugin-import-x';
|
|
4
4
|
import jsdocPlugin from 'eslint-plugin-jsdoc';
|
|
5
5
|
import prettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
6
6
|
|
|
7
7
|
import { globalIgnores } from './ignores.js';
|
|
8
8
|
import { commonLanguageOptions } from './language-options.js';
|
|
9
9
|
import { commonRules } from './rules.js';
|
|
10
|
+
import { commonParser } from './setup.js';
|
|
11
|
+
|
|
12
|
+
let createTypeScriptImportResolver;
|
|
13
|
+
try {
|
|
14
|
+
createTypeScriptImportResolver = (await import('eslint-import-resolver-typescript')).createTypeScriptImportResolver;
|
|
15
|
+
} catch {
|
|
16
|
+
createTypeScriptImportResolver = null;
|
|
17
|
+
}
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
20
|
* Filters conditional plugins based on user options.
|
|
@@ -95,6 +103,25 @@ const stripPlugins = (flatConfigs, pluginNames) => {
|
|
|
95
103
|
});
|
|
96
104
|
};
|
|
97
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Removes the parser from individual configs when the main config provides one.
|
|
108
|
+
* Prevents parser conflicts (e.g., eslint-config-next/parser vs `@typescript-eslint/parser`).
|
|
109
|
+
*
|
|
110
|
+
* @param {object[]} flatConfigs - Flat config array.
|
|
111
|
+
*
|
|
112
|
+
* @returns {object[]} Config array with parsers removed.
|
|
113
|
+
*/
|
|
114
|
+
const stripParser = (flatConfigs) =>
|
|
115
|
+
flatConfigs.map((config) => {
|
|
116
|
+
if (!config.languageOptions?.parser) return config;
|
|
117
|
+
|
|
118
|
+
const { parser: _, ...languageOptions } = config.languageOptions;
|
|
119
|
+
|
|
120
|
+
return Object.keys(languageOptions).length > 0
|
|
121
|
+
? { ...config, languageOptions }
|
|
122
|
+
: { ...config, languageOptions: undefined };
|
|
123
|
+
});
|
|
124
|
+
|
|
98
125
|
/**
|
|
99
126
|
* Merges user-provided global ignores with common defaults.
|
|
100
127
|
*
|
|
@@ -141,11 +168,17 @@ const buildConfigObject = ({
|
|
|
141
168
|
),
|
|
142
169
|
languageOptions: {
|
|
143
170
|
...commonLanguageOptions,
|
|
171
|
+
...(typescript && commonParser),
|
|
144
172
|
...extraLanguageOptions,
|
|
145
173
|
...(typescript && { parserOptions: { tsconfigRootDir: process.cwd(), ...parserOptions } }),
|
|
146
174
|
},
|
|
147
175
|
settings: {
|
|
148
|
-
...(opts.importOrder && {
|
|
176
|
+
...(opts.importOrder && {
|
|
177
|
+
'import-x/resolver-next': [
|
|
178
|
+
createNodeResolver(),
|
|
179
|
+
...(createTypeScriptImportResolver ? [createTypeScriptImportResolver()] : []),
|
|
180
|
+
],
|
|
181
|
+
}),
|
|
149
182
|
...(opts.jsdoc && { jsdoc: { mode: 'typescript' } }),
|
|
150
183
|
...extraSettings,
|
|
151
184
|
...settings,
|
|
@@ -194,7 +227,7 @@ export const buildConfig = ({
|
|
|
194
227
|
|
|
195
228
|
const mergedPlugins = [
|
|
196
229
|
...builtinPlugins,
|
|
197
|
-
opts.importOrder &&
|
|
230
|
+
opts.importOrder && importXFlatConfigs.recommended,
|
|
198
231
|
opts.jsdoc && jsdocPlugin.configs['flat/recommended'],
|
|
199
232
|
opts.prettier && prettierRecommended,
|
|
200
233
|
...conditionalPluginList,
|
|
@@ -204,6 +237,7 @@ export const buildConfig = ({
|
|
|
204
237
|
const flatConfigs = flattenPlugins(mergedPlugins);
|
|
205
238
|
const wrappedConfigs = fixPlugins(flatConfigs);
|
|
206
239
|
const strippedConfigs = stripPlugins(wrappedConfigs, Object.keys(centralPlugins));
|
|
240
|
+
const parsedConfigs = typescript ? stripParser(strippedConfigs) : strippedConfigs;
|
|
207
241
|
const mergedGlobalIgnores = mergeGlobalIgnores(opts.globalIgnores);
|
|
208
242
|
|
|
209
243
|
const configObject = buildConfigObject({
|
|
@@ -217,5 +251,5 @@ export const buildConfig = ({
|
|
|
217
251
|
extraRules,
|
|
218
252
|
});
|
|
219
253
|
|
|
220
|
-
return defineConfig([...mergedGlobalIgnores, ...
|
|
254
|
+
return defineConfig([...mergedGlobalIgnores, ...parsedConfigs, configObject]);
|
|
221
255
|
};
|
|
@@ -49,4 +49,32 @@ describe('eslint/lib/build-config.js', () => {
|
|
|
49
49
|
expect(configNames).toContain('test-flat-config');
|
|
50
50
|
expect(configNames).toContain('test-flat-object');
|
|
51
51
|
});
|
|
52
|
+
|
|
53
|
+
// Test that buildConfig sets import-x/resolver-next when importOrder is enabled.
|
|
54
|
+
it('should configure import-x/resolver-next with node resolver when importOrder is enabled', async () => {
|
|
55
|
+
const module = await import('./build-config.js');
|
|
56
|
+
const { files } = await import('./files.js');
|
|
57
|
+
|
|
58
|
+
const result = module.buildConfig({ files: files.withoutTs, options: { importOrder: true } });
|
|
59
|
+
|
|
60
|
+
// The last config object in the array should have the resolver settings
|
|
61
|
+
const configObject = result[result.length - 1];
|
|
62
|
+
expect(configObject.settings).toBeDefined();
|
|
63
|
+
expect(configObject.settings['import-x/resolver-next']).toBeDefined();
|
|
64
|
+
expect(Array.isArray(configObject.settings['import-x/resolver-next'])).toBe(true);
|
|
65
|
+
// Should at least have the node resolver
|
|
66
|
+
expect(configObject.settings['import-x/resolver-next'].length).toBeGreaterThanOrEqual(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Test that buildConfig omits import-x/resolver-next when importOrder is disabled.
|
|
70
|
+
it('should omit import-x/resolver-next when importOrder is disabled', async () => {
|
|
71
|
+
const module = await import('./build-config.js');
|
|
72
|
+
const { files } = await import('./files.js');
|
|
73
|
+
|
|
74
|
+
const result = module.buildConfig({ files: files.withoutTs, options: { importOrder: false } });
|
|
75
|
+
|
|
76
|
+
const configObject = result[result.length - 1];
|
|
77
|
+
expect(configObject.settings).toBeDefined();
|
|
78
|
+
expect(configObject.settings['import-x/resolver-next']).toBeUndefined();
|
|
79
|
+
});
|
|
52
80
|
});
|
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: {
|