diff --git a/crates/vite_global_cli/src/cli.rs b/crates/vite_global_cli/src/cli.rs index a365261e32..932fe8a3da 100644 --- a/crates/vite_global_cli/src/cli.rs +++ b/crates/vite_global_cli/src/cli.rs @@ -650,10 +650,10 @@ Examples: vp env use lts # Use latest LTS for this shell session vp env use # Use project version for this shell session vp env use --unset # Remove session override - vp env run --node 20 node -v # Run 'node -v' with Node.js 20 - vp env run --node lts npm i # Run 'npm i' with latest LTS - vp env run node -v # Shim mode (version auto-resolved) - vp env run npm install # Shim mode (version auto-resolved) + vp env exec --node 20 node -v # Execute 'node -v' with Node.js 20 + vp env exec --node lts npm i # Execute 'npm i' with latest LTS + vp env exec node -v # Shim mode (version auto-resolved) + vp env exec npm install # Shim mode (version auto-resolved) Global Packages: vp install -g # Install a global package @@ -766,8 +766,9 @@ pub enum EnvSubcommands { sort: SortingMethod, }, - /// Run a command with a specific Node.js version - Run { + /// Execute a command with a specific Node.js version + #[command(visible_alias = "run")] + Exec { /// Node.js version to use (e.g., "20.18.0", "lts", "^20.0.0") /// If not provided and command is node/npm/npx or a global package binary, /// version is resolved automatically (same as shim behavior) diff --git a/crates/vite_global_cli/src/commands/env/run.rs b/crates/vite_global_cli/src/commands/env/exec.rs similarity index 90% rename from crates/vite_global_cli/src/commands/env/run.rs rename to crates/vite_global_cli/src/commands/env/exec.rs index 80c40fa2bc..bc4c69cd35 100644 --- a/crates/vite_global_cli/src/commands/env/run.rs +++ b/crates/vite_global_cli/src/commands/env/exec.rs @@ -1,8 +1,8 @@ -//! Run command for executing commands with a specific Node.js version. +//! Exec command for executing commands with a specific Node.js version. //! //! Handles two modes: -//! 1. Explicit version: `vp env run --node [--npm ] ` -//! 2. Shim mode: `vp env run [args...]` where tool is node/npm/npx or a global package binary +//! 1. Explicit version: `vp env exec --node [--npm ] ` +//! 2. Shim mode: `vp env exec [args...]` where tool is node/npm/npx or a global package binary //! //! The shim mode uses the same dispatch logic as Unix symlinks, ensuring identical behavior //! across platforms (used by Windows .cmd wrappers and Git Bash shell scripts). @@ -17,7 +17,7 @@ use crate::{ shim::{dispatch as shim_dispatch, is_shim_tool}, }; -/// Execute the run command. +/// Execute the exec command. /// /// When `--node` is provided, runs a command with the specified Node.js version. /// When `--node` is not provided and the command is a shim tool (node/npm/npx or global package), @@ -28,8 +28,8 @@ pub async fn execute( command: &[String], ) -> Result { if command.is_empty() { - eprintln!("vp env run: missing command to execute"); - eprintln!("Usage: vp env run [--node ] [args...]"); + eprintln!("vp env exec: missing command to execute"); + eprintln!("Usage: vp env exec [--node ] [args...]"); return Ok(exit_status(1)); } @@ -45,7 +45,7 @@ pub async fn execute( let tool = &command[0]; if is_shim_tool(tool) { // Clear recursion env var to force fresh version resolution. - // This is needed because `vp env run` may be invoked from within a context + // This is needed because `vp env exec` may be invoked from within a context // where VITE_PLUS_TOOL_RECURSION is already set (e.g., when pnpm runs through // the vite-plus shim). Without clearing it, shim_dispatch would passthrough // to the system node instead of resolving the version. @@ -67,13 +67,13 @@ pub async fn execute( } // Not a shim tool and no --node - error - eprintln!("vp env run: --node is required when running non-shim commands"); - eprintln!("Usage: vp env run --node [args...]"); + eprintln!("vp env exec: --node is required when running non-shim commands"); + eprintln!("Usage: vp env exec --node [args...]"); eprintln!(); eprintln!("For shim tools, --node is optional (version resolved automatically):"); - eprintln!(" vp env run node script.js # Core tool"); - eprintln!(" vp env run npm install # Core tool"); - eprintln!(" vp env run tsc --version # Global package"); + eprintln!(" vp env exec node script.js # Core tool"); + eprintln!(" vp env exec npm install # Core tool"); + eprintln!(" vp env exec tsc --version # Global package"); Ok(exit_status(1)) } diff --git a/crates/vite_global_cli/src/commands/env/global_install.rs b/crates/vite_global_cli/src/commands/env/global_install.rs index 9c4f73dc7d..79a51bb393 100644 --- a/crates/vite_global_cli/src/commands/env/global_install.rs +++ b/crates/vite_global_cli/src/commands/env/global_install.rs @@ -364,7 +364,7 @@ const CORE_SHIMS: &[&str] = &["node", "npm", "npx", "vp"]; /// Create a shim for a package binary. /// /// On Unix: Creates a symlink to ../current/bin/vp -/// On Windows: Creates a .cmd wrapper that calls `vp env run ` +/// On Windows: Creates a .cmd wrapper that calls `vp env exec ` async fn create_package_shim( bin_dir: &vite_path::AbsolutePath, bin_name: &str, @@ -405,24 +405,24 @@ async fn create_package_shim( return Ok(()); } - // Create .cmd wrapper that calls vp env run + // Create .cmd wrapper that calls vp env exec // Set VITE_PLUS_HOME using %~dp0.. which resolves to the parent of bin/ // This ensures the vp binary knows its home directory let wrapper_content = format!( - "@echo off\r\nset VITE_PLUS_HOME=%~dp0..\r\n\"%VITE_PLUS_HOME%\\current\\bin\\vp.exe\" env run {} %*\r\nexit /b %ERRORLEVEL%\r\n", + "@echo off\r\nset VITE_PLUS_HOME=%~dp0..\r\n\"%VITE_PLUS_HOME%\\current\\bin\\vp.exe\" env exec {} %*\r\nexit /b %ERRORLEVEL%\r\n", bin_name ); tokio::fs::write(&cmd_path, wrapper_content).await?; // Also create shell script for Git Bash (bin_name without extension) - // Uses explicit "vp env run " instead of symlink+argv[0] because + // Uses explicit "vp env exec " instead of symlink+argv[0] because // Windows symlinks require admin privileges let sh_path = bin_dir.join(bin_name); let sh_content = format!( r#"#!/bin/sh VITE_PLUS_HOME="$(dirname "$(dirname "$(readlink -f "$0" 2>/dev/null || echo "$0")")")" export VITE_PLUS_HOME -exec "$VITE_PLUS_HOME/current/bin/vp.exe" env run {} "$@" +exec "$VITE_PLUS_HOME/current/bin/vp.exe" env exec {} "$@" "#, bin_name ); diff --git a/crates/vite_global_cli/src/commands/env/mod.rs b/crates/vite_global_cli/src/commands/env/mod.rs index 3c1cf35397..a3bdc08e31 100644 --- a/crates/vite_global_cli/src/commands/env/mod.rs +++ b/crates/vite_global_cli/src/commands/env/mod.rs @@ -8,6 +8,7 @@ pub mod config; mod current; mod default; mod doctor; +mod exec; pub mod global_install; mod list; mod list_remote; @@ -16,7 +17,6 @@ mod on; pub mod package_metadata; pub mod packages; mod pin; -mod run; mod setup; mod unpin; mod r#use; @@ -49,8 +49,8 @@ pub async fn execute(cwd: AbsolutePathBuf, args: EnvArgs) -> Result { list_remote::execute(pattern, lts, all, json, sort).await } - crate::cli::EnvSubcommands::Run { node, npm, command } => { - run::execute(node.as_deref(), npm.as_deref(), &command).await + crate::cli::EnvSubcommands::Exec { node, npm, command } => { + exec::execute(node.as_deref(), npm.as_deref(), &command).await } crate::cli::EnvSubcommands::Uninstall { version } => { let provider = vite_js_runtime::NodeProvider::new(); diff --git a/crates/vite_global_cli/src/commands/env/setup.rs b/crates/vite_global_cli/src/commands/env/setup.rs index da2734dae4..1f9f69f3f5 100644 --- a/crates/vite_global_cli/src/commands/env/setup.rs +++ b/crates/vite_global_cli/src/commands/env/setup.rs @@ -11,7 +11,7 @@ //! //! On Windows: //! - bin/vp.cmd is a wrapper script that calls ..\current\bin\vp.exe -//! - bin/node.cmd, bin/npm.cmd, bin/npx.cmd are wrappers calling `vp env run ` +//! - bin/node.cmd, bin/npm.cmd, bin/npx.cmd are wrappers calling `vp env exec ` use std::process::ExitStatus; @@ -220,9 +220,9 @@ async fn create_unix_shim( Ok(()) } -/// Create Windows shims using .cmd wrappers that call `vp env run `. +/// Create Windows shims using .cmd wrappers that call `vp env exec `. /// -/// All tools (node, npm, npx) get .cmd wrappers that invoke `vp env run`. +/// All tools (node, npm, npx) get .cmd wrappers that invoke `vp env exec`. /// Also creates shell scripts (without extension) for Git Bash compatibility. /// This is consistent with Volta's Windows approach. #[cfg(windows)] @@ -233,26 +233,26 @@ async fn create_windows_shim( ) -> Result<(), Error> { let cmd_path = bin_dir.join(format!("{tool}.cmd")); - // Create .cmd wrapper that calls vp env run + // Create .cmd wrapper that calls vp env exec // Use a for loop to canonicalize VITE_PLUS_HOME path. // %~dp0.. would produce paths like C:\Users\x\.vite-plus\bin\.. // The for loop resolves this to a clean C:\Users\x\.vite-plus let cmd_content = format!( - "@echo off\r\nfor %%I in (\"%~dp0..\") do set VITE_PLUS_HOME=%%~fI\r\n\"%VITE_PLUS_HOME%\\current\\bin\\vp.exe\" env run {} %*\r\nexit /b %ERRORLEVEL%\r\n", + "@echo off\r\nfor %%I in (\"%~dp0..\") do set VITE_PLUS_HOME=%%~fI\r\n\"%VITE_PLUS_HOME%\\current\\bin\\vp.exe\" env exec {} %*\r\nexit /b %ERRORLEVEL%\r\n", tool ); tokio::fs::write(&cmd_path, cmd_content).await?; // Also create shell script for Git Bash (tool without extension) - // Uses explicit "vp env run " instead of symlink+argv[0] because + // Uses explicit "vp env exec " instead of symlink+argv[0] because // Windows symlinks require admin privileges let sh_path = bin_dir.join(tool); let sh_content = format!( r#"#!/bin/sh VITE_PLUS_HOME="$(dirname "$(dirname "$(readlink -f "$0" 2>/dev/null || echo "$0")")")" export VITE_PLUS_HOME -exec "$VITE_PLUS_HOME/current/bin/vp.exe" env run {} "$@" +exec "$VITE_PLUS_HOME/current/bin/vp.exe" env exec {} "$@" "#, tool ); diff --git a/crates/vite_global_cli/src/shim/mod.rs b/crates/vite_global_cli/src/shim/mod.rs index 3503d794fa..ea55fea19c 100644 --- a/crates/vite_global_cli/src/shim/mod.rs +++ b/crates/vite_global_cli/src/shim/mod.rs @@ -5,7 +5,7 @@ //! //! Detection methods: //! - Unix: Symlinks to vp binary preserve argv[0], allowing tool detection -//! - Windows: .cmd wrappers call `vp env run ` directly +//! - Windows: .cmd wrappers call `vp env exec ` directly //! - Legacy: VITE_PLUS_SHIM_TOOL env var (kept for backward compatibility) mod cache; @@ -92,7 +92,7 @@ const SHIM_TOOL_ENV_VAR: &str = "VITE_PLUS_SHIM_TOOL"; /// 2. Check `VITE_PLUS_SHIM_TOOL` env var (for shell wrapper scripts) /// 3. Fall back to argv[0] detection (primary method on Unix with symlinks) /// -/// Note: Modern Windows wrappers use `vp env run ` instead of env vars. +/// Note: Modern Windows wrappers use `vp env exec ` instead of env vars. /// /// IMPORTANT: This function clears `VITE_PLUS_SHIM_TOOL` after reading it to /// prevent the env var from leaking to child processes. diff --git a/packages/global/snap-tests/cli-helper-message/snap.txt b/packages/global/snap-tests/cli-helper-message/snap.txt index 24a76a1530..1c5693821f 100644 --- a/packages/global/snap-tests/cli-helper-message/snap.txt +++ b/packages/global/snap-tests/cli-helper-message/snap.txt @@ -295,7 +295,7 @@ Commands: unpin Remove the .node-version file from current directory (alias for `pin --unpin`) list List locally installed Node.js versions [aliases: ls] list-remote List available Node.js versions from the registry [aliases: ls-remote] - run Run a command with a specific Node.js version + exec Execute a command with a specific Node.js version [aliases: run] uninstall Uninstall a Node.js version [aliases: uni] install Install a Node.js version [aliases: i] use Use a specific Node.js version for this shell session @@ -329,10 +329,10 @@ Examples: vp env use lts # Use latest LTS for this shell session vp env use # Use project version for this shell session vp env use --unset # Remove session override - vp env run --node 20 node -v # Run 'node -v' with Node.js 20 - vp env run --node lts npm i # Run 'npm i' with latest LTS - vp env run node -v # Shim mode (version auto-resolved) - vp env run npm install # Shim mode (version auto-resolved) + vp env exec --node 20 node -v # Execute 'node -v' with Node.js 20 + vp env exec --node lts npm i # Execute 'npm i' with latest LTS + vp env exec node -v # Shim mode (version auto-resolved) + vp env exec npm install # Shim mode (version auto-resolved) Global Packages: vp install -g # Install a global package diff --git a/packages/global/snap-tests/command-env-run-shim-mode/package.json b/packages/global/snap-tests/command-env-exec-shim-mode/package.json similarity index 68% rename from packages/global/snap-tests/command-env-run-shim-mode/package.json rename to packages/global/snap-tests/command-env-exec-shim-mode/package.json index 01daa978c1..638867a99c 100644 --- a/packages/global/snap-tests/command-env-run-shim-mode/package.json +++ b/packages/global/snap-tests/command-env-exec-shim-mode/package.json @@ -1,5 +1,5 @@ { - "name": "command-env-run-shim-mode", + "name": "command-env-exec-shim-mode", "version": "1.0.0", "private": true, "engines": { diff --git a/packages/global/snap-tests/command-env-exec-shim-mode/snap.txt b/packages/global/snap-tests/command-env-exec-shim-mode/snap.txt new file mode 100644 index 0000000000..a0343bb01c --- /dev/null +++ b/packages/global/snap-tests/command-env-exec-shim-mode/snap.txt @@ -0,0 +1,18 @@ +> vp env exec node -v # Shim mode: version resolved from package.json engines.node +v20.18.0 + +> vp env exec npm -v # Shim mode: npm uses same version +10.8.2 + +> vp env exec node -e "console.log('Hello from shim mode')" # Shim mode: run inline script +Hello from shim mode + +> vp env exec nonexistent-tool --version || echo 'Expected error: non-shim command requires --node' # Error: non-shim tool +vp env exec: --node is required when running non-shim commands +Usage: vp env exec --node [args...] + +For shim tools, --node is optional (version resolved automatically): + vp env exec node script.js # Core tool + vp env exec npm install # Core tool + vp env exec tsc --version # Global package +Expected error: non-shim command requires --node diff --git a/packages/global/snap-tests/command-env-exec-shim-mode/steps.json b/packages/global/snap-tests/command-env-exec-shim-mode/steps.json new file mode 100644 index 0000000000..26aa616dda --- /dev/null +++ b/packages/global/snap-tests/command-env-exec-shim-mode/steps.json @@ -0,0 +1,10 @@ +{ + "env": {}, + "ignoredPlatforms": [], + "commands": [ + "vp env exec node -v # Shim mode: version resolved from package.json engines.node", + "vp env exec npm -v # Shim mode: npm uses same version", + "vp env exec node -e \"console.log('Hello from shim mode')\" # Shim mode: run inline script", + "vp env exec nonexistent-tool --version || echo 'Expected error: non-shim command requires --node' # Error: non-shim tool" + ] +} diff --git a/packages/global/snap-tests/command-env-run/package.json b/packages/global/snap-tests/command-env-exec/package.json similarity index 59% rename from packages/global/snap-tests/command-env-run/package.json rename to packages/global/snap-tests/command-env-exec/package.json index 1f55f590ed..8bd8344c78 100644 --- a/packages/global/snap-tests/command-env-run/package.json +++ b/packages/global/snap-tests/command-env-exec/package.json @@ -1,5 +1,5 @@ { - "name": "command-env-run", + "name": "command-env-exec", "version": "1.0.0", "private": true } diff --git a/packages/global/snap-tests/command-env-exec/snap.txt b/packages/global/snap-tests/command-env-exec/snap.txt new file mode 100644 index 0000000000..fd72947da8 --- /dev/null +++ b/packages/global/snap-tests/command-env-exec/snap.txt @@ -0,0 +1,5 @@ +> vp env exec --node 20.19 node -v # Run node with specific major version +v20.19.6 + +> vp env exec --node 20.19 node -e "console.log('Hello from Node ' + process.version)" # Run inline script +Hello from Node v diff --git a/packages/global/snap-tests/command-env-exec/steps.json b/packages/global/snap-tests/command-env-exec/steps.json new file mode 100644 index 0000000000..4ada2b80b4 --- /dev/null +++ b/packages/global/snap-tests/command-env-exec/steps.json @@ -0,0 +1,8 @@ +{ + "env": {}, + "ignoredPlatforms": [], + "commands": [ + "vp env exec --node 20.19 node -v # Run node with specific major version", + "vp env exec --node 20.19 node -e \"console.log('Hello from Node ' + process.version)\" # Run inline script" + ] +} diff --git a/packages/global/snap-tests/command-env-run-shim-mode/snap.txt b/packages/global/snap-tests/command-env-run-shim-mode/snap.txt deleted file mode 100644 index 36e294d5b9..0000000000 --- a/packages/global/snap-tests/command-env-run-shim-mode/snap.txt +++ /dev/null @@ -1,18 +0,0 @@ -> vp env run node -v # Shim mode: version resolved from package.json engines.node -v20.18.0 - -> vp env run npm -v # Shim mode: npm uses same version -10.8.2 - -> vp env run node -e "console.log('Hello from shim mode')" # Shim mode: run inline script -Hello from shim mode - -> vp env run nonexistent-tool --version || echo 'Expected error: non-shim command requires --node' # Error: non-shim tool -vp env run: --node is required when running non-shim commands -Usage: vp env run --node [args...] - -For shim tools, --node is optional (version resolved automatically): - vp env run node script.js # Core tool - vp env run npm install # Core tool - vp env run tsc --version # Global package -Expected error: non-shim command requires --node diff --git a/packages/global/snap-tests/command-env-run-shim-mode/steps.json b/packages/global/snap-tests/command-env-run-shim-mode/steps.json deleted file mode 100644 index a3ffec1485..0000000000 --- a/packages/global/snap-tests/command-env-run-shim-mode/steps.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "env": {}, - "ignoredPlatforms": [], - "commands": [ - "vp env run node -v # Shim mode: version resolved from package.json engines.node", - "vp env run npm -v # Shim mode: npm uses same version", - "vp env run node -e \"console.log('Hello from shim mode')\" # Shim mode: run inline script", - "vp env run nonexistent-tool --version || echo 'Expected error: non-shim command requires --node' # Error: non-shim tool" - ] -} diff --git a/packages/global/snap-tests/command-env-run/snap.txt b/packages/global/snap-tests/command-env-run/snap.txt deleted file mode 100644 index 8ba2685fee..0000000000 --- a/packages/global/snap-tests/command-env-run/snap.txt +++ /dev/null @@ -1,5 +0,0 @@ -> vp env run --node 20.19 node -v # Run node with specific major version -v20.19.6 - -> vp env run --node 20.19 node -e "console.log('Hello from Node ' + process.version)" # Run inline script -Hello from Node v diff --git a/packages/global/snap-tests/command-env-run/steps.json b/packages/global/snap-tests/command-env-run/steps.json deleted file mode 100644 index 418b31d7a2..0000000000 --- a/packages/global/snap-tests/command-env-run/steps.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "env": {}, - "ignoredPlatforms": [], - "commands": [ - "vp env run --node 20.19 node -v # Run node with specific major version", - "vp env run --node 20.19 node -e \"console.log('Hello from Node ' + process.version)\" # Run inline script" - ] -} diff --git a/packages/global/snap-tests/command-env-which/snap.txt b/packages/global/snap-tests/command-env-which/snap.txt index 4e79846d11..59a47540ce 100644 --- a/packages/global/snap-tests/command-env-which/snap.txt +++ b/packages/global/snap-tests/command-env-which/snap.txt @@ -1,4 +1,4 @@ -> vp env run node --version # Ensure Node.js is installed first +> vp env exec node --version # Ensure Node.js is installed first v20.18.0 > vp env which node # Core tool - shows resolved Node.js binary path diff --git a/packages/global/snap-tests/command-env-which/steps.json b/packages/global/snap-tests/command-env-which/steps.json index 9a54a8eee9..293ffd7b18 100644 --- a/packages/global/snap-tests/command-env-which/steps.json +++ b/packages/global/snap-tests/command-env-which/steps.json @@ -2,7 +2,7 @@ "env": {}, "ignoredPlatforms": ["win32"], "commands": [ - "vp env run node --version # Ensure Node.js is installed first", + "vp env exec node --version # Ensure Node.js is installed first", "vp env which node # Core tool - shows resolved Node.js binary path", "vp env which npm # Core tool - shows resolved npm binary path", "vp env which npx # Core tool - shows resolved npx binary path", diff --git a/packages/global/snap-tests/command-run-without-vite-plus/steps.json b/packages/global/snap-tests/command-run-without-vite-plus/steps.json index 577c449d9c..ac1d07f1cc 100644 --- a/packages/global/snap-tests/command-run-without-vite-plus/steps.json +++ b/packages/global/snap-tests/command-run-without-vite-plus/steps.json @@ -2,6 +2,7 @@ "env": { "VITE_DISABLE_AUTO_INSTALL": "1" }, + "ignoredPlatforms": ["win32"], "commands": [ "vp run hello # should fall back to pnpm run when no vite-plus dependency", "vp run greet --arg1 value1 # should pass through args to pnpm run", diff --git a/rfcs/env-command.md b/rfcs/env-command.md index f95b1d231e..b27fe02bd7 100644 --- a/rfcs/env-command.md +++ b/rfcs/env-command.md @@ -347,11 +347,11 @@ VITE_PLUS_HOME/ # Default: ~/.vite-plus │ ├── vp # Shell script for Git Bash (Windows) │ ├── vp.cmd # Wrapper calling ..\current\bin\vp.exe (Windows) │ ├── node # Shell script for Git Bash (Windows) -│ ├── node.cmd # Wrapper calling vp env run node (Windows) +│ ├── node.cmd # Wrapper calling vp env exec node (Windows) │ ├── npm # Shell script for Git Bash (Windows) -│ ├── npm.cmd # Wrapper calling vp env run npm (Windows) +│ ├── npm.cmd # Wrapper calling vp env exec npm (Windows) │ ├── npx # Shell script for Git Bash (Windows) -│ ├── npx.cmd # Wrapper calling vp env run npx (Windows) +│ ├── npx.cmd # Wrapper calling vp env exec npx (Windows) │ ├── tsc # Shell script for global package Git Bash (Windows) │ └── tsc.cmd # Wrapper for global package (Windows) ├── current/ @@ -648,7 +648,7 @@ To prevent infinite loops when shims invoke other shims, vite-plus uses environm 1. When a shim executes the real binary, it sets `VITE_PLUS_TOOL_RECURSION=1` 2. Subsequent shim invocations check this variable 3. If set, shims use **passthrough mode** (skip version resolution, use current PATH) -4. `vp env run` explicitly **removes** this variable to force re-evaluation +4. `vp env exec` explicitly **removes** this variable to force re-evaluation **Environment Variable**: `VITE_PLUS_BYPASS` (PATH-style list) @@ -660,7 +660,7 @@ When multiple vite-plus installations exist in PATH and `system_first` mode is a 2. The next installation sees `VITE_PLUS_BYPASS` is set and enters bypass mode via `find_system_tool()` 3. `find_system_tool()` filters all directories listed in `VITE_PLUS_BYPASS` (plus its own bin dir) from PATH 4. This ensures the search skips all known vite-plus bin directories and finds the real system binary (or errors cleanly) -5. `VITE_PLUS_BYPASS` is preserved through `vp env run` so loop protection remains active +5. `VITE_PLUS_BYPASS` is preserved through `vp env exec` so loop protection remains active **Flow Diagram:** @@ -706,7 +706,7 @@ fn execute_run_command() { **Why This Matters:** - Prevents infinite loops when Node scripts spawn other Node processes -- Allows `vp env run` to override versions mid-execution +- Allows `vp env exec` to override versions mid-execution - Ensures consistent behavior in complex process trees ## Design Decisions @@ -736,15 +736,15 @@ fn execute_run_command() { ### 3. Wrapper Scripts for Windows -**Decision**: Use `.cmd` wrapper scripts on Windows that call `vp env run `. +**Decision**: Use `.cmd` wrapper scripts on Windows that call `vp env exec `. **Rationale**: - Windows PATH resolution prefers `.cmd` over `.exe` for extensionless commands -- Simple wrapper format: `vp env run npm %*` - no binary copies needed +- Simple wrapper format: `vp env exec npm %*` - no binary copies needed - Same pattern as Volta (`volta run `) - Single `vp.exe` binary to maintain in `current/bin/` -- No `VITE_PLUS_SHIM_TOOL` env var complexity - dispatch via `vp env run` command +- No `VITE_PLUS_SHIM_TOOL` env var complexity - dispatch via `vp env exec` command ### 4. execve on Unix, spawn on Windows @@ -1687,9 +1687,9 @@ Binary execution uses per-binary config for deterministic lookup: This eliminates the non-deterministic behavior of filesystem iteration order. -## Run Command +## Exec Command -The `vp env run` command executes a command with a specific Node.js version. It operates in two modes: +The `vp env exec` command executes a command with a specific Node.js version. It operates in two modes: 1. **Explicit version mode**: When `--node` is provided, runs with the specified version 2. **Shim mode**: When `--node` is not provided and the command is a shim tool (node/npm/npx or global package), uses the same version resolution as Unix symlinks @@ -1699,34 +1699,34 @@ This is useful for: - Testing code against different Node versions - Running one-off commands without changing project configuration - CI/CD scripts that need explicit version control -- Windows shims (`.cmd` wrappers and Git Bash shell scripts call `vp env run `) +- Windows shims (`.cmd` wrappers and Git Bash shell scripts call `vp env exec `) ### Usage ```bash # Shim mode: version resolved automatically (same as Unix symlinks) -vp env run node --version # Core tool - resolves from .node-version/package.json -vp env run npm install # Core tool -vp env run npx vitest # Core tool -vp env run tsc --version # Global package - uses Node.js from install time +vp env exec node --version # Core tool - resolves from .node-version/package.json +vp env exec npm install # Core tool +vp env exec npx vitest # Core tool +vp env exec tsc --version # Global package - uses Node.js from install time # Explicit version mode: run with specific Node version -vp env run --node 20.18.0 node app.js +vp env exec --node 20.18.0 node app.js # Run with specific Node and npm versions -vp env run --node 22.13.0 --npm 10.8.0 npm install +vp env exec --node 22.13.0 --npm 10.8.0 npm install # Version can be semver range (resolved at runtime) -vp env run --node "^20.0.0" node -v +vp env exec --node "^20.0.0" node -v # Run npm scripts -vp env run --node 18.20.0 npm test +vp env exec --node 18.20.0 npm test # Pass arguments to the command -vp env run --node 20 -- node --inspect app.js +vp env exec --node 20 -- node --inspect app.js # Error: non-shim command without --node -vp env run python --version # Fails: --node required for non-shim tools +vp env exec python --version # Fails: --node required for non-shim tools ``` ### Flags @@ -1760,21 +1760,21 @@ When `--node` **is provided**: ```bash # Shim mode: same behavior as Unix symlinks -vp env run node -v # Uses version from project config -vp env run npm install # Uses same version -vp env run tsc --version # Global package +vp env exec node -v # Uses version from project config +vp env exec npm install # Uses same version +vp env exec tsc --version # Global package # Test against multiple Node versions in CI for version in 18 20 22; do - vp env run --node $version npm test + vp env exec --node $version npm test done # Run with exact version -vp env run --node 20.18.0 node -e "console.log(process.version)" +vp env exec --node 20.18.0 node -e "console.log(process.version)" # Output: v20.18.0 # Debug with specific Node version -vp env run --node 22 -- node --inspect-brk app.js +vp env exec --node 22 -- node --inspect-brk app.js ``` ### Use in Scripts @@ -1787,7 +1787,7 @@ VERSIONS="18.20.0 20.18.0 22.13.0" for v in $VERSIONS; do echo "Testing with Node $v..." - vp env run --node "$v" npm test || exit 1 + vp env exec --node "$v" npm test || exit 1 done echo "All tests passed!" @@ -1971,12 +1971,12 @@ VITE_PLUS_HOME\ ├── bin\ │ ├── vp # Shell script for Git Bash (calls vp.exe directly) │ ├── vp.cmd # Wrapper for cmd.exe/PowerShell -│ ├── node # Shell script for Git Bash (calls vp env run node) -│ ├── node.cmd # Wrapper calling vp env run node -│ ├── npm # Shell script for Git Bash (calls vp env run npm) -│ ├── npm.cmd # Wrapper calling vp env run npm -│ ├── npx # Shell script for Git Bash (calls vp env run npx) -│ ├── npx.cmd # Wrapper calling vp env run npx +│ ├── node # Shell script for Git Bash (calls vp env exec node) +│ ├── node.cmd # Wrapper calling vp env exec node +│ ├── npm # Shell script for Git Bash (calls vp env exec npm) +│ ├── npm.cmd # Wrapper calling vp env exec npm +│ ├── npx # Shell script for Git Bash (calls vp env exec npx) +│ ├── npx.cmd # Wrapper calling vp env exec npx │ ├── tsc # Shell script for global package (Git Bash) │ └── tsc.cmd # Wrapper for global package (cmd.exe/PowerShell) └── current\ @@ -1990,7 +1990,7 @@ Git Bash (MSYS2/MinGW) doesn't use Windows' PATHEXT mechanism, so it won't find #### Why Not Symlinks? -On Unix, shims are symlinks to the vp binary, which preserves argv[0] for tool detection. On Windows, we use explicit `vp env run ` calls instead of symlinks because: +On Unix, shims are symlinks to the vp binary, which preserves argv[0] for tool detection. On Windows, we use explicit `vp env exec ` calls instead of symlinks because: 1. **Admin privileges required**: Windows symlinks need admin rights or Developer Mode 2. **Unreliable Git Bash support**: Symlink emulation varies by Git for Windows version @@ -2013,7 +2013,7 @@ exec "$VITE_PLUS_HOME/current/bin/vp.exe" "$@" #!/bin/sh VITE_PLUS_HOME="$(dirname "$(dirname "$(readlink -f "$0" 2>/dev/null || echo "$0")")")" export VITE_PLUS_HOME -exec "$VITE_PLUS_HOME/current/bin/vp.exe" env run node "$@" +exec "$VITE_PLUS_HOME/current/bin/vp.exe" env exec node "$@" ``` This ensures all commands work in: @@ -2038,7 +2038,7 @@ The `vp.cmd` wrapper forwards all arguments to the actual `vp.exe` binary. ```batch @echo off set VITE_PLUS_HOME=%~dp0.. -"%VITE_PLUS_HOME%\current\bin\vp.exe" env run node %* +"%VITE_PLUS_HOME%\current\bin\vp.exe" env exec node %* exit /b %ERRORLEVEL% ``` @@ -2047,7 +2047,7 @@ For npm: ```batch @echo off set VITE_PLUS_HOME=%~dp0.. -"%VITE_PLUS_HOME%\current\bin\vp.exe" env run npm %* +"%VITE_PLUS_HOME%\current\bin\vp.exe" env exec npm %* exit /b %ERRORLEVEL% ``` @@ -2055,8 +2055,8 @@ exit /b %ERRORLEVEL% 1. User runs `npm install` 2. Windows finds `~/.vite-plus/bin/npm.cmd` in PATH (cmd.exe/PowerShell) or `npm` (Git Bash) -3. Wrapper calls `vp.exe env run npm install` -4. `vp env run` command handles version resolution and execution +3. Wrapper calls `vp.exe env exec npm install` +4. `vp env exec` command handles version resolution and execution **Benefits of this approach**: @@ -2137,7 +2137,7 @@ env-doctor/ 10. Implement `vp env unpin` as alias for `pin --unpin` 11. Implement `vp env list` (local) and `vp env list-remote` (remote) to show versions 12. Implement recursion prevention (`VITE_PLUS_TOOL_RECURSION`) -13. Implement `vp env run --node ` command +13. Implement `vp env exec --node ` command ### Phase 2: Full Tool Support (P1) @@ -2184,7 +2184,7 @@ The following decisions have been made: 1. **VITE_PLUS_HOME Default Location**: `~/.vite-plus` - Simple, memorable path that's easy for users to find and configure. -2. **Windows Wrapper Strategy**: `.cmd` wrappers that call `vp env run ` - Consistent with Volta, no binary copies needed. +2. **Windows Wrapper Strategy**: `.cmd` wrappers that call `vp env exec ` - Consistent with Volta, no binary copies needed. 3. **Corepack Handling**: Not included - vite-plus has integrated package manager functionality, making corepack shims unnecessary.