@st1ggy/linter-config 6.3.2 → 7.2.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 +23 -10
- package/data/linter-config-inventory.json +4376 -493
- package/docs/RULE_MAPPING.md +2 -0
- package/index.d.ts +18 -0
- package/package.json +79 -28
- package/scripts/README.md +14 -11
- package/scripts/init-astro.sh +5 -0
- package/scripts/inventory.mjs +9 -2
- package/scripts/linter-init-core.mjs +93 -32
- package/scripts/linter-init.mjs +118 -93
- package/src/eslint/configs/astro-stack.js +3 -0
- package/src/eslint/configs/config.common.js +1 -1
- package/src/eslint/configs/config.gitignore.js +3 -4
- package/src/eslint/configs/config.unicorn.js +1 -1
- package/src/eslint/configs/constants.js +4 -2
- package/src/eslint/eslint.config.astro.js +4 -0
- package/src/examples/example.astro +7 -0
- package/src/examples/example.ts +1 -1
- package/src/index.js +2 -0
- package/src/prettier/prettier-astro.config.js +7 -0
package/docs/RULE_MAPPING.md
CHANGED
|
@@ -21,6 +21,7 @@ node scripts/inventory.mjs
|
|
|
21
21
|
| React | `config.react.js` | React/JSX + hooks. |
|
|
22
22
|
| Next.js | `config.next.js` | `@next/eslint-plugin-next`. |
|
|
23
23
|
| Svelte | `svelte-stack.js` | `eslint-plugin-svelte` flat recommended + TS parser options. |
|
|
24
|
+
| Astro | `astro-stack.js` | `eslint-plugin-astro` recommended. |
|
|
24
25
|
|
|
25
26
|
Inventory rule counts (sample files in this repository):
|
|
26
27
|
|
|
@@ -28,6 +29,7 @@ Inventory rule counts (sample files in this repository):
|
|
|
28
29
|
- `eslint-react`: includes React layer on the same sample
|
|
29
30
|
- `eslint-next`: Next layer on the same sample
|
|
30
31
|
- `eslint-svelte`: effective rules on `src/examples/example.svelte`
|
|
32
|
+
- `eslint-astro`: effective rules on `src/examples/example.astro`
|
|
31
33
|
|
|
32
34
|
## Stylelint (SCSS preset)
|
|
33
35
|
|
package/index.d.ts
CHANGED
|
@@ -11,9 +11,11 @@ declare module '@st1ggy/linter-config' {
|
|
|
11
11
|
export const eslintReact: Linter.Config[]
|
|
12
12
|
export const eslintNext: Linter.Config[]
|
|
13
13
|
export const eslintSvelte: Linter.Config[]
|
|
14
|
+
export const eslintAstro: Linter.Config[]
|
|
14
15
|
|
|
15
16
|
export const prettierCommon: PrettierConfig
|
|
16
17
|
export const prettierSvelte: PrettierConfig
|
|
18
|
+
export const prettierAstro: PrettierConfig
|
|
17
19
|
|
|
18
20
|
export const stylelintScss: Stylelint.Config
|
|
19
21
|
}
|
|
@@ -42,6 +44,14 @@ declare module '@st1ggy/linter-config/eslint-svelte' {
|
|
|
42
44
|
export default config
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
declare module '@st1ggy/linter-config/eslint-astro' {
|
|
48
|
+
import type { Linter } from 'eslint'
|
|
49
|
+
|
|
50
|
+
const config: Linter.Config[]
|
|
51
|
+
|
|
52
|
+
export default config
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
declare module '@st1ggy/linter-config/eslint-common' {
|
|
46
56
|
import type { Linter } from 'eslint'
|
|
47
57
|
|
|
@@ -66,6 +76,14 @@ declare module '@st1ggy/linter-config/prettier-svelte' {
|
|
|
66
76
|
export default config
|
|
67
77
|
}
|
|
68
78
|
|
|
79
|
+
declare module '@st1ggy/linter-config/prettier-astro' {
|
|
80
|
+
import type { Config as PrettierConfig } from 'prettier'
|
|
81
|
+
|
|
82
|
+
const config: PrettierConfig
|
|
83
|
+
|
|
84
|
+
export default config
|
|
85
|
+
}
|
|
86
|
+
|
|
69
87
|
declare module '@st1ggy/linter-config/stylelint-scss' {
|
|
70
88
|
import type * as Stylelint from 'stylelint'
|
|
71
89
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@st1ggy/linter-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.2.2",
|
|
4
4
|
"description": "ESLint, Prettier, and Stylelint shareable configs (sources under src/).",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "
|
|
8
|
+
"url": "https://github.com/St1ggy/linter-config.git"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|
|
11
11
|
"eslint",
|
|
@@ -22,41 +22,40 @@
|
|
|
22
22
|
"@st1ggy/linter-config": "./scripts/linter-init.mjs"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@eslint/compat": "^2.0
|
|
25
|
+
"@eslint/compat": "^2.1.0",
|
|
26
|
+
"@eslint/config-helpers": "^0.7.0",
|
|
26
27
|
"@eslint/js": "^10.0.1",
|
|
27
|
-
"@inquirer/core": "^
|
|
28
|
-
"@inquirer/prompts": "^
|
|
29
|
-
"@next/eslint-plugin-next": "^16.2.3",
|
|
28
|
+
"@inquirer/core": "^11.2.1",
|
|
29
|
+
"@inquirer/prompts": "^8.5.2",
|
|
30
30
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
31
|
-
"eslint": "^
|
|
31
|
+
"eslint": "^10.8.0",
|
|
32
32
|
"eslint-config-prettier": "^10.1.8",
|
|
33
33
|
"eslint-import-resolver-custom-alias": "^1.3.2",
|
|
34
|
-
"eslint-import-resolver-typescript": "^4.4.
|
|
35
|
-
"eslint-plugin-import-x": "^4.
|
|
36
|
-
"eslint-plugin-prettier": "^5.5.
|
|
37
|
-
"eslint-plugin-
|
|
38
|
-
"eslint-plugin-
|
|
39
|
-
"eslint-plugin-sonarjs": "^4.0.2",
|
|
40
|
-
"eslint-plugin-svelte": "^3.17.0",
|
|
41
|
-
"eslint-plugin-unicorn": "^64.0.0",
|
|
34
|
+
"eslint-import-resolver-typescript": "^4.4.5",
|
|
35
|
+
"eslint-plugin-import-x": "^4.17.1",
|
|
36
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
37
|
+
"eslint-plugin-sonarjs": "^4.2.0",
|
|
38
|
+
"eslint-plugin-unicorn": "^73.0.0",
|
|
42
39
|
"find-up-simple": "^1.0.1",
|
|
43
40
|
"minimist": "^1.2.8",
|
|
44
|
-
"ora": "^
|
|
45
|
-
"prettier": "^3.
|
|
46
|
-
"
|
|
47
|
-
"stylelint": "^
|
|
48
|
-
"stylelint-config-clean-order": "^8.0.1",
|
|
41
|
+
"ora": "^9.4.1",
|
|
42
|
+
"prettier": "^3.9.6",
|
|
43
|
+
"stylelint": "^17.14.1",
|
|
44
|
+
"stylelint-config-clean-order": "^10.0.0",
|
|
49
45
|
"stylelint-config-recommended": "^18.0.0",
|
|
50
46
|
"stylelint-config-recommended-scss": "^17.0.1",
|
|
51
47
|
"stylelint-config-sass-guidelines": "^13.0.0",
|
|
52
48
|
"stylelint-no-unsupported-browser-features": "^8.1.1",
|
|
53
49
|
"stylelint-order": "^8.1.1",
|
|
54
50
|
"stylelint-prettier": "^5.0.3",
|
|
55
|
-
"typescript": "
|
|
56
|
-
"typescript-eslint": "^8.
|
|
51
|
+
"typescript": "~6.0.3",
|
|
52
|
+
"typescript-eslint": "^8.66.0"
|
|
57
53
|
},
|
|
58
54
|
"types": "./index.d.ts",
|
|
59
55
|
"type": "module",
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=24.16.0"
|
|
58
|
+
},
|
|
60
59
|
"sideEffects": false,
|
|
61
60
|
"exports": {
|
|
62
61
|
".": {
|
|
@@ -79,6 +78,11 @@
|
|
|
79
78
|
"import": "./src/eslint/eslint-svelte.config.js",
|
|
80
79
|
"default": "./src/eslint/eslint-svelte.config.js"
|
|
81
80
|
},
|
|
81
|
+
"./eslint-astro": {
|
|
82
|
+
"types": "./index.d.ts",
|
|
83
|
+
"import": "./src/eslint/eslint.config.astro.js",
|
|
84
|
+
"default": "./src/eslint/eslint.config.astro.js"
|
|
85
|
+
},
|
|
82
86
|
"./eslint-common": {
|
|
83
87
|
"types": "./index.d.ts",
|
|
84
88
|
"import": "./src/eslint/eslint.config.common.js",
|
|
@@ -94,6 +98,11 @@
|
|
|
94
98
|
"import": "./src/prettier/prettier-svelte.config.js",
|
|
95
99
|
"default": "./src/prettier/prettier-svelte.config.js"
|
|
96
100
|
},
|
|
101
|
+
"./prettier-astro": {
|
|
102
|
+
"types": "./index.d.ts",
|
|
103
|
+
"import": "./src/prettier/prettier-astro.config.js",
|
|
104
|
+
"default": "./src/prettier/prettier-astro.config.js"
|
|
105
|
+
},
|
|
97
106
|
"./stylelint-scss": {
|
|
98
107
|
"types": "./index.d.ts",
|
|
99
108
|
"import": "./src/stylelint/stylelint.config.scss.js",
|
|
@@ -119,28 +128,61 @@
|
|
|
119
128
|
"publish:npm": "npm publish --access public",
|
|
120
129
|
"inventory": "node ./scripts/inventory.mjs",
|
|
121
130
|
"config:init": "node ./scripts/linter-init.mjs init --common --dir ./examples/init-smoke",
|
|
131
|
+
"config:migrate": "node ./scripts/linter-init.mjs migrate --common --dir ./examples/init-smoke",
|
|
122
132
|
"config:reinit": "node ./scripts/linter-init.mjs reinit --common --dir ./examples/init-smoke",
|
|
123
133
|
"config:create": "node ./scripts/linter-init.mjs create --common --dir ./examples/init-smoke",
|
|
124
134
|
"config:remove-current": "bash ./scripts/remove-current.sh"
|
|
125
135
|
},
|
|
126
136
|
"peerDependencies": {
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
"
|
|
137
|
+
"astro": ">=4.0.0",
|
|
138
|
+
"eslint": "^10.8.0",
|
|
139
|
+
"eslint-plugin-astro": "^3.1.0",
|
|
140
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
141
|
+
"eslint-plugin-react": "^7.37.5",
|
|
142
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
143
|
+
"eslint-plugin-svelte": "^3.22.0",
|
|
144
|
+
"next": "^16.3.0",
|
|
145
|
+
"prettier": "^3.9.6",
|
|
146
|
+
"prettier-plugin-astro": "^0.14.1",
|
|
147
|
+
"prettier-plugin-svelte": "^4.1.1",
|
|
130
148
|
"react": "^18.0.0 || ^19.0.0",
|
|
131
|
-
"stylelint": "^17.
|
|
149
|
+
"stylelint": "^17.14.1",
|
|
132
150
|
"svelte": "^4.0.0 || ^5.0.0"
|
|
133
151
|
},
|
|
134
152
|
"peerDependenciesMeta": {
|
|
135
153
|
"eslint": {
|
|
136
154
|
"optional": true
|
|
137
155
|
},
|
|
156
|
+
"eslint-plugin-astro": {
|
|
157
|
+
"optional": true
|
|
158
|
+
},
|
|
159
|
+
"eslint-plugin-jsx-a11y": {
|
|
160
|
+
"optional": true
|
|
161
|
+
},
|
|
162
|
+
"eslint-plugin-react": {
|
|
163
|
+
"optional": true
|
|
164
|
+
},
|
|
165
|
+
"eslint-plugin-react-hooks": {
|
|
166
|
+
"optional": true
|
|
167
|
+
},
|
|
168
|
+
"eslint-plugin-svelte": {
|
|
169
|
+
"optional": true
|
|
170
|
+
},
|
|
138
171
|
"next": {
|
|
139
172
|
"optional": true
|
|
140
173
|
},
|
|
174
|
+
"astro": {
|
|
175
|
+
"optional": true
|
|
176
|
+
},
|
|
141
177
|
"prettier": {
|
|
142
178
|
"optional": true
|
|
143
179
|
},
|
|
180
|
+
"prettier-plugin-astro": {
|
|
181
|
+
"optional": true
|
|
182
|
+
},
|
|
183
|
+
"prettier-plugin-svelte": {
|
|
184
|
+
"optional": true
|
|
185
|
+
},
|
|
144
186
|
"react": {
|
|
145
187
|
"optional": true
|
|
146
188
|
},
|
|
@@ -152,8 +194,17 @@
|
|
|
152
194
|
}
|
|
153
195
|
},
|
|
154
196
|
"devDependencies": {
|
|
197
|
+
"@next/eslint-plugin-next": "^16.3.0",
|
|
155
198
|
"@stylistic/eslint-plugin-migrate": "^4.4.1",
|
|
156
|
-
"conventional-changelog
|
|
157
|
-
"conventional-changelog-conventionalcommits": "^
|
|
199
|
+
"conventional-changelog": "^8.1.0",
|
|
200
|
+
"conventional-changelog-conventionalcommits": "^10.2.1",
|
|
201
|
+
"eslint-plugin-astro": "^3.1.0",
|
|
202
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
203
|
+
"eslint-plugin-react": "^7.37.5",
|
|
204
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
205
|
+
"eslint-plugin-svelte": "^3.22.0",
|
|
206
|
+
"prettier-plugin-astro": "^0.14.1",
|
|
207
|
+
"prettier-plugin-svelte": "^4.1.1",
|
|
208
|
+
"svelte": "^5.56.8"
|
|
158
209
|
}
|
|
159
210
|
}
|
package/scripts/README.md
CHANGED
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
From this repository root, use the npm scripts in the root [`package.json`](../package.json). They run **`node ./scripts/linter-init.mjs`** against **[`examples/init-smoke`](../examples/init-smoke)** so we never write consumer stubs into the **`@st1ggy/linter-config`** package root (the CLI blocks that).
|
|
4
4
|
|
|
5
|
-
| Script
|
|
6
|
-
|
|
|
7
|
-
| `npm run config:init`
|
|
8
|
-
| `npm run config:
|
|
9
|
-
| `npm run config:
|
|
5
|
+
| Script | Effect |
|
|
6
|
+
| ------------------------ | --------------------------------------------------------------------------------------- |
|
|
7
|
+
| `npm run config:init` | `init` — create missing `eslint.config.js`, `prettier.config.js`, `stylelint.config.js` |
|
|
8
|
+
| `npm run config:migrate` | `migrate` — optionally remove legacy configs, then overwrite the three wrappers |
|
|
9
|
+
| `npm run config:reinit` | alias for `config:migrate` |
|
|
10
|
+
| `npm run config:create` | same as `config:init` |
|
|
10
11
|
|
|
11
|
-
Each run installs **`@st1ggy/linter-config`** into `examples/init-smoke` when needed (unless you add **`--skip-install`** to the underlying command in `package.json`).
|
|
12
|
+
Each run installs **`@st1ggy/linter-config`** and only the selected stack's integration plugins into `examples/init-smoke` when needed (unless you add **`--skip-install`** to the underlying command in `package.json`).
|
|
12
13
|
|
|
13
14
|
### Legacy config cleanup (optional)
|
|
14
15
|
|
|
15
|
-
**`
|
|
16
|
+
**`migrate`** presents every legacy config file for confirmation before it overwrites `eslint.config.js`, `prettier.config.js`, and `stylelint.config.js`. [`remove-current.sh`](remove-current.sh) remains available as a standalone cleanup helper. From the repo root: **`npm run config:remove-current`**.
|
|
16
17
|
|
|
17
18
|
Direct CLI (paths from repo root — same entry as published **`@st1ggy/linter-config`**):
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
21
|
node ./scripts/linter-init.mjs init --react
|
|
21
|
-
node ./scripts/linter-init.mjs
|
|
22
|
+
node ./scripts/linter-init.mjs migrate --svelte --dir ./my-app
|
|
23
|
+
node ./scripts/linter-init.mjs init --astro
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
## Flags (published package)
|
|
@@ -28,16 +30,17 @@ The CLI is published under the name **`@st1ggy/linter-config`** (see [`package.j
|
|
|
28
30
|
```bash
|
|
29
31
|
npx @st1ggy/linter-config init --common
|
|
30
32
|
npx @st1ggy/linter-config init --next
|
|
31
|
-
npm exec @st1ggy/linter-config --
|
|
33
|
+
npm exec @st1ggy/linter-config -- migrate --svelte
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
**Without** installing first:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
npx --yes @st1ggy/linter-config init --
|
|
39
|
+
npx --yes @st1ggy/linter-config init --astro
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
- **Stack (optional, default common):** `--common` | `--react` | `--next` | `--svelte` (at most one).
|
|
42
|
+
- **Stack (optional, default common):** `--common` | `--react` | `--next` | `--svelte` | `--astro` (at most one).
|
|
41
43
|
- **`--skip-install`:** only write wrapper files; do not run npm/pnpm/yarn/bun.
|
|
44
|
+
- Every CLI command opens an interactive wizard. `init` creates missing wrappers; `migrate` can remove selected legacy configs and replaces wrappers.
|
|
42
45
|
|
|
43
46
|
Shell shortcuts in this folder (`init-common.sh`, etc.) call **`node …/linter-init.mjs`** (same script as the published **`@st1ggy/linter-config`** CLI) with the matching stack; pass **`--skip-install`** through when needed.
|
package/scripts/inventory.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Or set `LINTER_CONFIG_ROOT` to override the default (repository root).
|
|
4
4
|
|
|
5
5
|
import { spawnSync } from 'node:child_process'
|
|
6
|
-
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
6
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
7
7
|
import { createRequire } from 'node:module'
|
|
8
8
|
import path from 'node:path'
|
|
9
9
|
import process from 'node:process'
|
|
@@ -12,7 +12,8 @@ import { fileURLToPath } from 'node:url'
|
|
|
12
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
13
13
|
const LINTER_ROOT = process.env.LINTER_CONFIG_ROOT ?? path.resolve(__dirname, '..')
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const packageJson = JSON.parse(readFileSync(path.join(LINTER_ROOT, 'package.json'), 'utf8'))
|
|
16
|
+
const SOURCE_LABEL = `${packageJson.name}@${packageJson.version} (local tree)`
|
|
16
17
|
|
|
17
18
|
const flatConfigPresets = [
|
|
18
19
|
{
|
|
@@ -35,6 +36,11 @@ const flatConfigPresets = [
|
|
|
35
36
|
module: 'src/eslint/eslint-svelte.config.js',
|
|
36
37
|
sampleFile: 'src/examples/example.svelte',
|
|
37
38
|
},
|
|
39
|
+
{
|
|
40
|
+
id: 'eslint-astro',
|
|
41
|
+
module: 'src/eslint/eslint.config.astro.js',
|
|
42
|
+
sampleFile: 'src/examples/example.astro',
|
|
43
|
+
},
|
|
38
44
|
]
|
|
39
45
|
|
|
40
46
|
function compareKeysAlphabetically(left, right) {
|
|
@@ -99,6 +105,7 @@ async function inventoryFlatConfigs() {
|
|
|
99
105
|
const engine = new ESLint({
|
|
100
106
|
cwd: LINTER_ROOT,
|
|
101
107
|
overrideConfig: config,
|
|
108
|
+
overrideConfigFile: true,
|
|
102
109
|
})
|
|
103
110
|
const filePath = path.join(LINTER_ROOT, preset.sampleFile)
|
|
104
111
|
const calculated = await engine.calculateConfigForFile(filePath)
|
|
@@ -1,33 +1,43 @@
|
|
|
1
1
|
// Shared logic for @st1ggy/linter-config CLI (no prompts).
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from 'node:child_process'
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
|
|
5
5
|
import path from 'node:path'
|
|
6
6
|
|
|
7
7
|
export const PACKAGE = '@st1ggy/linter-config'
|
|
8
8
|
|
|
9
|
-
export const STACK_KEYS = ['common', 'react', 'next', 'svelte']
|
|
9
|
+
export const STACK_KEYS = ['common', 'react', 'next', 'svelte', 'astro']
|
|
10
10
|
|
|
11
11
|
export const STACKS = {
|
|
12
12
|
common: {
|
|
13
13
|
eslint: 'eslint-common',
|
|
14
14
|
prettier: 'prettier-common',
|
|
15
15
|
stylelint: 'stylelint-scss',
|
|
16
|
+
packages: [],
|
|
16
17
|
},
|
|
17
18
|
react: {
|
|
18
19
|
eslint: 'eslint-react',
|
|
19
20
|
prettier: 'prettier-common',
|
|
20
21
|
stylelint: 'stylelint-scss',
|
|
22
|
+
packages: ['eslint-plugin-react', 'eslint-plugin-react-hooks'],
|
|
21
23
|
},
|
|
22
24
|
next: {
|
|
23
25
|
eslint: 'eslint-next',
|
|
24
26
|
prettier: 'prettier-common',
|
|
25
27
|
stylelint: 'stylelint-scss',
|
|
28
|
+
packages: ['@next/eslint-plugin-next', 'eslint-plugin-react', 'eslint-plugin-react-hooks'],
|
|
26
29
|
},
|
|
27
30
|
svelte: {
|
|
28
31
|
eslint: 'eslint-svelte',
|
|
29
32
|
prettier: 'prettier-svelte',
|
|
30
33
|
stylelint: 'stylelint-scss',
|
|
34
|
+
packages: ['eslint-plugin-svelte', 'prettier-plugin-svelte'],
|
|
35
|
+
},
|
|
36
|
+
astro: {
|
|
37
|
+
eslint: 'eslint-astro',
|
|
38
|
+
prettier: 'prettier-astro',
|
|
39
|
+
stylelint: 'stylelint-scss',
|
|
40
|
+
packages: ['eslint-plugin-astro', 'eslint-plugin-jsx-a11y', 'prettier-plugin-astro'],
|
|
31
41
|
},
|
|
32
42
|
}
|
|
33
43
|
|
|
@@ -48,6 +58,10 @@ export const STACK_CHOICES = [
|
|
|
48
58
|
value: 'svelte',
|
|
49
59
|
name: 'svelte — Svelte + Prettier plugin for Svelte',
|
|
50
60
|
},
|
|
61
|
+
{
|
|
62
|
+
value: 'astro',
|
|
63
|
+
name: 'astro — Astro + Prettier plugin for Astro',
|
|
64
|
+
},
|
|
51
65
|
]
|
|
52
66
|
|
|
53
67
|
export function readPackageJson(directory) {
|
|
@@ -64,7 +78,7 @@ export function readPackageJson(directory) {
|
|
|
64
78
|
}
|
|
65
79
|
}
|
|
66
80
|
|
|
67
|
-
export function
|
|
81
|
+
export function mergedDependencies(packageJson) {
|
|
68
82
|
return {
|
|
69
83
|
...packageJson.optionalDependencies,
|
|
70
84
|
...packageJson.peerDependencies,
|
|
@@ -79,11 +93,12 @@ export function isSelfPackageRoot(directory) {
|
|
|
79
93
|
return packageJson?.name === PACKAGE
|
|
80
94
|
}
|
|
81
95
|
|
|
82
|
-
export function hasResolvablePackage(startDirectory) {
|
|
96
|
+
export function hasResolvablePackage(startDirectory, packageName = PACKAGE) {
|
|
83
97
|
let currentDirectory = path.resolve(startDirectory)
|
|
98
|
+
const packageParts = packageName.split('/')
|
|
84
99
|
|
|
85
100
|
while (true) {
|
|
86
|
-
const marker = path.join(currentDirectory, 'node_modules',
|
|
101
|
+
const marker = path.join(currentDirectory, 'node_modules', ...packageParts, 'package.json')
|
|
87
102
|
|
|
88
103
|
if (existsSync(marker)) {
|
|
89
104
|
return true
|
|
@@ -144,10 +159,10 @@ export function runPmSync(command, args, cwd) {
|
|
|
144
159
|
}
|
|
145
160
|
|
|
146
161
|
// skipInstall: skip npm install; options.quiet: suppress stderr warnings
|
|
147
|
-
export function
|
|
162
|
+
export function ensureDevDependencies(targetDirectory, packages, shouldSkipInstall, options = {}) {
|
|
148
163
|
const { quiet = false } = options
|
|
149
164
|
|
|
150
|
-
if (
|
|
165
|
+
if (shouldSkipInstall) {
|
|
151
166
|
return
|
|
152
167
|
}
|
|
153
168
|
|
|
@@ -158,29 +173,32 @@ export function ensureDevDependency(targetDirectory, skipInstall, options = {})
|
|
|
158
173
|
if (!existsSync(packageJsonPath)) {
|
|
159
174
|
if (!quiet) {
|
|
160
175
|
process.stderr.write(
|
|
161
|
-
`warning: no package.json in ${directory}; add the
|
|
176
|
+
`warning: no package.json in ${directory}; add the packages manually: npm i -D ${packages.join(' ')}\n`,
|
|
162
177
|
)
|
|
163
178
|
}
|
|
164
179
|
|
|
165
180
|
return
|
|
166
181
|
}
|
|
167
182
|
|
|
168
|
-
|
|
183
|
+
const packageJson = readPackageJson(directory)
|
|
184
|
+
|
|
185
|
+
if (!packageJson) {
|
|
169
186
|
return
|
|
170
187
|
}
|
|
171
188
|
|
|
172
|
-
const
|
|
189
|
+
const dependencies = mergedDependencies(packageJson)
|
|
190
|
+
const packagesToAdd = packages.filter((packageName) => !Object.hasOwn(dependencies, packageName))
|
|
191
|
+
const hasUnresolvedPackage = packages.some((packageName) => !hasResolvablePackage(directory, packageName))
|
|
173
192
|
|
|
174
|
-
if (!
|
|
193
|
+
if (!hasUnresolvedPackage && packagesToAdd.length === 0) {
|
|
175
194
|
return
|
|
176
195
|
}
|
|
177
196
|
|
|
178
197
|
const pm = detectPackageManager(directory)
|
|
179
|
-
const listed = Boolean(mergedDeps(packageJson)[PACKAGE])
|
|
180
198
|
|
|
181
|
-
if (
|
|
199
|
+
if (packagesToAdd.length === 0) {
|
|
182
200
|
if (!quiet) {
|
|
183
|
-
process.stdout.write(`install: ${pm} install (${directory}) —
|
|
201
|
+
process.stdout.write(`install: ${pm} install (${directory}) — selected packages already listed\n`)
|
|
184
202
|
}
|
|
185
203
|
|
|
186
204
|
const sync = {
|
|
@@ -196,53 +214,69 @@ export function ensureDevDependency(targetDirectory, skipInstall, options = {})
|
|
|
196
214
|
}
|
|
197
215
|
|
|
198
216
|
if (!quiet) {
|
|
199
|
-
process.stdout.write(`install: ${pm} add -D ${
|
|
217
|
+
process.stdout.write(`install: ${pm} add -D ${packagesToAdd.join(' ')} (${directory})\n`)
|
|
200
218
|
}
|
|
201
219
|
|
|
202
220
|
const add = {
|
|
203
|
-
npm: () => runPmSync('npm', ['install', '-D',
|
|
204
|
-
pnpm: () => runPmSync('pnpm', ['add', '-D',
|
|
205
|
-
yarn: () => runPmSync('yarn', ['add', '-D',
|
|
206
|
-
bun: () => runPmSync('bun', ['add', '-d',
|
|
221
|
+
npm: () => runPmSync('npm', ['install', '-D', ...packagesToAdd], directory),
|
|
222
|
+
pnpm: () => runPmSync('pnpm', ['add', '-D', ...packagesToAdd], directory),
|
|
223
|
+
yarn: () => runPmSync('yarn', ['add', '-D', ...packagesToAdd], directory),
|
|
224
|
+
bun: () => runPmSync('bun', ['add', '-d', ...packagesToAdd], directory),
|
|
207
225
|
}
|
|
208
226
|
|
|
209
227
|
add[pm]()
|
|
210
228
|
}
|
|
211
229
|
|
|
230
|
+
export function ensureDevDependency(targetDirectory, shouldSkipInstall, options = {}) {
|
|
231
|
+
ensureDevDependencies(targetDirectory, [PACKAGE], shouldSkipInstall, options)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function stackPackages(stackKey) {
|
|
235
|
+
const stack = STACKS[stackKey]
|
|
236
|
+
|
|
237
|
+
if (!stack) {
|
|
238
|
+
throw new Error(`Unknown stack "${stackKey}". Use: ${STACK_KEYS.join(', ')}`)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return [PACKAGE, ...stack.packages]
|
|
242
|
+
}
|
|
243
|
+
|
|
212
244
|
export function printHelp() {
|
|
213
245
|
process.stdout.write(`\
|
|
214
246
|
${PACKAGE} — generate local wrapper configs in a consumer project.
|
|
215
247
|
|
|
216
|
-
|
|
248
|
+
Always opens a guided menu in an interactive terminal. Stack flags preselect a choice.
|
|
217
249
|
|
|
218
250
|
Commands:
|
|
219
251
|
init Create missing files only (skip existing).
|
|
220
|
-
|
|
221
|
-
|
|
252
|
+
migrate Optionally remove legacy configs, then overwrite wrapper files.
|
|
253
|
+
reinit Alias for migrate.
|
|
254
|
+
create Alias for init.
|
|
222
255
|
|
|
223
256
|
Writes (each command):
|
|
224
257
|
eslint.config.js, prettier.config.js, stylelint.config.js — re-exports for one stack.
|
|
225
258
|
|
|
226
|
-
Unless --skip-install: if package.json exists
|
|
227
|
-
|
|
259
|
+
Unless --skip-install: if package.json exists, runs the detected package manager to add or sync
|
|
260
|
+
${PACKAGE} and the selected stack's integration plugins.
|
|
228
261
|
|
|
229
262
|
Stack (at most one; default: common):
|
|
230
|
-
--common | --react | --next | --svelte
|
|
263
|
+
--common | --react | --next | --svelte | --astro
|
|
231
264
|
|
|
232
265
|
Options:
|
|
233
266
|
--dir, -d Target directory (default: current working directory).
|
|
234
267
|
--skip-install Do not run npm/pnpm/yarn/bun (only write wrapper files).
|
|
235
|
-
-i, --interactive
|
|
268
|
+
-i, --interactive Accepted for compatibility; the menu is always interactive.
|
|
236
269
|
|
|
237
270
|
Examples (after: npm i -D ${PACKAGE}):
|
|
238
271
|
npx ${PACKAGE}
|
|
239
272
|
npx ${PACKAGE} init
|
|
240
273
|
npx ${PACKAGE} init --react
|
|
241
|
-
npx ${PACKAGE}
|
|
274
|
+
npx ${PACKAGE} migrate --svelte --dir ./apps/web
|
|
275
|
+
npx ${PACKAGE} init --astro
|
|
242
276
|
npm exec ${PACKAGE} -- init --common
|
|
243
277
|
|
|
244
278
|
Without prior install (downloads this package; then runs the same CLI):
|
|
245
|
-
npx --yes ${PACKAGE} init --
|
|
279
|
+
npx --yes ${PACKAGE} init --astro
|
|
246
280
|
|
|
247
281
|
Repo (paths from root):
|
|
248
282
|
node scripts/linter-init.mjs init --common
|
|
@@ -279,6 +313,33 @@ export function writeFile(targetDirectory, name, content, overwrite, options = {
|
|
|
279
313
|
return true
|
|
280
314
|
}
|
|
281
315
|
|
|
316
|
+
export function wrapperFileNames() {
|
|
317
|
+
return ['eslint.config.js', 'prettier.config.js', 'stylelint.config.js']
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function existingWrapperFiles(targetDirectory) {
|
|
321
|
+
return wrapperFileNames().filter((name) => existsSync(path.join(targetDirectory, name)))
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function legacyConfigFiles(targetDirectory) {
|
|
325
|
+
if (!existsSync(targetDirectory)) {
|
|
326
|
+
return []
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const wrappers = new Set(wrapperFileNames())
|
|
330
|
+
|
|
331
|
+
return readdirSync(targetDirectory, { withFileTypes: true })
|
|
332
|
+
.filter((entry) => entry.isFile() && /(?:eslint|prettier|stylelint)/i.test(entry.name) && !wrappers.has(entry.name))
|
|
333
|
+
.map((entry) => entry.name)
|
|
334
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function removeFiles(targetDirectory, names) {
|
|
338
|
+
for (const name of names) {
|
|
339
|
+
rmSync(path.join(targetDirectory, name), { force: true })
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
282
343
|
export function resolveStackKey(values) {
|
|
283
344
|
const chosen = []
|
|
284
345
|
|
|
@@ -309,9 +370,9 @@ export function run(mode, targetDirectory, stackKey, options = {}) {
|
|
|
309
370
|
throw new Error(`Unknown stack "${stackKey}". Use: ${STACK_KEYS.join(', ')}`)
|
|
310
371
|
}
|
|
311
372
|
|
|
312
|
-
const
|
|
373
|
+
const shouldOverwrite = mode === 'migrate' || mode === 'reinit'
|
|
313
374
|
|
|
314
|
-
writeFile(targetDirectory, 'eslint.config.js', jsReExport(stack.eslint),
|
|
315
|
-
writeFile(targetDirectory, 'prettier.config.js', jsReExport(stack.prettier),
|
|
316
|
-
writeFile(targetDirectory, 'stylelint.config.js', jsReExport(stack.stylelint),
|
|
375
|
+
writeFile(targetDirectory, 'eslint.config.js', jsReExport(stack.eslint), shouldOverwrite, { quiet })
|
|
376
|
+
writeFile(targetDirectory, 'prettier.config.js', jsReExport(stack.prettier), shouldOverwrite, { quiet })
|
|
377
|
+
writeFile(targetDirectory, 'stylelint.config.js', jsReExport(stack.stylelint), shouldOverwrite, { quiet })
|
|
317
378
|
}
|