Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions packages/cli/binding/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ pub enum CustomTaskSubcommand {
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
args: Vec<String>,
},
/// Build application
/// Build for production
#[command(disable_help_flag = true)]
Build {
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
args: Vec<String>,
},
/// Run test
/// Run tests
#[command(disable_help_flag = true)]
Test {
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
Expand Down Expand Up @@ -92,7 +92,6 @@ pub enum CustomTaskSubcommand {
args: Vec<String>,
},
/// Install command.

Copilot AI Jan 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description comment for the Install command was removed. While this change makes the documentation more concise, the removed comment provided useful context that the install command currently forwards to the package manager. Consider keeping a brief note about this forwarding behavior, as it helps developers understand the command's implementation.

Suggested change
/// Install command.
/// Install command (currently forwards to the package manager).

Copilot uses AI. Check for mistakes.
/// It will be passed to the package manager's install command currently.
#[command(disable_help_flag = true, alias = "i")]
Install {
#[clap(allow_hyphen_values = true, trailing_var_arg = true)]
Expand Down Expand Up @@ -611,6 +610,11 @@ pub async fn main(
// Get args from parameter or env::args()
// When running from NAPI, args should be passed explicitly to skip node/script paths
let args_vec: Vec<String> = args.unwrap_or_else(|| env::args().skip(1).collect());
let args_vec = normalize_help_args(args_vec);
if should_print_help(&args_vec) {
print_help();
return Ok(ExitStatus::SUCCESS);
}

// Parse CLI args using vite_task::CLIArgs
// Prepend "vite" as program name for clap
Expand Down Expand Up @@ -703,6 +707,47 @@ pub async fn main(
}
}

fn normalize_help_args(args: Vec<String>) -> Vec<String> {
args

Copilot AI Jan 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normalize_help_args function is defined but currently does nothing (it just returns the args unchanged). This appears to be a placeholder that was created to mirror the structure in packages/global/binding/src/lib.rs where normalize_help_args performs actual normalization to convert "help" subcommands to "--help" flags. Either implement the normalization logic here for consistency or remove this function and call print_help directly from the appropriate location if this normalization is not needed for the local CLI.

Suggested change
args
args
.into_iter()
.map(|arg| if arg == "help" { "--help".to_string() } else { arg })
.collect()

Copilot uses AI. Check for mistakes.
}

fn should_print_help(args: &[String]) -> bool {
matches!(
args,
[arg] if arg == "-h" || arg == "--help"
)
}

fn print_help() {
let version = env!("CARGO_PKG_VERSION");
let bold = "\x1b[1m";
let bold_underline = "\x1b[1;4m";
let reset = "\x1b[0m";
println!(
"vite+/{version}

{bold_underline}Usage:{reset} {bold}vite{reset} <COMMAND>

{bold_underline}Vite+ Commands:{reset}
{bold}dev{reset} Run development server
{bold}build{reset} Build for production
{bold}preview{reset} Preview production build
{bold}lint{reset} Lint code
{bold}test{reset} Run tests
{bold}fmt{reset} Format code
{bold}lib{reset} Build library
{bold}doc{reset} Build documentation
{bold}run{reset} Run tasks
{bold}cache{reset} Manage the task cache

{bold_underline}Package Manager Commands:{reset}
{bold}install{reset} Install all dependencies

Options:
-h, --help Print help"
);
}

pub fn init_tracing() {
use std::sync::OnceLock;

Expand Down
35 changes: 18 additions & 17 deletions packages/cli/snap-tests/command-helper/snap.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
> vite -h # help message
Vite+<repeat>

Usage: vite <COMMAND>

Commands:
run Run tasks
lint Lint code
fmt Format code
build Build application
test Run test
lib Build library
dev Run development server
preview Preview production build
doc Build documentation
install Install command. It will be passed to the package manager's install command currently
cache Manage the task cache
help Print this message or the help of the given subcommand(s)
vite+/<semver>

Usage: vite <COMMAND>

Vite+ Commands:
dev Run development server
build Build for production
preview Preview production build
lint Lint code
test Run tests
fmt Format code
lib Build library
doc Build documentation
run Run tasks
cache Manage the task cache

Package Manager Commands:
install Install all dependencies

Options:
-h, --help Print help
Expand Down
91 changes: 79 additions & 12 deletions packages/global/binding/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::process::ExitStatus;

use clap::{Parser, Subcommand};
use clap::{CommandFactory, Parser, Subcommand};
use vite_error::Error;
use vite_install::commands::{
add::SaveDependencyType, install::InstallCommandOptions, outdated::Format,
Expand All @@ -15,16 +15,7 @@ use crate::commands::{

#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
#[command(
disable_help_subcommand = true,
help_template = "\
vite+/{version}

{usage-heading} {usage}

{all-args}{after-help}
"
)]
#[command(disable_help_subcommand = true)]
pub struct Args {
#[clap(subcommand)]
pub commands: Commands,
Expand Down Expand Up @@ -406,6 +397,24 @@ pub enum Commands {
#[arg(last = true, allow_hyphen_values = true)]
pass_through_args: Option<Vec<String>>,
},
/// View package information from registry
#[command(alias = "view", alias = "show")]
Info {
/// Package name with optional version
#[arg(required = true)]
package: String,

/// Specific field to view
field: Option<String>,

/// Output in JSON format
#[arg(long)]
json: bool,

/// Additional arguments to pass through to the package manager
#[arg(last = true, allow_hyphen_values = true)]
pass_through_args: Option<Vec<String>>,
},
/// Link packages for local development
#[command(alias = "ln")]
Link {
Expand Down Expand Up @@ -433,7 +442,7 @@ pub enum Commands {
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
args: Vec<String>,
},
/// Package manager utilities
/// Forward command to the package manager.

Copilot AI Jan 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description "Forward command to the package manager." ends with a period, which is inconsistent with other command descriptions in the enum (e.g., line 448: "Execute a package binary without installing it as a dependency"). Remove the trailing period for consistency.

Suggested change
/// Forward command to the package manager.
/// Forward command to the package manager

Copilot uses AI. Check for mistakes.
#[command(subcommand)]
Pm(PmCommands),
/// Execute a package binary without installing it as a dependency
Expand Down Expand Up @@ -1064,6 +1073,17 @@ pub async fn main(cwd: AbsolutePathBuf, mut args: Args) -> Result<std::process::
.await?;
return Ok(exit_status);
}
Commands::Info { package, field, json, pass_through_args } => {
let exit_status = PmCommand::new(cwd)
.execute(PmCommands::View {
package: package.clone(),
field: field.clone(),
json: *json,
pass_through_args: pass_through_args.clone(),
})
.await?;
return Ok(exit_status);
}
Comment on lines +1076 to +1086

Copilot AI Jan 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Info command forwards to PmCommands::View but there's no test coverage demonstrating that the top-level vite info command works correctly. Consider adding a test case to verify that vite info <package> properly delegates to the package manager's view/info command, similar to how other package manager commands are tested in the snap-tests directory.

Copilot uses AI. Check for mistakes.
Commands::Pm(pm_command) => {
let exit_status = PmCommand::new(cwd).execute(pm_command.clone()).await?;
return Ok(exit_status);
Expand All @@ -1078,6 +1098,53 @@ pub async fn main(cwd: AbsolutePathBuf, mut args: Args) -> Result<std::process::
};
}

pub fn command_with_help() -> clap::Command {
let bold = "\x1b[1m";
let bold_underline = "\x1b[1;4m";
let reset = "\x1b[0m";
let version = env!("CARGO_PKG_VERSION");

let after_help = format!(
"{bold_underline}Vite+ Commands:{reset}
{bold}dev{reset} Run development server
{bold}build{reset} Build for production
{bold}lint{reset} Lint code
{bold}test{reset} Run tests
{bold}fmt{reset} Format code
{bold}doc{reset} Build documentation
{bold}lib{reset} Build library
{bold}migrate{reset} Migrate an existing project to Vite+
{bold}cache{reset} Manage the task cache
{bold}new{reset} Generate a new project

Copilot AI Jan 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help text displays "new" as a command, but the actual command is defined as "Gen" in the Commands enum (line 467). While the JavaScript code intercepts both "new" and "gen" commands before reaching Rust, it would be more consistent to add an alias attribute to the Gen command definition to make it clear in the code that both names are supported. This would improve code clarity and make it easier for future maintainers to understand that "new" is an officially supported alias.

Suggested change
{bold}new{reset} Generate a new project
{bold}gen{reset} (alias: new) Generate a new project

Copilot uses AI. Check for mistakes.
{bold}run{reset} Run tasks

{bold_underline}Package Manager Commands:{reset}
{bold}install{reset} Install all dependencies, or add packages if package names are provided
{bold}add{reset} Add packages to dependencies
{bold}remove{reset} Remove packages from dependencies
{bold}dedupe{reset} Deduplicate dependencies by removing older versions
{bold}dlx{reset} Execute a package binary without installing it as a dependency
{bold}info{reset} View package information from registry
{bold}link{reset} Link packages for local development
{bold}outdated{reset} Check for outdated packages
{bold}pm{reset} Forward command to the package manager
{bold}unlink{reset} Unlink packages
{bold}update{reset} Update packages to their latest versions
{bold}why{reset} Show why a package is installed
"
);
let help_template = format!(
"vite+/{version}

{{usage-heading}} {{usage}}{{after-help}}
{bold_underline}Options:{reset}
{{options}}
"
);

Args::command().after_help(after_help).help_template(help_template)
}

pub fn init_tracing() {
use std::sync::OnceLock;

Expand Down
2 changes: 1 addition & 1 deletion packages/global/binding/src/commands/pm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
cli::{ConfigCommands, OwnerCommands, PmCommands},
};

/// Package manager utilities command.
/// Forward command to the package manager.
///
/// This command provides a unified interface to package manager utilities
/// across pnpm, npm, and yarn.
Expand Down
20 changes: 18 additions & 2 deletions packages/global/binding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ mod migration;
mod package_manager;
mod utils;

use clap::Parser as _;
use std::ffi::{OsStr, OsString};

use clap::FromArgMatches as _;
use napi::{anyhow, bindgen_prelude::*};
use napi_derive::napi;
pub use utils::run_command;
Expand Down Expand Up @@ -90,5 +92,19 @@ pub async fn run(options: CliOptions) -> Result<i32> {

fn parse_args() -> Args {
// Parse CLI arguments (skip first arg which is the node binary)
Args::parse_from(std::env::args_os().skip(1))
let args = normalize_help_args(std::env::args_os().skip(1).collect());
let matches = crate::cli::command_with_help().get_matches_from(args);
Args::from_arg_matches(&matches).unwrap_or_else(|e| e.exit())
}

fn normalize_help_args(args: Vec<OsString>) -> Vec<OsString> {
if matches!(args.first(), Some(arg) if arg == OsStr::new("help")) {
return vec![OsString::from("--help")];
}

if args.len() >= 2 && args[1] == OsStr::new("help") {
return vec![args[0].clone(), OsString::from("--help")];
}

args
}
51 changes: 27 additions & 24 deletions packages/global/snap-tests/cli-helper-message/snap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,32 @@ vite+/<semver>

Usage: vite <COMMAND>

Commands:
install Install all dependencies, or add packages if package names are provided
add Add packages to dependencies
remove Remove packages from dependencies
update Update packages to their latest versions
dedupe Deduplicate dependencies by removing older versions
outdated Check for outdated packages
why Show why a package is installed
link Link packages for local development
unlink Unlink packages
pm Package manager utilities
dlx Execute a package binary without installing it as a dependency
gen Generate a new project
migrate Migrate an existing project to vite+<repeat>
dev Run development server
build Build application
test Run test
lint Lint code
fmt Format code
lib Build library
doc Build documentation
run Run tasks
cache Manage the task cache
Vite+ Commands:
dev Run development server
build Build for production
lint Lint code
test Run tests
fmt Format code
doc Build documentation
lib Build library
migrate Migrate an existing project to Vite+<repeat>
cache Manage the task cache
new Generate a new project
run Run tasks

Package Manager Commands:
install Install all dependencies, or add packages if package names are provided
add Add packages to dependencies
remove Remove packages from dependencies
dedupe Deduplicate dependencies by removing older versions
dlx Execute a package binary without installing it as a dependency
info View package information from registry
link Link packages for local development
outdated Check for outdated packages
pm Forward command to the package manager
unlink Unlink packages
update Update packages to their latest versions
why Show why a package is installed

Options:
-h, --help Print help
Expand Down Expand Up @@ -235,7 +238,7 @@ Options:
-h, --help Print help

> vite pm -h # show pm help message
Package manager utilities
Forward command to the package manager

Usage: vite pm <COMMAND>

Expand Down
Loading