@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 CHANGED
@@ -2,21 +2,21 @@
2
2
 
3
3
  Reusable ESLint flat config and git-hook toolkit for Archipelago projects.
4
4
 
5
- ## Update 1 Bulan Terakhir (Mei-Jun 2026)
5
+ ## Last Month Updates (May-Jun 2026)
6
6
 
7
- Ringkasan perubahan terbaru yang paling penting:
7
+ Here are the most important recent changes:
8
8
 
9
- - Installer sekarang bisa membuat file setup utama otomatis saat belum ada.
10
- - Hook `pre-commit` lebih tahan error saat config belum lengkap.
11
- - Security scanner lebih akurat dan mengurangi false positive.
12
- - Ada opsi validasi akun/signature ketat lewat `REQUIRE_VERIFIED_ACCOUNT=1`.
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
- Jika `REQUIRE_VERIFIED_ACCOUNT=1` aktif:
14
+ When `REQUIRE_VERIFIED_ACCOUNT=1` is enabled:
15
15
 
16
- - `pre-commit` akan cek `user.name`, `user.email`, dan `commit.gpgsign=true`.
17
- - `pre-push` akan menolak commit yang status signature-nya bukan `G`.
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
- Cara pakai cepat:
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
- Aktifkan strict verification hanya saat dibutuhkan:
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:
@@ -1,5 +1,7 @@
1
1
  const config = {
2
- '*.{js,mjs,cjs,ts,tsx,vue}': ['eslint --fix', 'prettier --write'],
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archpublicwebsite/eslint-config",
3
- "version": "1.0.23",
3
+ "version": "1.0.30",
4
4
  "author": "Archipelago Hotels",
5
5
  "description": "Reusable ESLint flat config and git-hook toolkit for Archipelago projects",
6
6
  "type": "module",
@@ -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')
@@ -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 content = `{
182
+ const nonNuxtContent = `{
178
183
  "extends": "./tsconfig.base.json",
179
184
  "compilerOptions": {
180
185
  "paths": {}
181
186
  },
182
187
  "include": [
183
- "src/**/*.ts",
184
- "src/**/*.vue",
185
- "packages/**/*.ts",
186
- "packages/**/*.vue",
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
- if (writeIfMissing(tsconfigPath, content)) log('Created tsconfig.json')
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) {
@@ -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
- 'volar.takeOverMode.enabled': true,
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': 'explicit',
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': 'Vue.volar',
66
+ 'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
61
67
  },
62
68
  '[json]': {
63
69
  'editor.defaultFormatter': 'dbaeumer.vscode-eslint',