diff --git a/crates/vite_global_cli/src/help.rs b/crates/vite_global_cli/src/help.rs index 4d037cf643..d6b2cabd52 100644 --- a/crates/vite_global_cli/src/help.rs +++ b/crates/vite_global_cli/src/help.rs @@ -65,7 +65,7 @@ fn documentation_url_for_command_path(command_path: &[&str]) -> Option<&'static ["config"] | ["staged"] => Some("https://viteplus.dev/guide/commit-hooks"), [ "install" | "add" | "remove" | "update" | "dedupe" | "outdated" | "list" | "ls" | "why" - | "info" | "view" | "show" | "link" | "unlink" | "pm", + | "info" | "view" | "show" | "link" | "unlink" | "rebuild" | "pm", .., ] => Some("https://viteplus.dev/guide/install"), ["dev"] => Some("https://viteplus.dev/guide/dev"), @@ -477,6 +477,7 @@ pub fn top_level_help_doc() -> HelpDoc { row("info, view, show", "View package information from the registry"), row("link, ln", "Link packages for local development"), row("unlink", "Unlink packages"), + row("rebuild", "Rebuild native modules"), row("pm", "Forward a command to the package manager"), ], ), diff --git a/crates/vite_global_cli/src/main.rs b/crates/vite_global_cli/src/main.rs index aa33495fcd..54c58b2a1f 100644 --- a/crates/vite_global_cli/src/main.rs +++ b/crates/vite_global_cli/src/main.rs @@ -36,43 +36,60 @@ use crate::cli::{ /// Normalize CLI arguments: /// - `vp list ...` / `vp ls ...` → `vp pm list ...` +/// - `vp rebuild ...` → `vp pm rebuild ...` /// - `vp help [command]` → `vp [command] --help` /// - `vp node [args...]` → `vp env exec node [args...]` fn normalize_args(args: Vec) -> Vec { - match args.get(1).map(String::as_str) { - // `vp list ...` → `vp pm list ...` - // `vp ls ...` → `vp pm list ...` - Some("list" | "ls") => { - let mut normalized = Vec::with_capacity(args.len() + 1); - normalized.push(args[0].clone()); - normalized.push("pm".to_string()); - normalized.push("list".to_string()); - normalized.extend(args[2..].iter().cloned()); - normalized - } - // `vp help` alone -> show main help - Some("help") if args.len() == 2 => vec![args[0].clone(), "--help".to_string()], - // `vp help [command] [args...]` -> `vp [command] --help [args...]` - Some("help") if args.len() > 2 => { - let mut normalized = Vec::with_capacity(args.len()); - normalized.push(args[0].clone()); - normalized.push(args[2].clone()); - normalized.push("--help".to_string()); - normalized.extend(args[3..].iter().cloned()); - normalized - } - // `vp node [args...]` → `vp env exec node [args...]` - Some("node") => { - let mut normalized = Vec::with_capacity(args.len() + 2); - normalized.push(args[0].clone()); - normalized.push("env".to_string()); - normalized.push("exec".to_string()); - normalized.push("node".to_string()); - normalized.extend(args[2..].iter().cloned()); - normalized - } - // No transformation needed - _ => args, + let mut normalized = args; + loop { + let next = match normalized.get(1).map(String::as_str) { + // `vp list ...` → `vp pm list ...` + // `vp ls ...` → `vp pm list ...` + Some("list" | "ls") => { + let mut next = Vec::with_capacity(normalized.len() + 1); + next.push(normalized[0].clone()); + next.push("pm".to_string()); + next.push("list".to_string()); + next.extend(normalized[2..].iter().cloned()); + next + } + // `vp rebuild ...` → `vp pm rebuild ...` + Some("rebuild") => { + let mut next = Vec::with_capacity(normalized.len() + 1); + next.push(normalized[0].clone()); + next.push("pm".to_string()); + next.push("rebuild".to_string()); + next.extend(normalized[2..].iter().cloned()); + next + } + // `vp help` alone -> show main help + Some("help") if normalized.len() == 2 => { + vec![normalized[0].clone(), "--help".to_string()] + } + // `vp help [command] [args...]` -> `vp [command] --help [args...]` + Some("help") if normalized.len() > 2 => { + let mut next = Vec::with_capacity(normalized.len()); + next.push(normalized[0].clone()); + next.push(normalized[2].clone()); + next.push("--help".to_string()); + next.extend(normalized[3..].iter().cloned()); + next + } + // `vp node [args...]` → `vp env exec node [args...]` + Some("node") => { + let mut next = Vec::with_capacity(normalized.len() + 2); + next.push(normalized[0].clone()); + next.push("env".to_string()); + next.push("exec".to_string()); + next.push("node".to_string()); + next.extend(normalized[2..].iter().cloned()); + next + } + // No transformation needed + _ => return normalized, + }; + + normalized = next; } } @@ -434,6 +451,34 @@ mod tests { assert_eq!(normalized, s(&["vp", "env", "exec", "node"])); } + #[test] + fn normalize_args_rewrites_bare_vp_rebuild() { + let input = s(&["vp", "rebuild"]); + let normalized = normalize_args(input); + assert_eq!(normalized, s(&["vp", "pm", "rebuild"])); + } + + #[test] + fn normalize_args_rewrites_vp_rebuild_with_args() { + let input = s(&["vp", "rebuild", "--", "--update-binary"]); + let normalized = normalize_args(input); + assert_eq!(normalized, s(&["vp", "pm", "rebuild", "--", "--update-binary"])); + } + + #[test] + fn normalize_args_rewrites_vp_help_rebuild() { + let input = s(&["vp", "help", "rebuild"]); + let normalized = normalize_args(input); + assert_eq!(normalized, s(&["vp", "pm", "rebuild", "--help"])); + } + + #[test] + fn normalize_args_rewrites_vp_help_node() { + let input = s(&["vp", "help", "node"]); + let normalized = normalize_args(input); + assert_eq!(normalized, s(&["vp", "env", "exec", "node", "--help"])); + } + #[test] fn unknown_argument_detected_without_pass_as_value_hint() { let error = try_parse_args_from(["vp".to_string(), "--cache".to_string()]) diff --git a/docs/guide/install.md b/docs/guide/install.md index 374b21f8ca..87c782ca62 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -60,6 +60,7 @@ Vite+ provides all the familiar package management commands: - `vp list` shows installed packages - `vp why ` explains why a package is present - `vp info ` shows registry metadata for a package +- `vp rebuild` rebuilds native modules (e.g. after switching Node.js versions) - `vp link` and `vp unlink` manage local package links - `vp dlx ` runs a package binary without adding it to the project - `vp pm ` forwards a raw package-manager-specific command when you need behavior outside the normalized `vp` command set @@ -115,6 +116,20 @@ Use these when you need to understand the current state of dependencies. - `vp why react` explains why `react` is installed - `vp info react` shows registry metadata such as versions and dist-tags +#### Rebuild + +Use `vp rebuild` when native modules need to be recompiled, for example after switching Node.js versions or when a C/C++ addon fails to load. + +- `vp rebuild` rebuilds all native modules +- `vp rebuild -- ` passes extra arguments to the underlying package manager + +```bash +vp rebuild +vp rebuild -- --update-binary +``` + +`vp rebuild` is a shorthand for `vp pm rebuild`. + #### Advanced Use these when you need lower-level package-manager behavior. diff --git a/packages/cli/snap-tests-global/cli-helper-message/snap.txt b/packages/cli/snap-tests-global/cli-helper-message/snap.txt index b4f36cc96c..b376b8dc1f 100644 --- a/packages/cli/snap-tests-global/cli-helper-message/snap.txt +++ b/packages/cli/snap-tests-global/cli-helper-message/snap.txt @@ -41,6 +41,7 @@ Manage Dependencies: info, view, show View package information from the registry link, ln Link packages for local development unlink Unlink packages + rebuild Rebuild native modules pm Forward a command to the package manager Maintain: