Skip to content

Commit eb7370a

Browse files
authored
feat(cli): add vp node shorthand for vp env exec node (#1359)
Rewrite `vp node [args...]` to `vp env exec node [args...]` in the pre-clap argument normalizer so the shorthand reuses the existing shim dispatch (automatic Node version resolution, auto-download, recursion prevention). No changes to the Commands enum — avoids growing the derived clap parser. Closes #1325
1 parent 96a43f3 commit eb7370a

File tree

8 files changed

+73
-1
lines changed

8 files changed

+73
-1
lines changed

crates/vite_global_cli/src/help.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ pub fn top_level_help_doc() -> HelpDoc {
451451
vec![
452452
row("run", "Run tasks (also available as standalone `vpr`)"),
453453
row("exec", "Execute a command from local node_modules/.bin"),
454+
row("node", "Run a Node.js script (shorthand for `env exec node`)"),
454455
row("dlx", "Execute a package binary without installing it as a dependency"),
455456
row("cache", "Manage the task cache"),
456457
],

crates/vite_global_cli/src/main.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use crate::cli::{
3737
/// Normalize CLI arguments:
3838
/// - `vp list ...` / `vp ls ...` → `vp pm list ...`
3939
/// - `vp help [command]` → `vp [command] --help`
40+
/// - `vp node [args...]` → `vp env exec node [args...]`
4041
fn normalize_args(args: Vec<String>) -> Vec<String> {
4142
match args.get(1).map(String::as_str) {
4243
// `vp list ...` → `vp pm list ...`
@@ -60,6 +61,16 @@ fn normalize_args(args: Vec<String>) -> Vec<String> {
6061
normalized.extend(args[3..].iter().cloned());
6162
normalized
6263
}
64+
// `vp node [args...]` → `vp env exec node [args...]`
65+
Some("node") => {
66+
let mut normalized = Vec::with_capacity(args.len() + 2);
67+
normalized.push(args[0].clone());
68+
normalized.push("env".to_string());
69+
normalized.push("exec".to_string());
70+
normalized.push("node".to_string());
71+
normalized.extend(args[2..].iter().cloned());
72+
normalized
73+
}
6374
// No transformation needed
6475
_ => args,
6576
}
@@ -402,9 +413,27 @@ mod tests {
402413

403414
use super::{
404415
extract_unknown_argument, has_pass_as_value_suggestion, is_affirmative_response,
405-
replace_top_level_typoed_subcommand, try_parse_args_from,
416+
normalize_args, replace_top_level_typoed_subcommand, try_parse_args_from,
406417
};
407418

419+
fn s(v: &[&str]) -> Vec<String> {
420+
v.iter().map(|s| s.to_string()).collect()
421+
}
422+
423+
#[test]
424+
fn normalize_args_rewrites_vp_node_to_env_exec_node() {
425+
let input = s(&["vp", "node", "script.js", "foo", "--flag"]);
426+
let normalized = normalize_args(input);
427+
assert_eq!(normalized, s(&["vp", "env", "exec", "node", "script.js", "foo", "--flag"]));
428+
}
429+
430+
#[test]
431+
fn normalize_args_rewrites_bare_vp_node() {
432+
let input = s(&["vp", "node"]);
433+
let normalized = normalize_args(input);
434+
assert_eq!(normalized, s(&["vp", "env", "exec", "node"]));
435+
}
436+
408437
#[test]
409438
fn unknown_argument_detected_without_pass_as_value_hint() {
410439
let error = try_parse_args_from(["vp".to_string(), "--cache".to_string()])

docs/guide/env.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ This switches to system-first mode, where the shims prefer your system Node.js a
4242
- `vp env install` installs a Node.js version
4343
- `vp env uninstall` removes an installed Node.js version
4444
- `vp env exec` runs a command with a specific Node.js version
45+
- `vp node` runs a Node.js script — shorthand for `vp env exec node`
4546

4647
### Inspect
4748

@@ -81,6 +82,8 @@ vp env list-remote --lts # List only LTS versions
8182
# Execute
8283
vp env exec --node lts npm i # Execute npm with latest LTS
8384
vp env exec node -v # Use shim mode with automatic version resolution
85+
vp node script.js # Shorthand: run a Node.js script with the resolved version
86+
vp node -e "console.log(1+1)" # Shorthand: forward any node flag or argument
8487
```
8588

8689
## Custom Node.js Mirror

packages/cli/snap-tests-global/cli-helper-message/snap.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Develop:
2121
Execute:
2222
run Run tasks (also available as standalone `vpr`)
2323
exec Execute a command from local node_modules/.bin
24+
node Run a Node.js script (shorthand for `env exec node`)
2425
dlx Execute a package binary without installing it as a dependency
2526
cache Manage the task cache
2627

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "command-node",
3+
"version": "1.0.0",
4+
"private": true,
5+
"engines": {
6+
"node": "20.18.0"
7+
}
8+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const [, , ...rest] = process.argv;
2+
console.log('node version:', process.version);
3+
console.log('script args:', JSON.stringify(rest));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
> vp node -v # Shorthand: version resolved from package.json engines.node
2+
v20.18.0
3+
4+
> vp node script.js # Execute a local JS file (primary use case)
5+
node version: v<semver>
6+
script args: []
7+
8+
> vp node script.js foo bar --flag # Forward script args to the local file
9+
node version: v<semver>
10+
script args: ["foo","bar","--flag"]
11+
12+
> vp node -e "console.log('Hello from vp node')" # Inline script via -e
13+
Hello from vp node
14+
15+
> vp env exec node -v # Equivalence check: same output as shorthand
16+
v20.18.0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"env": {},
3+
"ignoredPlatforms": [],
4+
"commands": [
5+
"vp node -v # Shorthand: version resolved from package.json engines.node",
6+
"vp node script.js # Execute a local JS file (primary use case)",
7+
"vp node script.js foo bar --flag # Forward script args to the local file",
8+
"vp node -e \"console.log('Hello from vp node')\" # Inline script via -e",
9+
"vp env exec node -v # Equivalence check: same output as shorthand"
10+
]
11+
}

0 commit comments

Comments
 (0)