From ea222652fbde27863add40b56b1310a272dbe96c Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Tue, 23 Jun 2026 19:04:09 +0900 Subject: [PATCH 1/6] fix(cli): inline lint-staged version for staged debug bundle --- packages/cli/tsdown.config.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts index 9b1f2e8bff..b359ff4565 100644 --- a/packages/cli/tsdown.config.ts +++ b/packages/cli/tsdown.config.ts @@ -1,5 +1,10 @@ +import { createRequire } from 'node:module'; + import { defineConfig } from 'tsdown'; +const require = createRequire(import.meta.url); +const lintStagedPackageJson = require('lint-staged/package.json') as { version: string }; + /** * Rewrite `../versions.js` → `./versions.js` at resolve time. * @@ -18,6 +23,27 @@ const fixVersionsPathPlugin = { }, }; +/** + * `lint-staged` reads `../package.json` only when debug mode is enabled. + * After bundling `lib/version.js` into `dist/staged/bin.js`, that relative URL + * points at `dist/package.json` instead of lint-staged's package root. + */ +const inlineLintStagedVersionPlugin = { + name: 'inline-lint-staged-version', + transform(_code: string, id: string) { + const normalizedId = id.split('?')[0].replaceAll('\\', '/'); + + if (normalizedId.endsWith('/lint-staged/lib/version.js')) { + return { + code: `export const getVersion = async () => ${JSON.stringify(lintStagedPackageJson.version)};\n`, + map: null, + }; + } + + return undefined; + }, +}; + export default defineConfig([ // ESM — all entry points bundled to dist/ { @@ -56,7 +82,7 @@ export default defineConfig([ mainFields: ['module', 'main'], }, }, - plugins: [fixVersionsPathPlugin], + plugins: [fixVersionsPathPlugin, inlineLintStagedVersionPlugin], }, // CJS — dual-format entries From fd802abdbf980327b14ad354e78e580005080d6d Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Tue, 23 Jun 2026 19:32:41 +0900 Subject: [PATCH 2/6] chore: retrigger actions From 9c8e917cd285e4d9c065199c9b81ed5f0e20e2a3 Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Tue, 23 Jun 2026 19:50:45 +0900 Subject: [PATCH 3/6] fix(cli): support vp staged --debug in bundled lint-staged --- .../command-staged-with-config/snap.txt | 5 ++- .../command-staged-with-config/steps.json | 6 ++++ packages/cli/tsdown.config.ts | 32 ++++++++++++------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt index 7fcf705678..2dd9564b93 100644 --- a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt +++ b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt @@ -20,5 +20,8 @@ [COMPLETED] Cleaning up temporary files... > git add -A && git commit -m 'second' +> echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts +> vp staged --debug > /dev/null 2>&1 # should succeed with debug enabled +> git add -A && git commit -m 'third' > printf 'eval("code");\n' > src/fail.js && git add src/fail.js -[1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors \ No newline at end of file +[1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors diff --git a/packages/cli/snap-tests-global/command-staged-with-config/steps.json b/packages/cli/snap-tests-global/command-staged-with-config/steps.json index 0430c879d2..a5d0049765 100644 --- a/packages/cli/snap-tests-global/command-staged-with-config/steps.json +++ b/packages/cli/snap-tests-global/command-staged-with-config/steps.json @@ -9,6 +9,12 @@ }, "vp staged # should succeed with staged .ts files", { "command": "git add -A && git commit -m 'second'", "ignoreOutput": true }, + { + "command": "echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts", + "ignoreOutput": true + }, + "vp staged --debug > /dev/null 2>&1 # should succeed with debug enabled", + { "command": "git add -A && git commit -m 'third'", "ignoreOutput": true }, { "command": "printf 'eval(\"code\");\\n' > src/fail.js && git add src/fail.js", "ignoreOutput": true diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts index b359ff4565..a2c9d79540 100644 --- a/packages/cli/tsdown.config.ts +++ b/packages/cli/tsdown.config.ts @@ -4,6 +4,7 @@ import { defineConfig } from 'tsdown'; const require = createRequire(import.meta.url); const lintStagedPackageJson = require('lint-staged/package.json') as { version: string }; +const virtualLintStagedVersionId = '\0vite-plus:lint-staged-version'; /** * Rewrite `../versions.js` → `./versions.js` at resolve time. @@ -24,22 +25,29 @@ const fixVersionsPathPlugin = { }; /** - * `lint-staged` reads `../package.json` only when debug mode is enabled. - * After bundling `lib/version.js` into `dist/staged/bin.js`, that relative URL - * points at `dist/package.json` instead of lint-staged's package root. + * `lint-staged` reads `../package.json` from `lib/version.js` when debug logging is enabled. + * The CLI bundles lint-staged into `dist/staged/bin.js`, so that relative runtime file does not + * exist in the published package. Inline the resolved dependency version instead. */ const inlineLintStagedVersionPlugin = { name: 'inline-lint-staged-version', - transform(_code: string, id: string) { - const normalizedId = id.split('?')[0].replaceAll('\\', '/'); - - if (normalizedId.endsWith('/lint-staged/lib/version.js')) { - return { - code: `export const getVersion = async () => ${JSON.stringify(lintStagedPackageJson.version)};\n`, - map: null, - }; + resolveId(source: string, importer?: string) { + if ( + source === './version.js' && + importer?.replaceAll('\\', '/').endsWith('/lint-staged/lib/index.js') + ) { + return virtualLintStagedVersionId; + } + return undefined; + }, + load(id: string) { + if (id === virtualLintStagedVersionId) { + return [ + `const version = ${JSON.stringify(lintStagedPackageJson.version)};`, + 'export const getVersion = async () => version;', + '', + ].join('\n'); } - return undefined; }, }; From 19f82c1d5eebe136623faa1fbde2ec66585d6dc5 Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Wed, 24 Jun 2026 00:27:42 +0900 Subject: [PATCH 4/6] test(cli): drop trailing newline from staged snap fixture --- .../cli/snap-tests-global/command-staged-with-config/snap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt index 2dd9564b93..d1b55235df 100644 --- a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt +++ b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt @@ -24,4 +24,4 @@ > vp staged --debug > /dev/null 2>&1 # should succeed with debug enabled > git add -A && git commit -m 'third' > printf 'eval("code");\n' > src/fail.js && git add src/fail.js -[1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors +[1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors \ No newline at end of file From 7af675335ec824ce07f4a8a80721f43d6830a8dc Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Wed, 24 Jun 2026 00:31:20 +0900 Subject: [PATCH 5/6] refactor(cli): simplify lint-staged version inlining to a single load hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the resolveId + virtual-module indirection and replace lint-staged's lib/version.js directly in a single load hook. The ./version.js import is relative, so the bundler resolves it to the real file and the load hook short-circuits the read — no virtual id or importer matching needed. --- packages/cli/tsdown.config.ts | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts index a2c9d79540..944111ecdf 100644 --- a/packages/cli/tsdown.config.ts +++ b/packages/cli/tsdown.config.ts @@ -4,7 +4,6 @@ import { defineConfig } from 'tsdown'; const require = createRequire(import.meta.url); const lintStagedPackageJson = require('lint-staged/package.json') as { version: string }; -const virtualLintStagedVersionId = '\0vite-plus:lint-staged-version'; /** * Rewrite `../versions.js` → `./versions.js` at resolve time. @@ -25,28 +24,16 @@ const fixVersionsPathPlugin = { }; /** - * `lint-staged` reads `../package.json` from `lib/version.js` when debug logging is enabled. - * The CLI bundles lint-staged into `dist/staged/bin.js`, so that relative runtime file does not - * exist in the published package. Inline the resolved dependency version instead. + * Replace lint-staged's lib/version.js with a build-time version value. + * + * The original module reads ../package.json at runtime when debug logging is enabled, + * but that file does not exist in the bundled dist/staged/bin.js. */ const inlineLintStagedVersionPlugin = { name: 'inline-lint-staged-version', - resolveId(source: string, importer?: string) { - if ( - source === './version.js' && - importer?.replaceAll('\\', '/').endsWith('/lint-staged/lib/index.js') - ) { - return virtualLintStagedVersionId; - } - return undefined; - }, load(id: string) { - if (id === virtualLintStagedVersionId) { - return [ - `const version = ${JSON.stringify(lintStagedPackageJson.version)};`, - 'export const getVersion = async () => version;', - '', - ].join('\n'); + if (id.replaceAll('\\', '/').endsWith('/lint-staged/lib/version.js')) { + return `export const getVersion = async () => ${JSON.stringify(lintStagedPackageJson.version)};\n`; } return undefined; }, From 97cf33985300dcd91e5019eb82f3d9d4c042c1a0 Mon Sep 17 00:00:00 2001 From: Koki Matsumoto Date: Wed, 24 Jun 2026 09:28:59 +0900 Subject: [PATCH 6/6] test(cli): use ignoreOutput for staged debug snapshot step Switch the `vp staged --debug` step from `> /dev/null 2>&1` to `ignoreOutput: true`. The output is still suppressed on success, so the snapshot stays stable, but it is preserved on failure, making a regression easier to debug. --- .../snap-tests-global/command-staged-with-config/snap.txt | 2 +- .../snap-tests-global/command-staged-with-config/steps.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt index d1b55235df..0425facb67 100644 --- a/packages/cli/snap-tests-global/command-staged-with-config/snap.txt +++ b/packages/cli/snap-tests-global/command-staged-with-config/snap.txt @@ -21,7 +21,7 @@ > git add -A && git commit -m 'second' > echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts -> vp staged --debug > /dev/null 2>&1 # should succeed with debug enabled +> vp staged --debug # should succeed with debug enabled > git add -A && git commit -m 'third' > printf 'eval("code");\n' > src/fail.js && git add src/fail.js [1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors \ No newline at end of file diff --git a/packages/cli/snap-tests-global/command-staged-with-config/steps.json b/packages/cli/snap-tests-global/command-staged-with-config/steps.json index a5d0049765..9bddcda0a4 100644 --- a/packages/cli/snap-tests-global/command-staged-with-config/steps.json +++ b/packages/cli/snap-tests-global/command-staged-with-config/steps.json @@ -13,7 +13,10 @@ "command": "echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts", "ignoreOutput": true }, - "vp staged --debug > /dev/null 2>&1 # should succeed with debug enabled", + { + "command": "vp staged --debug # should succeed with debug enabled", + "ignoreOutput": true + }, { "command": "git add -A && git commit -m 'third'", "ignoreOutput": true }, { "command": "printf 'eval(\"code\");\\n' > src/fail.js && git add src/fail.js",