@infra-x/create-eslint-config 0.1.4 → 0.2.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/dist/index.mjs +8 -10
- package/dist/template/.turbo/turbo-build.log +13 -0
- package/dist/template/CHANGELOG.md +7 -0
- package/dist/template/README.md +82 -1
- package/dist/template/eslint.config.mts +1 -1
- package/dist/template/package.json +25 -8
- package/dist/template/src/configs/a11y.ts +2 -2
- package/dist/template/src/configs/better-tailwindcss.ts +2 -2
- package/dist/template/src/configs/boundaries.ts +1 -1
- package/dist/template/src/configs/depend.ts +3 -4
- package/dist/template/src/configs/ignores.ts +7 -7
- package/dist/template/src/configs/imports.ts +8 -3
- package/dist/template/src/configs/javascript.ts +1 -1
- package/dist/template/src/configs/jsdoc.ts +1 -1
- package/dist/template/src/configs/nextjs.ts +2 -2
- package/dist/template/src/configs/package-json.ts +1 -1
- package/dist/template/src/configs/prettier.ts +1 -1
- package/dist/template/src/configs/react.ts +4 -4
- package/dist/template/src/configs/storybook.ts +1 -1
- package/dist/template/src/configs/stylistic.ts +1 -1
- package/dist/template/src/configs/typescript.ts +2 -2
- package/dist/template/src/configs/unicorn.ts +1 -1
- package/dist/template/src/configs/vitest.ts +3 -4
- package/dist/template/src/index.ts +44 -39
- package/dist/template/src/types.ts +34 -23
- package/dist/template/src/utils.ts +17 -17
- package/dist/template/tsconfig.json +1 -1
- package/package.json +14 -17
package/dist/index.mjs
CHANGED
|
@@ -3,24 +3,23 @@ import { access, cp, readdir } from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { confirm, intro, log, outro } from "@clack/prompts";
|
|
6
|
-
|
|
7
6
|
//#region src/index.ts
|
|
8
|
-
async function getConflicts(templateDir
|
|
9
|
-
const entries = await readdir(templateDir
|
|
7
|
+
async function getConflicts(templateDir, destDir) {
|
|
8
|
+
const entries = await readdir(templateDir, {
|
|
10
9
|
recursive: true,
|
|
11
10
|
withFileTypes: true
|
|
12
11
|
});
|
|
13
|
-
const conflicts
|
|
12
|
+
const conflicts = [];
|
|
14
13
|
for (const entry of entries) {
|
|
15
14
|
if (!entry.isFile()) continue;
|
|
16
|
-
const rel = path.join(entry.parentPath, entry.name).slice(templateDir
|
|
17
|
-
const destPath = path.join(destDir
|
|
15
|
+
const rel = path.join(entry.parentPath, entry.name).slice(templateDir.length + 1);
|
|
16
|
+
const destPath = path.join(destDir, rel);
|
|
18
17
|
try {
|
|
19
18
|
await access(destPath);
|
|
20
|
-
conflicts
|
|
19
|
+
conflicts.push(rel);
|
|
21
20
|
} catch {}
|
|
22
21
|
}
|
|
23
|
-
return conflicts
|
|
22
|
+
return conflicts;
|
|
24
23
|
}
|
|
25
24
|
intro("@infra-x/create-eslint-config");
|
|
26
25
|
const templateDir = path.join(fileURLToPath(new URL(".", import.meta.url)), "template");
|
|
@@ -35,6 +34,5 @@ if (conflicts.length > 0) {
|
|
|
35
34
|
}
|
|
36
35
|
await cp(templateDir, destDir, { recursive: true });
|
|
37
36
|
outro("复制完成!");
|
|
38
|
-
|
|
39
37
|
//#endregion
|
|
40
|
-
export {
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
> @infra-x/eslint-config@0.1.5 build /home/runner/work/infra-code/infra-code/packages/eslint-config
|
|
3
|
+
> tsdown
|
|
4
|
+
|
|
5
|
+
[34mℹ[39m tsdown [2mv0.21.3[22m powered by rolldown [2mv1.0.0-rc.9[22m
|
|
6
|
+
[34mℹ[39m config file: [4m/home/runner/work/infra-code/infra-code/packages/eslint-config/tsdown.config.ts[24m
|
|
7
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
9
|
+
[34mℹ[39m Build start
|
|
10
|
+
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m17.21 kB[22m [2m│ gzip: 4.74 kB[22m
|
|
11
|
+
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 6.94 kB[22m [2m│ gzip: 2.19 kB[22m
|
|
12
|
+
[34mℹ[39m 2 files, total: 24.15 kB
|
|
13
|
+
[32m✔[39m Build complete in [32m1654ms[39m
|
package/dist/template/README.md
CHANGED
|
@@ -1,3 +1,84 @@
|
|
|
1
1
|
# @infra-x/eslint-config
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Composable ESLint flat config factory for infra-x projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @infra-x/eslint-config eslint globals
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// eslint.config.mts
|
|
15
|
+
import { composeConfig } from '@infra-x/eslint-config'
|
|
16
|
+
|
|
17
|
+
export default composeConfig({
|
|
18
|
+
typescript: { tsconfigRootDir: import.meta.dirname },
|
|
19
|
+
react: true,
|
|
20
|
+
tailwind: true,
|
|
21
|
+
imports: true,
|
|
22
|
+
prettier: true,
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For multiple config segments (e.g. separate test rules):
|
|
27
|
+
|
|
28
|
+
> 注意:在多`tsconfig`配置时,`tsc -b`,需要添加 `-b`参数。
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// eslint.config.mts
|
|
32
|
+
import { GLOB_TESTS, composeConfig } from '@infra-x/eslint-config'
|
|
33
|
+
import { defineConfig } from 'eslint/config'
|
|
34
|
+
|
|
35
|
+
const appConfig = defineConfig({
|
|
36
|
+
extends: composeConfig({
|
|
37
|
+
typescript: { tsconfigRootDir: import.meta.dirname },
|
|
38
|
+
imports: true,
|
|
39
|
+
react: true,
|
|
40
|
+
nextjs: true,
|
|
41
|
+
}),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const vitestConfig = defineConfig({
|
|
45
|
+
files: GLOB_TESTS,
|
|
46
|
+
extends: composeConfig({
|
|
47
|
+
typescript: { tsconfigRootDir: import.meta.dirname },
|
|
48
|
+
vitest: true,
|
|
49
|
+
unicorn: false,
|
|
50
|
+
stylistic: false,
|
|
51
|
+
depend: false,
|
|
52
|
+
}),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
export default [...appConfig, ...vitestConfig]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Each option accepts `true` (defaults), an options object, or `false` (disable).
|
|
59
|
+
|
|
60
|
+
## Options
|
|
61
|
+
|
|
62
|
+
Default-on: `ignores` · `javascript` · `typescript` · `stylistic` · `unicorn` · `depend` · `configFiles`
|
|
63
|
+
|
|
64
|
+
Opt-in:
|
|
65
|
+
|
|
66
|
+
| Option | Description |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `react` | React + react-hooks rules; set `vite: true` for react-refresh |
|
|
69
|
+
| `nextjs` | Next.js rules |
|
|
70
|
+
| `tailwind` | Tailwind CSS class ordering (`entryPoint` defaults to `src/global.css`) |
|
|
71
|
+
| `imports` | Import ordering and resolution |
|
|
72
|
+
| `prettier` | Prettier formatting (should be last) |
|
|
73
|
+
| `a11y` | Accessibility rules |
|
|
74
|
+
| `jsdoc` | JSDoc rules |
|
|
75
|
+
| `boundaries` | Module boundary enforcement |
|
|
76
|
+
| `packageJson` | `package.json` rules |
|
|
77
|
+
| `vitest` | Vitest testing rules |
|
|
78
|
+
| `storybook` | Storybook rules |
|
|
79
|
+
|
|
80
|
+
All options support an `overrides` field for custom rule overrides, and most accept a `files` glob array.
|
|
81
|
+
|
|
82
|
+
## Roadmap
|
|
83
|
+
|
|
84
|
+
- **oxlint 集成**:计划引入 oxlint 作为快速检查层,通过 `eslint-plugin-oxlint` 禁用 ESLint 中与 oxlint 重复的规则(core/typescript/unicorn),减少 ESLint 规则数量约 50%,显著提升 CI lint 速度
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"typecheck": "tsc --noEmit"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
+
"@infra-x/typescript-config": "0.1.6",
|
|
22
23
|
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
|
|
23
24
|
"@types/node": "^25.0.3",
|
|
24
25
|
"eslint": "^9.39.2",
|
|
@@ -32,23 +33,24 @@
|
|
|
32
33
|
"@eslint-react/eslint-plugin": "^2.13.0",
|
|
33
34
|
"@eslint/compat": "1.4.1",
|
|
34
35
|
"@eslint/core": "0.17.0",
|
|
35
|
-
"@eslint/js": "^
|
|
36
|
+
"@eslint/js": "^10.0.1",
|
|
36
37
|
"@next/eslint-plugin-next": "^16.1.6",
|
|
37
38
|
"@stylistic/eslint-plugin": "^5.9.0",
|
|
38
39
|
"@vitest/eslint-plugin": "^1.6.9",
|
|
40
|
+
"eslint-config-prettier": "^10.1.8",
|
|
39
41
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
40
42
|
"eslint-plugin-better-tailwindcss": "^4.3.1",
|
|
41
43
|
"eslint-plugin-boundaries": "^5.4.0",
|
|
42
|
-
"eslint-plugin-depend": "^1.
|
|
43
|
-
"eslint-plugin-import-x": "4.16.
|
|
44
|
-
"eslint-plugin-jsdoc": "^
|
|
44
|
+
"eslint-plugin-depend": "^1.5.0",
|
|
45
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
46
|
+
"eslint-plugin-jsdoc": "^62.7.1",
|
|
45
47
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
46
|
-
"eslint-plugin-package-json": "^0.
|
|
48
|
+
"eslint-plugin-package-json": "^0.91.0",
|
|
47
49
|
"eslint-plugin-prettier": "^5.5.5",
|
|
48
50
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
49
|
-
"eslint-plugin-react-refresh": "^0.
|
|
50
|
-
"eslint-plugin-storybook": "^10.2.
|
|
51
|
-
"eslint-plugin-unicorn": "^
|
|
51
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
52
|
+
"eslint-plugin-storybook": "^10.2.14",
|
|
53
|
+
"eslint-plugin-unicorn": "^63.0.0",
|
|
52
54
|
"typescript-eslint": "^8.56.1"
|
|
53
55
|
},
|
|
54
56
|
"peerDependencies": {
|
|
@@ -56,6 +58,21 @@
|
|
|
56
58
|
"globals": "16.5.0",
|
|
57
59
|
"jiti": "2.6.1",
|
|
58
60
|
"prettier": "^3.7.4",
|
|
61
|
+
"storybook": ">=10.0.0",
|
|
59
62
|
"typescript": "^5.9.3"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"jiti": {
|
|
66
|
+
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"prettier": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"storybook": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"typescript": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
60
77
|
}
|
|
61
78
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* eslint-plugin-jsx-a11y
|
|
2
|
+
* eslint-plugin-jsx-a11y configuration for detecting accessibility issues in JSX (WCAG standard)
|
|
3
3
|
*/
|
|
4
4
|
import { defineConfig } from 'eslint/config'
|
|
5
5
|
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
|
@@ -10,7 +10,7 @@ import type { A11yOptions } from '../types'
|
|
|
10
10
|
import type { Linter } from 'eslint'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Accessibility rule configuration
|
|
14
14
|
*/
|
|
15
15
|
export function a11y(options: A11yOptions = {}): Linter.Config[] {
|
|
16
16
|
const { files = [GLOB_JSX], overrides = {} } = options
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tailwind CSS ESLint
|
|
2
|
+
* Tailwind CSS ESLint configuration using the official recommended ruleset
|
|
3
3
|
*/
|
|
4
4
|
import { defineConfig } from 'eslint/config'
|
|
5
5
|
import eslintPluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss'
|
|
@@ -10,7 +10,7 @@ import type { TailwindOptions } from '../types'
|
|
|
10
10
|
import type { Linter } from 'eslint'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Tailwind CSS
|
|
13
|
+
* Tailwind CSS rule configuration
|
|
14
14
|
*/
|
|
15
15
|
export function tailwind(options: TailwindOptions = {}): Linter.Config[] {
|
|
16
16
|
const { files = [GLOB_JSX], overrides = {}, entryPoint = 'src/global.css' } = options
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Dependency optimization rule configuration for detecting packages replaceable with native APIs or micro-utilities
|
|
3
3
|
*/
|
|
4
|
-
import { fixupPluginRules } from '@eslint/compat'
|
|
5
4
|
import dependPlugin from 'eslint-plugin-depend'
|
|
6
5
|
|
|
7
6
|
import { GLOB_SRC } from '../utils'
|
|
8
7
|
|
|
9
8
|
import type { DependOptions } from '../types'
|
|
10
|
-
import type {
|
|
9
|
+
import type { Linter } from 'eslint'
|
|
11
10
|
|
|
12
11
|
const DEFAULT_PRESETS: DependOptions['presets'] = ['native', 'microutilities', 'preferred']
|
|
13
12
|
|
|
@@ -19,7 +18,7 @@ export function depend(options: DependOptions = {}): Linter.Config[] {
|
|
|
19
18
|
name: 'depend/rules',
|
|
20
19
|
files: [GLOB_SRC],
|
|
21
20
|
plugins: {
|
|
22
|
-
depend:
|
|
21
|
+
depend: dependPlugin,
|
|
23
22
|
},
|
|
24
23
|
rules: {
|
|
25
24
|
'depend/ban-dependencies': [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ESLint
|
|
2
|
+
* ESLint ignore configuration with built-in default ignore patterns and .gitignore integration
|
|
3
3
|
*/
|
|
4
4
|
import { existsSync } from 'node:fs'
|
|
5
5
|
import path from 'node:path'
|
|
@@ -10,31 +10,31 @@ import type { IgnoresOptions } from '../types'
|
|
|
10
10
|
import type { Linter } from 'eslint'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Default ignored files and directories
|
|
14
14
|
*/
|
|
15
15
|
export const DEFAULT_IGNORES: string[] = [
|
|
16
|
-
//
|
|
16
|
+
// Dependency directories
|
|
17
17
|
'**/node_modules/**',
|
|
18
18
|
'**/.pnp.*',
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// Build artifacts
|
|
21
21
|
'**/dist/**',
|
|
22
22
|
'**/build/**',
|
|
23
23
|
'**/out/**',
|
|
24
24
|
'**/.next/**',
|
|
25
25
|
|
|
26
|
-
//
|
|
26
|
+
// Cache directories
|
|
27
27
|
'**/.cache/**',
|
|
28
28
|
'**/.turbo/**',
|
|
29
29
|
'**/.eslintcache',
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// Version control
|
|
32
32
|
'**/.git/**',
|
|
33
33
|
'**/.svn/**',
|
|
34
34
|
'**/.hg/**',
|
|
35
35
|
'**/public/**',
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// Type declaration files
|
|
38
38
|
'**/*.d.ts',
|
|
39
39
|
]
|
|
40
40
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Import
|
|
2
|
+
* Import rule configuration providing import ordering, circular dependency detection, and TypeScript support
|
|
3
3
|
*/
|
|
4
4
|
import { defineConfig } from 'eslint/config'
|
|
5
5
|
import { importX } from 'eslint-plugin-import-x'
|
|
@@ -10,14 +10,19 @@ import type { ImportsOptions } from '../types'
|
|
|
10
10
|
import type { ESLint, Linter } from 'eslint'
|
|
11
11
|
|
|
12
12
|
export function imports(options: ImportsOptions = {}): Linter.Config[] {
|
|
13
|
-
const { overrides = {}, stylistic = true, typescript = false, noRelativeParentImports = false } = options
|
|
13
|
+
const { overrides = {}, stylistic = true, typescript = false, noRelativeParentImports = false, tsconfigRootDir } = options
|
|
14
14
|
|
|
15
15
|
const files = [GLOB_SRC]
|
|
16
16
|
|
|
17
17
|
const settingsForTypescript = typescript
|
|
18
18
|
? {
|
|
19
19
|
...importX.configs['flat/recommended'].settings,
|
|
20
|
-
'import-x/resolver': {
|
|
20
|
+
'import-x/resolver': {
|
|
21
|
+
typescript: {
|
|
22
|
+
alwaysTryTypes: true,
|
|
23
|
+
...(tsconfigRootDir && { project: tsconfigRootDir }),
|
|
24
|
+
},
|
|
25
|
+
},
|
|
21
26
|
}
|
|
22
27
|
: {}
|
|
23
28
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Next.js ESLint
|
|
2
|
+
* Next.js ESLint configuration using the official plugin for best practices and Core Web Vitals enforcement
|
|
3
3
|
*/
|
|
4
4
|
import nextjsPlugin from '@next/eslint-plugin-next'
|
|
5
5
|
import { defineConfig } from 'eslint/config'
|
|
@@ -11,7 +11,7 @@ const recommended = nextjsPlugin.configs.recommended as unknown as Linter.Config
|
|
|
11
11
|
const coreWebVitals = nextjsPlugin.configs['core-web-vitals'] as unknown as Linter.Config
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Next.js
|
|
14
|
+
* Next.js rule configuration
|
|
15
15
|
*/
|
|
16
16
|
export function nextjs(options: NextjsOptions = {}): Linter.Config[] {
|
|
17
17
|
const { overrides = {} } = options
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* React ESLint
|
|
2
|
+
* React ESLint configuration integrating @eslint-react, react-hooks, and react-refresh plugins
|
|
3
3
|
*/
|
|
4
4
|
import reactPlugin from '@eslint-react/eslint-plugin'
|
|
5
5
|
import { defineConfig } from 'eslint/config'
|
|
@@ -12,10 +12,10 @@ import type { ReactOptions } from '../types'
|
|
|
12
12
|
import type { Linter } from 'eslint'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* React
|
|
15
|
+
* React rule configuration
|
|
16
16
|
*/
|
|
17
17
|
export function react(options: ReactOptions = {}): Linter.Config[] {
|
|
18
|
-
const { files = [GLOB_JSX], overrides = {} } = options
|
|
18
|
+
const { files = [GLOB_JSX], overrides = {}, vite = false } = options
|
|
19
19
|
|
|
20
20
|
return defineConfig({
|
|
21
21
|
name: 'react/rules',
|
|
@@ -23,7 +23,7 @@ export function react(options: ReactOptions = {}): Linter.Config[] {
|
|
|
23
23
|
extends: [
|
|
24
24
|
reactPlugin.configs['recommended-typescript'],
|
|
25
25
|
reactHooksPlugin.configs.flat['recommended-latest'],
|
|
26
|
-
reactRefresh.configs.recommended,
|
|
26
|
+
...(vite ? [reactRefresh.configs.recommended] : []),
|
|
27
27
|
],
|
|
28
28
|
rules: {
|
|
29
29
|
...overrides,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TypeScript ESLint
|
|
2
|
+
* TypeScript ESLint configuration with type-aware linting (recommended rules + stylistic rules)
|
|
3
3
|
*/
|
|
4
4
|
import { defineConfig } from 'eslint/config'
|
|
5
5
|
import { configs, parser, plugin } from 'typescript-eslint'
|
|
@@ -10,7 +10,7 @@ import type { TypeScriptOptions } from '../types'
|
|
|
10
10
|
import type { Linter } from 'eslint'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* TypeScript
|
|
13
|
+
* TypeScript rule configuration
|
|
14
14
|
*/
|
|
15
15
|
export function typescript(options: TypeScriptOptions = {}): Linter.Config[] {
|
|
16
16
|
const { files = [GLOB_TS], tsconfigRootDir, overrides = {} } = options
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vitest
|
|
2
|
+
* Vitest test rule configuration with testing best practices and quality assurance rules
|
|
3
3
|
*/
|
|
4
|
-
import { fixupPluginRules } from '@eslint/compat'
|
|
5
4
|
import vitestPlugin from '@vitest/eslint-plugin'
|
|
6
5
|
import { defineConfig } from 'eslint/config'
|
|
7
6
|
|
|
8
7
|
import { GLOB_TESTS, isInEditorEnv } from '../utils'
|
|
9
8
|
|
|
10
9
|
import type { VitestOptions } from '../types'
|
|
11
|
-
import type {
|
|
10
|
+
import type { Linter } from 'eslint'
|
|
12
11
|
|
|
13
12
|
export function vitest(options: VitestOptions = {}): Linter.Config[] {
|
|
14
13
|
const {
|
|
@@ -22,7 +21,7 @@ export function vitest(options: VitestOptions = {}): Linter.Config[] {
|
|
|
22
21
|
name: 'vitest/rules',
|
|
23
22
|
files,
|
|
24
23
|
plugins: {
|
|
25
|
-
vitest:
|
|
24
|
+
vitest: vitestPlugin,
|
|
26
25
|
},
|
|
27
26
|
rules: {
|
|
28
27
|
...vitestPlugin.configs.recommended.rules,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @workspace/eslint-config
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Composable ESLint configuration factory
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
@@ -60,68 +60,68 @@ import type {
|
|
|
60
60
|
import type { Linter } from 'eslint'
|
|
61
61
|
|
|
62
62
|
// ============================================================================
|
|
63
|
-
//
|
|
63
|
+
// Type definitions
|
|
64
64
|
// ============================================================================
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* composeConfig
|
|
67
|
+
* Options for composeConfig
|
|
68
68
|
*
|
|
69
|
-
*
|
|
70
|
-
* - `true` -
|
|
71
|
-
* -
|
|
72
|
-
* - `false` -
|
|
73
|
-
* -
|
|
69
|
+
* Each config entry accepts:
|
|
70
|
+
* - `true` - enable with default options
|
|
71
|
+
* - `object` - enable with custom options
|
|
72
|
+
* - `false` - explicitly disable (required for configs that are on by default)
|
|
73
|
+
* - omitted - leave disabled (for configs that are off by default)
|
|
74
74
|
*/
|
|
75
75
|
export interface ComposeConfigOptions {
|
|
76
|
-
//
|
|
77
|
-
/**
|
|
76
|
+
// Base configuration (enabled by default)
|
|
77
|
+
/** Ignore patterns configuration @default true */
|
|
78
78
|
ignores?: boolean | IgnoresOptions
|
|
79
|
-
/** JavaScript
|
|
79
|
+
/** JavaScript base configuration @default true */
|
|
80
80
|
javascript?: boolean | JavaScriptOptions
|
|
81
|
-
/** TypeScript
|
|
81
|
+
/** TypeScript configuration @default true */
|
|
82
82
|
typescript?: boolean | TypeScriptOptions
|
|
83
|
-
/**
|
|
83
|
+
/** Code style rules @default true */
|
|
84
84
|
stylistic?: boolean | StylisticOptions
|
|
85
|
-
/** Unicorn
|
|
85
|
+
/** Unicorn best practices @default true */
|
|
86
86
|
unicorn?: boolean | UnicornOptions
|
|
87
|
-
/**
|
|
87
|
+
/** Dependency optimization suggestions @default true */
|
|
88
88
|
depend?: boolean | DependOptions
|
|
89
|
-
/** config
|
|
89
|
+
/** Rules for config files (*.config.ts) without type-checking @default true */
|
|
90
90
|
configFiles?: boolean
|
|
91
91
|
|
|
92
|
-
//
|
|
93
|
-
/** React
|
|
92
|
+
// Framework configuration
|
|
93
|
+
/** React configuration */
|
|
94
94
|
react?: boolean | ReactOptions
|
|
95
|
-
/** Next.js
|
|
95
|
+
/** Next.js configuration */
|
|
96
96
|
nextjs?: boolean | NextjsOptions
|
|
97
|
-
/** Tailwind CSS
|
|
97
|
+
/** Tailwind CSS configuration */
|
|
98
98
|
tailwind?: boolean | TailwindOptions
|
|
99
99
|
|
|
100
|
-
//
|
|
101
|
-
/** Import
|
|
100
|
+
// Tooling configuration
|
|
101
|
+
/** Import ordering and rules */
|
|
102
102
|
imports?: boolean | ImportsOptions
|
|
103
|
-
/** Prettier
|
|
103
|
+
/** Prettier formatting */
|
|
104
104
|
prettier?: boolean | PrettierOptions
|
|
105
105
|
|
|
106
|
-
//
|
|
107
|
-
/**
|
|
106
|
+
// Quality configuration
|
|
107
|
+
/** Accessibility rules */
|
|
108
108
|
a11y?: boolean | A11yOptions
|
|
109
|
-
/** JSDoc
|
|
109
|
+
/** JSDoc documentation rules */
|
|
110
110
|
jsdoc?: boolean | JsdocOptions
|
|
111
|
-
/**
|
|
111
|
+
/** Module boundary rules */
|
|
112
112
|
boundaries?: boolean | BoundariesOptions
|
|
113
|
-
/** package.json
|
|
113
|
+
/** package.json rules */
|
|
114
114
|
packageJson?: boolean | PackageJsonOptions
|
|
115
115
|
|
|
116
|
-
//
|
|
117
|
-
/** Vitest
|
|
116
|
+
// Testing configuration
|
|
117
|
+
/** Vitest testing rules */
|
|
118
118
|
vitest?: boolean | VitestOptions
|
|
119
|
-
/** Storybook
|
|
119
|
+
/** Storybook rules */
|
|
120
120
|
storybook?: boolean | StorybookOptions
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// ============================================================================
|
|
124
|
-
//
|
|
124
|
+
// Core function
|
|
125
125
|
// ============================================================================
|
|
126
126
|
|
|
127
127
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -131,12 +131,12 @@ type ConfigEntry = {
|
|
|
131
131
|
key: keyof ComposeConfigOptions
|
|
132
132
|
fn: ConfigFn
|
|
133
133
|
defaultOn?: boolean
|
|
134
|
-
/**
|
|
134
|
+
/** Values derived from global options to inject; overridden by explicit user config */
|
|
135
135
|
inject?: (options: ComposeConfigOptions) => Record<string, unknown>
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
const CONFIG_REGISTRY: ConfigEntry[] = [
|
|
139
|
-
//
|
|
139
|
+
// Enabled by default
|
|
140
140
|
{ key: 'ignores', fn: ignores, defaultOn: true },
|
|
141
141
|
{ key: 'javascript', fn: javascript, defaultOn: true },
|
|
142
142
|
{
|
|
@@ -147,11 +147,16 @@ const CONFIG_REGISTRY: ConfigEntry[] = [
|
|
|
147
147
|
{ key: 'stylistic', fn: stylistic, defaultOn: true },
|
|
148
148
|
{ key: 'unicorn', fn: unicorn, defaultOn: true },
|
|
149
149
|
{ key: 'depend', fn: depend, defaultOn: true },
|
|
150
|
-
//
|
|
150
|
+
// Opt-in (order is fixed; prettier must come last)
|
|
151
151
|
{
|
|
152
152
|
key: 'imports',
|
|
153
153
|
fn: imports,
|
|
154
|
-
inject: (options) => ({
|
|
154
|
+
inject: (options) => ({
|
|
155
|
+
typescript: options.typescript !== false,
|
|
156
|
+
tsconfigRootDir: typeof options.typescript === 'object'
|
|
157
|
+
? options.typescript.tsconfigRootDir
|
|
158
|
+
: undefined,
|
|
159
|
+
}),
|
|
155
160
|
},
|
|
156
161
|
{ key: 'react', fn: react },
|
|
157
162
|
{ key: 'nextjs', fn: nextjs },
|
|
@@ -165,7 +170,7 @@ const CONFIG_REGISTRY: ConfigEntry[] = [
|
|
|
165
170
|
{ key: 'prettier', fn: prettier },
|
|
166
171
|
]
|
|
167
172
|
|
|
168
|
-
/**
|
|
173
|
+
/** Composes ESLint configs in the correct internal order */
|
|
169
174
|
export function composeConfig(options: ComposeConfigOptions = {}): Linter.Config[] {
|
|
170
175
|
const configs: Linter.Config[] = []
|
|
171
176
|
|
|
@@ -202,7 +207,7 @@ export function composeConfig(options: ComposeConfigOptions = {}): Linter.Config
|
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
// ============================================================================
|
|
205
|
-
//
|
|
210
|
+
// Type exports
|
|
206
211
|
// ============================================================================
|
|
207
212
|
|
|
208
213
|
export type {
|
|
@@ -226,7 +231,7 @@ export type {
|
|
|
226
231
|
} from './types'
|
|
227
232
|
|
|
228
233
|
// ============================================================================
|
|
229
|
-
//
|
|
234
|
+
// Constant exports
|
|
230
235
|
// ============================================================================
|
|
231
236
|
|
|
232
237
|
export { GLOB_SRC, GLOB_JS, GLOB_TS, GLOB_JSX, GLOB_TESTS, GLOB_JSON, GLOB_MARKDOWN } from './utils'
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
import type { RulesConfig } from '@eslint/core'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Rule override options
|
|
5
5
|
*/
|
|
6
6
|
export interface OptionsOverrides {
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Custom rule overrides
|
|
9
9
|
*/
|
|
10
10
|
overrides?: Partial<RulesConfig>
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Stylistic options
|
|
15
15
|
*/
|
|
16
16
|
export interface OptionsStylistic {
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Whether to enable stylistic rules
|
|
19
19
|
* @default true
|
|
20
20
|
*/
|
|
21
21
|
stylistic?: boolean
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* File matching options
|
|
26
26
|
*/
|
|
27
27
|
export interface OptionsFiles {
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Custom file glob patterns
|
|
30
30
|
*/
|
|
31
31
|
files?: string[]
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* TypeScript
|
|
35
|
+
* TypeScript configuration options
|
|
36
36
|
*/
|
|
37
37
|
export interface OptionsTypeScript {
|
|
38
38
|
tsconfigRootDir?: string
|
|
@@ -41,18 +41,18 @@ export interface OptionsTypeScript {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Tailwind CSS
|
|
44
|
+
* Tailwind CSS configuration options
|
|
45
45
|
*/
|
|
46
46
|
export interface OptionsTailwind {
|
|
47
47
|
/**
|
|
48
|
-
* Tailwind CSS
|
|
48
|
+
* Path to the Tailwind CSS entry file
|
|
49
49
|
* @default 'src/global.css'
|
|
50
50
|
*/
|
|
51
51
|
entryPoint?: string
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// ============================================================================
|
|
55
|
-
// Config
|
|
55
|
+
// Config option types
|
|
56
56
|
// ============================================================================
|
|
57
57
|
|
|
58
58
|
export type A11yOptions = OptionsFiles & OptionsOverrides
|
|
@@ -74,48 +74,53 @@ export interface BoundariesOptions extends OptionsFiles, OptionsOverrides {
|
|
|
74
74
|
|
|
75
75
|
export interface DependOptions extends OptionsOverrides {
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* Preset list
|
|
78
78
|
*
|
|
79
|
-
* - `native`:
|
|
80
|
-
* - `microutilities`:
|
|
81
|
-
* - `preferred`:
|
|
79
|
+
* - `native`: Flags packages replaceable with native JavaScript APIs (e.g. `is-nan` → `Number.isNaN()`)
|
|
80
|
+
* - `microutilities`: Flags micro-utility packages implementable in a single line
|
|
81
|
+
* - `preferred`: Recommends lighter-weight, better-maintained alternatives
|
|
82
82
|
*
|
|
83
83
|
* @default ['native', 'microutilities', 'preferred']
|
|
84
84
|
*/
|
|
85
85
|
presets?: ('native' | 'microutilities' | 'preferred')[]
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
88
|
+
* Additional modules to ban
|
|
89
89
|
* @default []
|
|
90
90
|
*/
|
|
91
91
|
modules?: string[]
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
94
|
+
* Modules to allow even if matched by a preset
|
|
95
95
|
* @default []
|
|
96
96
|
*/
|
|
97
97
|
allowed?: string[]
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export interface IgnoresOptions {
|
|
101
|
-
/**
|
|
101
|
+
/** Custom ignore patterns; pass false to disable the built-in defaults */
|
|
102
102
|
ignores?: string[] | false
|
|
103
|
-
/** gitignore
|
|
103
|
+
/** Path to .gitignore file, or a boolean to enable/disable auto-detection */
|
|
104
104
|
gitignore?: string | boolean
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export interface ImportsOptions extends OptionsOverrides, OptionsStylistic {
|
|
108
108
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* @default false
|
|
109
|
+
* Whether to enable TypeScript support
|
|
110
|
+
* Automatically injected as true by composeConfig when the global typescript option is enabled
|
|
111
|
+
* @default false (standalone) / follows global typescript option (via composeConfig)
|
|
112
112
|
*/
|
|
113
113
|
typescript?: boolean
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* Disallow parent-relative imports (paths starting with ../)
|
|
116
116
|
* @default false
|
|
117
117
|
*/
|
|
118
118
|
noRelativeParentImports?: boolean
|
|
119
|
+
/**
|
|
120
|
+
* Root directory for tsconfig.json lookup; restricts resolver scope in monorepo to avoid cross-app漫游
|
|
121
|
+
* Automatically injected by composeConfig from the global typescript.tsconfigRootDir option
|
|
122
|
+
*/
|
|
123
|
+
tsconfigRootDir?: string
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
export type JavaScriptOptions = OptionsFiles & OptionsOverrides
|
|
@@ -137,7 +142,13 @@ export interface PackageJsonOptions extends OptionsOverrides {
|
|
|
137
142
|
|
|
138
143
|
export type PrettierOptions = OptionsOverrides
|
|
139
144
|
|
|
140
|
-
export
|
|
145
|
+
export interface ReactOptions extends OptionsFiles, OptionsOverrides {
|
|
146
|
+
/**
|
|
147
|
+
* Whether to enable react-refresh plugin (for Vite projects).
|
|
148
|
+
* @default false
|
|
149
|
+
*/
|
|
150
|
+
vite?: boolean
|
|
151
|
+
}
|
|
141
152
|
|
|
142
153
|
export type StorybookOptions = OptionsOverrides
|
|
143
154
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Utility functions and constants
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
// ============================================================================
|
|
6
|
-
//
|
|
6
|
+
// Environment detection
|
|
7
7
|
// ============================================================================
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Detects whether running inside Git Hooks or lint-staged
|
|
11
11
|
*/
|
|
12
12
|
function isInGitHooksOrLintStaged(): boolean {
|
|
13
13
|
const envVars = [
|
|
@@ -18,14 +18,14 @@ function isInGitHooksOrLintStaged(): boolean {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Detects whether running in an editor environment
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
* - CI
|
|
23
|
+
* Returns false when:
|
|
24
|
+
* - CI environment
|
|
25
25
|
* - Git Hooks
|
|
26
26
|
* - lint-staged
|
|
27
27
|
*
|
|
28
|
-
*
|
|
28
|
+
* Returns true when:
|
|
29
29
|
* - VSCode
|
|
30
30
|
* - JetBrains IDE
|
|
31
31
|
* - Vim / Neovim
|
|
@@ -46,35 +46,35 @@ export function isInEditorEnv(): boolean {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// ============================================================================
|
|
49
|
-
//
|
|
49
|
+
// File matching patterns (Globs)
|
|
50
50
|
// ============================================================================
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* ESLint
|
|
53
|
+
* ESLint file glob pattern constants
|
|
54
54
|
*
|
|
55
|
-
*
|
|
55
|
+
* Unified glob patterns to ensure consistent file matching across all configurations
|
|
56
56
|
*/
|
|
57
57
|
|
|
58
|
-
/**
|
|
58
|
+
/** All JS/TS source files (full ESM/CJS coverage) */
|
|
59
59
|
export const GLOB_SRC = '**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'
|
|
60
60
|
|
|
61
|
-
/**
|
|
61
|
+
/** JavaScript files only */
|
|
62
62
|
export const GLOB_JS = '**/*.{js,mjs,cjs,jsx}'
|
|
63
63
|
|
|
64
|
-
/**
|
|
64
|
+
/** TypeScript files only */
|
|
65
65
|
export const GLOB_TS = '**/*.{ts,mts,cts,tsx}'
|
|
66
66
|
|
|
67
|
-
/** JSX/TSX
|
|
67
|
+
/** JSX/TSX files (React-related) */
|
|
68
68
|
export const GLOB_JSX = '**/*.{jsx,tsx}'
|
|
69
69
|
|
|
70
|
-
/**
|
|
70
|
+
/** Test files */
|
|
71
71
|
export const GLOB_TESTS: string[] = [
|
|
72
72
|
'**/*.{test,spec}.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',
|
|
73
73
|
'**/__tests__/**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',
|
|
74
74
|
]
|
|
75
75
|
|
|
76
|
-
/** JSON
|
|
76
|
+
/** JSON files */
|
|
77
77
|
export const GLOB_JSON = '**/*.json'
|
|
78
78
|
|
|
79
|
-
/** Markdown
|
|
79
|
+
/** Markdown files */
|
|
80
80
|
export const GLOB_MARKDOWN = '**/*.md'
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"include": ["src", "*.config.ts", "*.config.mts"],
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"types": ["node"],
|
|
6
|
-
"isolatedDeclarations": false //
|
|
6
|
+
"isolatedDeclarations": false // Disabled to reduce maintenance overhead; enabling it would require verbose type annotations across configs
|
|
7
7
|
}
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infra-x/create-eslint-config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"description": "CLI to copy ESLint config source into a monorepo.",
|
|
6
6
|
"author": "infra-x",
|
|
7
7
|
"license": "MIT",
|
|
@@ -20,27 +20,24 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
|
-
"scripts": {
|
|
24
|
-
"build": "tsdown",
|
|
25
|
-
"dev": "tsdown --watch",
|
|
26
|
-
"typecheck": "tsc --noEmit",
|
|
27
|
-
"prepublishOnly": "pnpm run build"
|
|
28
|
-
},
|
|
29
23
|
"dependencies": {
|
|
30
|
-
"@clack/prompts": "^0.
|
|
24
|
+
"@clack/prompts": "^1.0.1"
|
|
31
25
|
},
|
|
32
26
|
"devDependencies": {
|
|
33
|
-
"@
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"typescript": "
|
|
27
|
+
"@types/node": "^25.3.3",
|
|
28
|
+
"eslint": "^10.0.2",
|
|
29
|
+
"tsdown": "^0.21.0",
|
|
30
|
+
"typescript": "^5.9.3",
|
|
31
|
+
"@infra-x/eslint-config": "0.1.5",
|
|
32
|
+
"@infra-x/typescript-config": "0.1.6"
|
|
39
33
|
},
|
|
40
|
-
"main": "./dist/index.mjs",
|
|
41
|
-
"module": "./dist/index.mjs",
|
|
42
34
|
"exports": {
|
|
43
35
|
".": "./dist/index.mjs",
|
|
44
36
|
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsdown",
|
|
40
|
+
"dev": "tsdown --watch",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
45
42
|
}
|
|
46
|
-
}
|
|
43
|
+
}
|