@archpublicwebsite/eslint-config 1.0.23 → 1.0.30
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 +48 -11
- package/lint-staged.config.mjs +3 -1
- package/package.json +1 -1
- package/tools/git-hooks/pre-commit.mjs +65 -0
- package/tools/setup/install.mjs +24 -7
- package/tools/setup/vscode.mjs +9 -3
package/README.md
CHANGED
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Reusable ESLint flat config and git-hook toolkit for Archipelago projects.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Last Month Updates (May-Jun 2026)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Here are the most important recent changes:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- The installer can now create key setup files automatically when they are missing.
|
|
10
|
+
- The `pre-commit` hook is now more resilient when project config is incomplete.
|
|
11
|
+
- The security scanner is more accurate and produces fewer false positives.
|
|
12
|
+
- A strict account/signature validation mode is available via `REQUIRE_VERIFIED_ACCOUNT=1`.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
When `REQUIRE_VERIFIED_ACCOUNT=1` is enabled:
|
|
15
15
|
|
|
16
|
-
- `pre-commit`
|
|
17
|
-
- `pre-push`
|
|
16
|
+
- `pre-commit` checks `user.name`, `user.email`, and `commit.gpgsign=true`.
|
|
17
|
+
- `pre-push` rejects commits whose signature status is not `G`.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Quick start:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
pnpm install
|
|
@@ -25,7 +25,7 @@ pnpm lint:check
|
|
|
25
25
|
pnpm typecheck
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Enable strict verification only when needed:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
REQUIRE_VERIFIED_ACCOUNT=1 git commit
|
|
@@ -131,6 +131,43 @@ The setup merges ESLint-related settings into `.vscode/settings.json`:
|
|
|
131
131
|
|
|
132
132
|
Existing settings are preserved. Only the ESLint-related keys are added or updated.
|
|
133
133
|
|
|
134
|
+
## Troubleshooting (Nuxt)
|
|
135
|
+
|
|
136
|
+
If you see errors like:
|
|
137
|
+
|
|
138
|
+
- `Cannot find module '~/composables'`
|
|
139
|
+
- `Cannot find name 'useRoute'`
|
|
140
|
+
- `Cannot find name 'useRuntimeConfig'`
|
|
141
|
+
- `'<script setup ...>' expected` in `.vue` files
|
|
142
|
+
|
|
143
|
+
Use this checklist:
|
|
144
|
+
|
|
145
|
+
1. Ensure root `tsconfig.json` extends Nuxt types:
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"extends": "./.nuxt/tsconfig.json"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
2. Generate Nuxt type files:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npx nuxi prepare
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
3. Confirm VS Code uses Volar for Vue files (disable Vetur).
|
|
160
|
+
4. Re-run setup script:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
node node_modules/@archpublicwebsite/eslint-config/tools/setup/install.mjs
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Note:
|
|
167
|
+
|
|
168
|
+
- The setup now writes workspace settings that disable Vetur validators to prevent false Vue/TS errors.
|
|
169
|
+
- After running setup, restart VS Code (`Developer: Reload Window`) so the language server state is refreshed.
|
|
170
|
+
|
|
134
171
|
## Public API
|
|
135
172
|
|
|
136
173
|
The package exports:
|
package/lint-staged.config.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const config = {
|
|
2
|
-
|
|
2
|
+
// Keep JS/TS/Vue formatting and lint fixes in one engine (ESLint)
|
|
3
|
+
// so save behavior and pre-commit output stay consistent.
|
|
4
|
+
'*.{js,mjs,cjs,ts,tsx,vue}': ['eslint --fix'],
|
|
3
5
|
'*.{json,md,yml,yaml,css,scss,html}': ['prettier --write'],
|
|
4
6
|
}
|
|
5
7
|
|
package/package.json
CHANGED
|
@@ -15,6 +15,66 @@ function runIfExists(scriptPath, command) {
|
|
|
15
15
|
run(command, { stdio: 'inherit' })
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function quoteShellArg(value) {
|
|
19
|
+
const escaped = String(value).replaceAll("'", '\'"\'"\'')
|
|
20
|
+
return `'${escaped}'`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getStagedLintTargets() {
|
|
24
|
+
const output = runSafe('git diff --cached --name-only --diff-filter=ACMR')
|
|
25
|
+
if (!output) {
|
|
26
|
+
return []
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return output
|
|
30
|
+
.split('\n')
|
|
31
|
+
.map(line => line.trim())
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
// Keep this check focused on app/source code files that should match
|
|
34
|
+
// editor save behavior. Tooling files are validated by lint-staged itself.
|
|
35
|
+
.filter(filePath => /\.(js|ts|tsx|vue)$/.test(filePath))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function ensureEslintFlatConfig() {
|
|
39
|
+
const hasFlatConfig =
|
|
40
|
+
existsSync('./eslint.config.mjs') || existsSync('./eslint.config.js') || existsSync('./eslint.config.cjs')
|
|
41
|
+
|
|
42
|
+
if (hasFlatConfig) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const installerPath = join(__dirname, '..', 'setup', 'install.mjs')
|
|
47
|
+
console.log('\nMissing eslint.config.* detected. Running setup installer to auto-create required config...')
|
|
48
|
+
run(`node "${installerPath}"`, { stdio: 'inherit' })
|
|
49
|
+
|
|
50
|
+
const configCreated =
|
|
51
|
+
existsSync('./eslint.config.mjs') || existsSync('./eslint.config.js') || existsSync('./eslint.config.cjs')
|
|
52
|
+
|
|
53
|
+
if (!configCreated) {
|
|
54
|
+
console.error('\nCOMMIT FAILED: eslint.config.* is still missing after setup.')
|
|
55
|
+
console.error('Run: node node_modules/@archpublicwebsite/eslint-config/tools/setup/install.mjs')
|
|
56
|
+
process.exit(1)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function verifySaveEquivalentLintState() {
|
|
61
|
+
const lintTargets = getStagedLintTargets()
|
|
62
|
+
if (lintTargets.length === 0) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const targetArgs = lintTargets.map(quoteShellArg).join(' ')
|
|
67
|
+
console.log('\nVerifying staged code with ESLint check...')
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
run(`pnpm exec eslint --no-error-on-unmatched-pattern ${targetArgs}`, { stdio: 'inherit' })
|
|
71
|
+
} catch {
|
|
72
|
+
console.error('\nCOMMIT FAILED: staged code still has ESLint issues after auto-fix.')
|
|
73
|
+
console.error('Fix the remaining issues, stage again, then commit.')
|
|
74
|
+
process.exit(1)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
18
78
|
if (!hasCommand('pnpm')) {
|
|
19
79
|
console.error('\nCOMMIT FAILED: pnpm is required but not found.\n')
|
|
20
80
|
process.exit(1)
|
|
@@ -58,6 +118,8 @@ if (process.env.SKIP_GLOBAL_SCAN === '1') {
|
|
|
58
118
|
}
|
|
59
119
|
|
|
60
120
|
// ── 3. Lint-staged — auto-fix & format staged files ───────────────────────────
|
|
121
|
+
ensureEslintFlatConfig()
|
|
122
|
+
|
|
61
123
|
console.log('\nRunning lint-staged (auto-fix staged files)...')
|
|
62
124
|
if (existsSync('./lint-staged.config.mjs')) {
|
|
63
125
|
run('pnpm exec lint-staged --config lint-staged.config.mjs', { stdio: 'inherit' })
|
|
@@ -66,4 +128,7 @@ if (existsSync('./lint-staged.config.mjs')) {
|
|
|
66
128
|
run('pnpm exec lint-staged', { stdio: 'inherit' })
|
|
67
129
|
}
|
|
68
130
|
|
|
131
|
+
// ── 4. Save-equivalent verification (same lint result as editor save) ────────
|
|
132
|
+
verifySaveEquivalentLintState()
|
|
133
|
+
|
|
69
134
|
console.log('\nCOMMIT CHECKS PASSED\n')
|
package/tools/setup/install.mjs
CHANGED
|
@@ -27,6 +27,11 @@ function writeIfMissing(filePath, content) {
|
|
|
27
27
|
return true
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
function isNuxtProject(projectRoot) {
|
|
31
|
+
const nuxtConfigNames = ['nuxt.config.ts', 'nuxt.config.js', 'nuxt.config.mjs', 'nuxt.config.cjs']
|
|
32
|
+
return nuxtConfigNames.some(fileName => existsSync(join(projectRoot, fileName)))
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
// ─── .editorconfig ──────────────────────────────────────────────────────────
|
|
31
36
|
|
|
32
37
|
function ensureEditorConfig(projectRoot) {
|
|
@@ -174,20 +179,19 @@ function ensureTsConfigBase(projectRoot) {
|
|
|
174
179
|
|
|
175
180
|
function ensureTsConfig(projectRoot) {
|
|
176
181
|
const tsconfigPath = join(projectRoot, 'tsconfig.json')
|
|
177
|
-
const
|
|
182
|
+
const nonNuxtContent = `{
|
|
178
183
|
"extends": "./tsconfig.base.json",
|
|
179
184
|
"compilerOptions": {
|
|
180
185
|
"paths": {}
|
|
181
186
|
},
|
|
182
187
|
"include": [
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
"
|
|
186
|
-
"
|
|
188
|
+
"**/*.ts",
|
|
189
|
+
"**/*.tsx",
|
|
190
|
+
"**/*.vue",
|
|
191
|
+
"**/*.d.ts",
|
|
187
192
|
"vite.config.ts"
|
|
188
193
|
],
|
|
189
194
|
"exclude": [
|
|
190
|
-
"apps/**",
|
|
191
195
|
"node_modules",
|
|
192
196
|
"**/dist/**",
|
|
193
197
|
"**/.nuxt/**",
|
|
@@ -195,7 +199,20 @@ function ensureTsConfig(projectRoot) {
|
|
|
195
199
|
]
|
|
196
200
|
}
|
|
197
201
|
`
|
|
198
|
-
|
|
202
|
+
|
|
203
|
+
// Nuxt projects must extend .nuxt/tsconfig.json so aliases (`~/`, `#imports`)
|
|
204
|
+
// and auto-imported composables (`useRoute`, `useRuntimeConfig`, etc.) resolve.
|
|
205
|
+
const nuxtContent = `{
|
|
206
|
+
"extends": "./.nuxt/tsconfig.json"
|
|
207
|
+
}
|
|
208
|
+
`
|
|
209
|
+
|
|
210
|
+
const nuxtProject = isNuxtProject(projectRoot)
|
|
211
|
+
const content = nuxtProject ? nuxtContent : nonNuxtContent
|
|
212
|
+
|
|
213
|
+
if (writeIfMissing(tsconfigPath, content)) {
|
|
214
|
+
log(nuxtProject ? 'Created tsconfig.json (Nuxt mode)' : 'Created tsconfig.json')
|
|
215
|
+
}
|
|
199
216
|
}
|
|
200
217
|
|
|
201
218
|
function ensureCommitlintConfig(projectRoot) {
|
package/tools/setup/vscode.mjs
CHANGED
|
@@ -20,7 +20,13 @@ const VSCODE_ESLINT_SETTINGS = {
|
|
|
20
20
|
|
|
21
21
|
// Volar + TS integration for Vue 3 SFC template diagnostics
|
|
22
22
|
'vue.server.hybridMode': true,
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
// Defensive guard: if Vetur is installed globally, disable its validators
|
|
25
|
+
// to avoid conflicting diagnostics like "'<script setup ...>' expected".
|
|
26
|
+
'vetur.validation.template': false,
|
|
27
|
+
'vetur.validation.script': false,
|
|
28
|
+
'vetur.validation.style': false,
|
|
29
|
+
'vetur.experimental.templateInterpolationService': false,
|
|
24
30
|
|
|
25
31
|
// Prevent duplicate/broken diagnostics from built-in TS/JS validators
|
|
26
32
|
// (vue-tsc + Volar remain the source of truth for Vue type diagnostics).
|
|
@@ -36,7 +42,7 @@ const VSCODE_ESLINT_SETTINGS = {
|
|
|
36
42
|
|
|
37
43
|
// Auto-fix on save via ESLint
|
|
38
44
|
'editor.codeActionsOnSave': {
|
|
39
|
-
'source.fixAll.eslint':
|
|
45
|
+
'source.fixAll.eslint': true,
|
|
40
46
|
'source.organizeImports': 'never',
|
|
41
47
|
},
|
|
42
48
|
|
|
@@ -57,7 +63,7 @@ const VSCODE_ESLINT_SETTINGS = {
|
|
|
57
63
|
'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
|
|
58
64
|
},
|
|
59
65
|
'[vue]': {
|
|
60
|
-
'editor.defaultFormatter': '
|
|
66
|
+
'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
|
|
61
67
|
},
|
|
62
68
|
'[json]': {
|
|
63
69
|
'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
|