Skip to content

Commit 3dae3a3

Browse files
rokuosanfengmk2
andauthored
fix(cli): inline lint-staged version into staged debug bundle (#1925)
## Problem - #1922 `vp staged --debug` crashes in the published package. When debug logging is enabled, bundled `lint-staged` calls `getVersion()`(`lib/version.js`), which reads its own manifest via`readFile(new URL('../package.json', import.meta.url))`. The CLI bundleslint-staged into `dist/staged/bin.js`, so that relative `../package.json` does not exist at runtime and the command throws instead of printing the debug log. This is exactly what the pinned `lint-staged@16.4.0` does in `lib/version.js`: ```js import fs from 'node:fs/promises' export const getVersion = async () => { const packageJson = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url))) return packageJson.version } ``` Source: https://github.com/lint-staged/lint-staged/blob/445f9dd042b88528c798b2e25c21c9adbc69a732/lib/version.js#L1-L6 ## Fix Add a tsdown plugin (`inline-lint-staged-version`) that rewrites the `./version.js` import coming from `lint-staged/lib/index.js` to a virtual module exposing the dependency version resolved at build time: ```js export const getVersion = async () => "16.4.0"; ``` Keeps the `getVersion` named-export shape identical, so no lint-staged internals change. ## Tests - Extend the `command-staged-with-config` global snap test with a `vp staged --debug` step that must succeed. A regression flips the recorded exit code (`>` → `[1]>`), failing the snapshot. Verified against a real build: `dist/staged/bin.js` now contains the inlined `const version = "16.4.0"` and no longer references `readFile(new URL('../package.json', ...))`. ```bash vscode ➜ /workspaces/vite-plus (fix-debug-staged) $ vp staged --debug lint-staged: Running `lint-staged@16.4.0` on Node.js v22.18.0 (linux) +126ms lint-staged:execGit: Running git command: [ 'version', '--build-options' ] +128ms lint-staged: git version 2.51.1 cpu: aarch64 no commit associated with this build ``` --- closes: #1922 --------- Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
1 parent f1652fc commit 3dae3a3

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

packages/cli/snap-tests-global/command-staged-with-config/snap.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@
2020
[COMPLETED] Cleaning up temporary files...
2121

2222
> git add -A && git commit -m 'second'
23+
> echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts
24+
> vp staged --debug # should succeed with debug enabled
25+
> git add -A && git commit -m 'third'
2326
> printf 'eval("code");\n' > src/fail.js && git add src/fail.js
2427
[1]> vp staged > /dev/null 2>&1 # should fail when staged .js file has lint errors

packages/cli/snap-tests-global/command-staged-with-config/steps.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
},
1010
"vp staged # should succeed with staged .ts files",
1111
{ "command": "git add -A && git commit -m 'second'", "ignoreOutput": true },
12+
{
13+
"command": "echo 'export const bar = 2;' >> src/index.ts && git add src/index.ts",
14+
"ignoreOutput": true
15+
},
16+
{
17+
"command": "vp staged --debug # should succeed with debug enabled",
18+
"ignoreOutput": true
19+
},
20+
{ "command": "git add -A && git commit -m 'third'", "ignoreOutput": true },
1221
{
1322
"command": "printf 'eval(\"code\");\\n' > src/fail.js && git add src/fail.js",
1423
"ignoreOutput": true

packages/cli/tsdown.config.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
import { createRequire } from 'node:module';
2+
13
import { defineConfig } from 'tsdown';
24

5+
const require = createRequire(import.meta.url);
6+
const lintStagedPackageJson = require('lint-staged/package.json') as { version: string };
7+
38
/**
49
* Rewrite `../versions.js` → `./versions.js` at resolve time.
510
*
@@ -18,6 +23,22 @@ const fixVersionsPathPlugin = {
1823
},
1924
};
2025

26+
/**
27+
* Replace lint-staged's lib/version.js with a build-time version value.
28+
*
29+
* The original module reads ../package.json at runtime when debug logging is enabled,
30+
* but that file does not exist in the bundled dist/staged/bin.js.
31+
*/
32+
const inlineLintStagedVersionPlugin = {
33+
name: 'inline-lint-staged-version',
34+
load(id: string) {
35+
if (id.replaceAll('\\', '/').endsWith('/lint-staged/lib/version.js')) {
36+
return `export const getVersion = async () => ${JSON.stringify(lintStagedPackageJson.version)};\n`;
37+
}
38+
return undefined;
39+
},
40+
};
41+
2142
export default defineConfig([
2243
// ESM — all entry points bundled to dist/
2344
{
@@ -56,7 +77,7 @@ export default defineConfig([
5677
mainFields: ['module', 'main'],
5778
},
5879
},
59-
plugins: [fixVersionsPathPlugin],
80+
plugins: [fixVersionsPathPlugin, inlineLintStagedVersionPlugin],
6081
},
6182

6283
// CJS — dual-format entries

0 commit comments

Comments
 (0)