11import { 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' ;
311import os from 'node:os' ;
412import path from 'node:path' ;
513import { 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
112143set VITE_PLUS_HOME=${ installDir } \r
113- "%VITE_PLUS_HOME%\\current\\bin\\vp.exe " %*\r
144+ "%VITE_PLUS_HOME%\\current\\bin\\vp.cmd " %*\r
114145exit /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
121152export 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
131162export 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
146198export 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