@@ -13,15 +13,13 @@ use vite_pm_cli::PackageManagerCommand;
1313use vite_shared:: output;
1414
1515use crate :: {
16- commands:: {
17- self ,
18- env:: { global_install, package_metadata:: PackageMetadata } ,
19- } ,
16+ commands:: { self , env:: package_metadata:: PackageMetadata , global} ,
2017 error:: Error ,
2118 help,
2219} ;
2320
2421const DEFAULT_GLOBAL_INSTALL_CONCURRENCY : usize = 5 ;
22+ const DEFAULT_GLOBAL_VIEW_CONCURRENCY : usize = 3 * DEFAULT_GLOBAL_INSTALL_CONCURRENCY ;
2523
2624#[ derive( Clone , Copy , Debug ) ]
2725pub struct RenderOptions {
@@ -552,7 +550,7 @@ fn run_tasks_completions(current: &OsStr) -> Vec<clap_complete::CompletionCandid
552550/// Handle a parsed package-manager command.
553551///
554552/// `Install`/`Add`/`Update`/`Remove` invoked with `-g`/`--global` are routed
555- /// through the vite-plus-managed Node.js install store (`commands::env `).
553+ /// through the vite-plus-managed Node.js install store (`commands::global `).
556554/// Everything else is forwarded to `vite_pm_cli::dispatch`, which executes
557555/// the underlying package manager (pnpm/npm/yarn/bun).
558556async fn run_package_manager_command (
@@ -581,13 +579,30 @@ async fn run_package_manager_command(
581579 managed_update ( packages, concurrency) . await
582580 }
583581
582+ PackageManagerCommand :: Outdated {
583+ global : true ,
584+ ref packages,
585+ long,
586+ format,
587+ concurrency,
588+ ..
589+ } => {
590+ global:: outdated:: execute (
591+ packages,
592+ long,
593+ format,
594+ concurrency. unwrap_or ( DEFAULT_GLOBAL_VIEW_CONCURRENCY ) ,
595+ )
596+ . await
597+ }
598+
584599 // `pm list -g` lists vite-plus-managed globals, not the underlying PM's.
585600 PackageManagerCommand :: Pm ( vite_pm_cli:: cli:: PmCommands :: List {
586601 global : true ,
587602 json,
588603 ref pattern,
589604 ..
590- } ) => crate :: commands :: env :: packages:: execute ( json, pattern. as_deref ( ) ) . await ,
605+ } ) => global :: packages:: execute ( json, pattern. as_deref ( ) ) . await ,
591606
592607 cmd => {
593608 commands:: prepend_js_runtime_to_path_env ( & cwd) . await ?;
@@ -602,7 +617,7 @@ async fn managed_install(
602617 force : bool ,
603618 concurrency : Option < usize > ,
604619) -> Result < ExitStatus , Error > {
605- if let Err ( ( package_name, error) ) = crate :: commands :: env :: global_install :: install (
620+ if let Err ( ( package_name, error) ) = global :: install :: install (
606621 packages,
607622 node,
608623 force,
@@ -623,106 +638,68 @@ async fn managed_install(
623638
624639async fn managed_uninstall ( packages : & [ String ] , dry_run : bool ) -> Result < ExitStatus , Error > {
625640 for package in packages {
626- if let Err ( e) = crate :: commands :: env :: global_install :: uninstall ( package, dry_run) . await {
641+ if let Err ( e) = global :: install :: uninstall ( package, dry_run) . await {
627642 vite_shared:: output:: raw_stderr ( & format ! ( "Failed to uninstall {package}: {e}" ) ) ;
628643 return Ok ( exit_status ( 1 ) ) ;
629644 }
630645 }
631646 Ok ( ExitStatus :: default ( ) )
632647}
633648
634- fn is_global_package_up_to_date ( installed_version : & str , registry_version : & str ) -> bool {
635- installed_version. trim ( ) == registry_version. trim ( )
636- }
637-
638649async fn managed_update (
639650 packages : & [ String ] ,
640651 concurrency : Option < usize > ,
641652) -> Result < ExitStatus , Error > {
642- let all_packages = if packages. is_empty ( ) {
653+ let concurrency = concurrency. unwrap_or ( DEFAULT_GLOBAL_INSTALL_CONCURRENCY ) ;
654+ let mut to_update: Vec < String > = Vec :: new ( ) ;
655+
656+ let packages = if packages. is_empty ( ) {
643657 let all = PackageMetadata :: list_all ( ) . await ?;
644658 if all. is_empty ( ) {
645659 vite_shared:: output:: raw ( "No global packages installed." ) ;
646660 return Ok ( ExitStatus :: default ( ) ) ;
647661 }
648- Some ( all)
649- } else {
650- None
651- } ;
652662
653- let mut to_update: Vec < String > = Vec :: new ( ) ;
654- let mut skipped = 0usize ;
655-
656- if let Some ( all) = all_packages {
657- for metadata in all {
658- match global_install:: latest_package_version ( & metadata. name ) . await {
659- Ok ( latest_version)
660- if is_global_package_up_to_date ( & metadata. version , & latest_version) =>
661- {
662- vite_shared:: output:: raw ( & format ! (
663- "{} is already up to date (v{})." ,
664- metadata. name, metadata. version
665- ) ) ;
666- skipped += 1 ;
667- }
668- Ok ( _) => to_update. push ( metadata. name . clone ( ) ) ,
669- Err ( e) => {
670- vite_shared:: output:: raw_stderr ( & format ! (
671- "Could not check latest version for {}: {e}; updating anyway." ,
672- metadata. name
673- ) ) ;
674- to_update. push ( metadata. name . clone ( ) ) ;
675- }
676- }
677- }
663+ None
678664 } else {
665+ let mut managed_specs = Vec :: new ( ) ;
666+
679667 for package in packages {
680- if global_install:: is_local_package_spec ( package) {
668+ // Always update local packages
669+ if global:: is_local_package_spec ( package) {
681670 to_update. push ( package. clone ( ) ) ;
682671 continue ;
683672 }
684673
685- let ( package_name, _) = global_install:: parse_package_spec ( package) ;
686- if let Some ( metadata) = PackageMetadata :: load ( & package_name) . await ? {
687- match global_install:: latest_package_version ( package) . await {
688- Ok ( latest_version)
689- if is_global_package_up_to_date ( & metadata. version , & latest_version) =>
690- {
691- vite_shared:: output:: raw ( & format ! (
692- "{} is already up to date (v{})." ,
693- package_name, metadata. version
694- ) ) ;
695- skipped += 1 ;
696- continue ;
697- }
698- Ok ( _) => { }
699- Err ( e) => {
700- vite_shared:: output:: raw_stderr ( & format ! (
701- "Could not check latest version for {package}: {e}; updating anyway."
702- ) ) ;
703- }
704- }
674+ let ( package_name, _) = global:: parse_package_spec ( package) ;
675+ if PackageMetadata :: load ( & package_name) . await ?. is_some ( ) {
676+ managed_specs. push ( package. clone ( ) ) ;
677+ } else {
678+ to_update. push ( package. clone ( ) ) ;
705679 }
706- to_update. push ( package. clone ( ) ) ;
707680 }
708- }
681+
682+ Some ( managed_specs)
683+ } ;
684+ to_update. extend (
685+ global:: outdated:: get_outdated_packages (
686+ & packages. unwrap_or ( Vec :: new ( ) ) ,
687+ concurrency * 3 ,
688+ true ,
689+ )
690+ . await ?
691+ . into_iter ( )
692+ . map ( |package| package. spec . unwrap_or ( package. name ) ) ,
693+ ) ;
709694
710695 if to_update. is_empty ( ) {
711- if skipped > 0 {
712- vite_shared:: output:: raw ( "All global packages are up to date." ) ;
713- }
696+ vite_shared:: output:: raw ( "All global packages are up to date." ) ;
714697 return Ok ( ExitStatus :: default ( ) ) ;
715698 }
716699
717700 // Call reinstall logic
718- if let Err ( ( package_name, error) ) = global_install:: install (
719- & to_update,
720- None ,
721- false ,
722- concurrency. unwrap_or ( DEFAULT_GLOBAL_INSTALL_CONCURRENCY ) ,
723- true ,
724- )
725- . await
701+ if let Err ( ( package_name, error) ) =
702+ global:: install:: install ( & to_update, None , false , concurrency, true ) . await
726703 {
727704 output:: error ( & format ! (
728705 "Failed to update {}: {error}" ,
@@ -975,20 +952,10 @@ pub fn try_parse_args_from_with_options(
975952#[ cfg( test) ]
976953mod tests {
977954 use super :: {
978- has_flag_before_terminator, is_global_package_up_to_date , should_force_global_delegate,
955+ has_flag_before_terminator, should_force_global_delegate,
979956 should_suppress_header_for_subcommand,
980957 } ;
981958
982- #[ test]
983- fn skips_global_update_when_registry_and_node_versions_match ( ) {
984- assert ! ( is_global_package_up_to_date( "5.9.3" , "5.9.3" ) ) ;
985- }
986-
987- #[ test]
988- fn updates_global_package_when_registry_version_differs_from_installed_version ( ) {
989- assert ! ( !is_global_package_up_to_date( "5.9.2" , "5.9.3" ) ) ;
990- }
991-
992959 #[ test]
993960 fn detects_flag_before_option_terminator ( ) {
994961 assert ! ( has_flag_before_terminator(
0 commit comments