Skip to content

Commit 45c45ce

Browse files
committed
feat(tools): wrap vp binary to ensure VITE_PLUS_HOME is set
In install-global-cli.ts: - Rename actual binary: vp -> vp-raw (Unix) / vp.exe -> vp-raw.exe (Windows) - Create wrapper at current/bin/vp that sets VITE_PLUS_HOME and calls vp-raw - Unix wrapper uses `exec -a "$0"` to preserve argv[0] for shim detection - Update vp-dev wrapper to call current/bin/vp (the wrapper) This ensures VITE_PLUS_HOME is consistently set when running `npm install -g` from within `vp env run npm` context in the development environment.
1 parent 11c5c3b commit 45c45ce

1 file changed

Lines changed: 61 additions & 8 deletions

File tree

packages/tools/src/install-global-cli.ts

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { execSync } from 'node:child_process';
2-
import { chmodSync, existsSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
2+
import {
3+
chmodSync,
4+
existsSync,
5+
mkdtempSync,
6+
readdirSync,
7+
renameSync,
8+
rmSync,
9+
writeFileSync,
10+
} from 'node:fs';
311
import os from 'node:os';
412
import path from 'node:path';
513
import { fileURLToPath } from 'node:url';
@@ -98,19 +106,42 @@ export function installGlobalCli() {
98106

99107
// Create wrapper scripts
100108
const binDir = path.join(installDir, 'bin');
109+
const currentBinDir = path.join(installDir, 'current', 'bin');
101110

111+
// Rename the actual vp binary to vp-raw, then create a wrapper at vp
112+
// This ensures VITE_PLUS_HOME is always set when vp is invoked (including via shims)
113+
// The wrapper uses `exec -a "$0"` to preserve argv[0] for shim detection
102114
if (isWindows) {
115+
const vpExe = path.join(currentBinDir, 'vp.exe');
116+
const vpRawExe = path.join(currentBinDir, 'vp-raw.exe');
117+
118+
// Rename vp.exe -> vp-raw.exe
119+
if (existsSync(vpExe) && !existsSync(vpRawExe)) {
120+
renameSync(vpExe, vpRawExe);
121+
console.log(`Renamed ${vpExe} -> ${vpRawExe}`);
122+
}
123+
124+
// Create vp.cmd wrapper in current/bin/ that sets VITE_PLUS_HOME and calls vp-raw.exe
125+
const vpWrapperPath = path.join(currentBinDir, 'vp.cmd');
126+
const vpWrapperContent = `@echo off\r
127+
set VITE_PLUS_HOME=${installDir}\r
128+
"%~dp0vp-raw.exe" %*\r
129+
exit /b %ERRORLEVEL%\r
130+
`;
131+
writeFileSync(vpWrapperPath, vpWrapperContent);
132+
console.log(`Created wrapper: ${vpWrapperPath}`);
133+
103134
// On Windows, create bash script wrappers for Git Bash compatibility
104135
// (Git Bash doesn't execute .cmd files automatically)
105136
if (binName === 'vp-dev') {
106-
// Remove the vp.cmd to avoid confusion
137+
// Remove the vp.cmd in bin/ to avoid confusion
107138
rmSync(path.join(binDir, 'vp.cmd'), { force: true });
108139

109140
// Create vp-dev.cmd for cmd.exe/PowerShell
110141
const cmdPath = path.join(binDir, 'vp-dev.cmd');
111142
const cmdContent = `@echo off\r
112143
set VITE_PLUS_HOME=${installDir}\r
113-
"%VITE_PLUS_HOME%\\current\\bin\\vp.exe" %*\r
144+
"%VITE_PLUS_HOME%\\current\\bin\\vp.cmd" %*\r
114145
exit /b %ERRORLEVEL%\r
115146
`;
116147
writeFileSync(cmdPath, cmdContent);
@@ -119,28 +150,49 @@ exit /b %ERRORLEVEL%\r
119150
const bashPath = path.join(binDir, 'vp-dev');
120151
const bashContent = `#!/bin/bash
121152
export VITE_PLUS_HOME="${installDir}"
122-
exec "$VITE_PLUS_HOME/current/bin/vp.exe" "$@"
153+
exec "$VITE_PLUS_HOME/current/bin/vp.cmd" "$@"
123154
`;
124155
writeFileSync(bashPath, bashContent);
125156
console.log(`\nCreated wrapper scripts: ${cmdPath}, ${bashPath}`);
126157
} else {
127158
// For 'vp', create bash script wrapper for Git Bash
128-
// (install.ps1 already creates vp.cmd for cmd.exe/PowerShell)
159+
// (install.ps1 already creates vp.cmd for cmd.exe/PowerShell, but we need to update it)
129160
const bashPath = path.join(binDir, 'vp');
130161
const bashContent = `#!/bin/bash
131162
export VITE_PLUS_HOME="${installDir}"
132-
exec "$VITE_PLUS_HOME/current/bin/vp.exe" "$@"
163+
exec "$VITE_PLUS_HOME/current/bin/vp.cmd" "$@"
133164
`;
134165
writeFileSync(bashPath, bashContent);
135166
console.log(`\nCreated bash wrapper: ${bashPath}`);
136167
}
137168
} else {
169+
// Unix: Rename vp -> vp-raw, create wrapper
170+
const vpBinary = path.join(currentBinDir, 'vp');
171+
const vpRawBinary = path.join(currentBinDir, 'vp-raw');
172+
173+
// Rename vp -> vp-raw
174+
if (existsSync(vpBinary) && !existsSync(vpRawBinary)) {
175+
renameSync(vpBinary, vpRawBinary);
176+
console.log(`Renamed ${vpBinary} -> ${vpRawBinary}`);
177+
}
178+
179+
// Create vp wrapper in current/bin/ that sets VITE_PLUS_HOME and calls vp-raw
180+
// Uses `exec -a "$0"` to preserve argv[0] for shim detection (node, npm, npx)
181+
const vpWrapperPath = path.join(currentBinDir, 'vp');
182+
const vpWrapperContent = `#!/bin/bash
183+
export VITE_PLUS_HOME="${installDir}"
184+
exec -a "$0" "$VITE_PLUS_HOME/current/bin/vp-raw" "$@"
185+
`;
186+
writeFileSync(vpWrapperPath, vpWrapperContent);
187+
chmodSync(vpWrapperPath, 0o755);
188+
console.log(`Created wrapper: ${vpWrapperPath}`);
189+
138190
// On Unix, create shell script wrappers
139191
if (binName === 'vp-dev') {
140192
// Remove the vp symlink to avoid confusion
141193
rmSync(path.join(binDir, 'vp'), { force: true });
142194

143-
// Create vp-dev wrapper that points directly to the binary
195+
// Create vp-dev wrapper that points to current/bin/vp (the wrapper)
144196
const wrapperPath = path.join(binDir, 'vp-dev');
145197
const wrapperContent = `#!/bin/bash
146198
export VITE_PLUS_HOME="${installDir}"
@@ -150,7 +202,8 @@ exec "$VITE_PLUS_HOME/current/bin/vp" "$@"
150202
chmodSync(wrapperPath, 0o755);
151203
console.log(`\nCreated wrapper script: ${wrapperPath}`);
152204
}
153-
// For 'vp' on Unix, install.sh already creates the symlink
205+
// For 'vp' on Unix, install.sh already creates the symlink to ../current/bin/vp
206+
// which now points to the wrapper script (which calls vp-raw)
154207
}
155208
} finally {
156209
// Cleanup temp dir only if we created it

0 commit comments

Comments
 (0)