@@ -7,6 +7,7 @@ use vite_shared::output;
77
88use crate :: package_manager:: {
99 PackageManager , PackageManagerType , ResolveCommandResult , format_path_env,
10+ resolve_global_npm_bin_path,
1011} ;
1112
1213/// The type of dependency to save.
@@ -46,21 +47,46 @@ impl PackageManager {
4647 options : & AddCommandOptions < ' _ > ,
4748 cwd : impl AsRef < AbsolutePath > ,
4849 ) -> Result < ExitStatus , Error > {
49- let resolve_command = self . resolve_add_command ( options) ;
50+ let resolve_command = self . resolve_add_command_with_global_npm_bin ( options, None ) ;
51+ run_command ( & resolve_command. bin_path , & resolve_command. args , & resolve_command. envs , cwd)
52+ . await
53+ }
54+
55+ /// Run the add command with an explicit npm binary for global installs.
56+ /// Return the exit status of the command.
57+ #[ must_use]
58+ pub async fn run_add_command_with_global_npm_bin (
59+ & self ,
60+ options : & AddCommandOptions < ' _ > ,
61+ cwd : impl AsRef < AbsolutePath > ,
62+ global_npm_bin_path : Option < & AbsolutePath > ,
63+ ) -> Result < ExitStatus , Error > {
64+ let resolve_command =
65+ self . resolve_add_command_with_global_npm_bin ( options, global_npm_bin_path) ;
5066 run_command ( & resolve_command. bin_path , & resolve_command. args , & resolve_command. envs , cwd)
5167 . await
5268 }
5369
5470 /// Resolve the add command.
5571 #[ must_use]
5672 pub fn resolve_add_command ( & self , options : & AddCommandOptions ) -> ResolveCommandResult {
73+ self . resolve_add_command_with_global_npm_bin ( options, None )
74+ }
75+
76+ /// Resolve the add command with an explicit npm binary for global installs.
77+ #[ must_use]
78+ pub fn resolve_add_command_with_global_npm_bin (
79+ & self ,
80+ options : & AddCommandOptions ,
81+ global_npm_bin_path : Option < & AbsolutePath > ,
82+ ) -> ResolveCommandResult {
5783 let bin_name: String ;
5884 let envs = HashMap :: from ( [ ( "PATH" . to_string ( ) , format_path_env ( self . get_bin_prefix ( ) ) ) ] ) ;
5985 let mut args: Vec < String > = Vec :: new ( ) ;
6086
6187 // global packages should use npm cli only
6288 if options. global {
63- bin_name = "npm" . into ( ) ;
89+ bin_name = resolve_global_npm_bin_path ( global_npm_bin_path ) ;
6490 args. push ( "install" . into ( ) ) ;
6591 args. push ( "--global" . into ( ) ) ;
6692 if let Some ( pass_through_args) = options. pass_through_args {
@@ -600,4 +626,24 @@ mod tests {
600626 assert_eq ! ( result. args, vec![ "add" , "--allow-build=react,napi" , "react" ] ) ;
601627 assert_eq ! ( result. bin_path, "pnpm" ) ;
602628 }
629+
630+ #[ test]
631+ fn test_global_add_uses_explicit_npm_bin ( ) {
632+ let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
633+ let npm_bin = if cfg ! ( windows) {
634+ AbsolutePathBuf :: new ( "C:\\ node\\ npm.cmd" . into ( ) ) . unwrap ( )
635+ } else {
636+ AbsolutePathBuf :: new ( "/node/bin/npm" . into ( ) ) . unwrap ( )
637+ } ;
638+ let result = pm. resolve_add_command_with_global_npm_bin (
639+ & AddCommandOptions {
640+ packages : & [ "typescript" . to_string ( ) ] ,
641+ global : true ,
642+ ..Default :: default ( )
643+ } ,
644+ Some ( & npm_bin) ,
645+ ) ;
646+ assert_eq ! ( result. args, vec![ "install" , "--global" , "typescript" ] ) ;
647+ assert_eq ! ( result. bin_path, npm_bin. as_path( ) . display( ) . to_string( ) ) ;
648+ }
603649}
0 commit comments