@@ -201,6 +201,68 @@ impl PackageManager {
201201
202202 ignores
203203 }
204+
205+ /// Build command arguments for adding packages with workspace support
206+ #[ must_use]
207+ pub fn build_add_args (
208+ & self ,
209+ packages : & [ String ] ,
210+ filters : & [ String ] ,
211+ workspace_root : bool ,
212+ workspace_only : bool ,
213+ extra_args : & [ String ] ,
214+ ) -> Vec < String > {
215+ let mut args = Vec :: new ( ) ;
216+
217+ match self . client {
218+ PackageManagerType :: Pnpm => {
219+ // pnpm: --filter must come before command
220+ for filter in filters {
221+ args. push ( "--filter" . to_string ( ) ) ;
222+ args. push ( filter. clone ( ) ) ;
223+ }
224+ args. push ( "add" . to_string ( ) ) ;
225+ args. extend_from_slice ( packages) ;
226+ if workspace_root {
227+ args. push ( "-w" . to_string ( ) ) ;
228+ }
229+ if workspace_only {
230+ args. push ( "--workspace" . to_string ( ) ) ;
231+ }
232+ args. extend_from_slice ( extra_args) ;
233+ }
234+ PackageManagerType :: Yarn => {
235+ // yarn: workspace <pkg> add
236+ if !filters. is_empty ( ) {
237+ args. push ( "workspace" . to_string ( ) ) ;
238+ args. push ( filters[ 0 ] . clone ( ) ) ;
239+ }
240+ args. push ( "add" . to_string ( ) ) ;
241+ args. extend_from_slice ( packages) ;
242+ if workspace_root {
243+ args. push ( "-W" . to_string ( ) ) ;
244+ }
245+ args. extend_from_slice ( extra_args) ;
246+ }
247+ PackageManagerType :: Npm => {
248+ // npm: install --workspace <pkg>
249+ args. push ( "install" . to_string ( ) ) ;
250+ args. extend_from_slice ( packages) ;
251+ if !filters. is_empty ( ) {
252+ for filter in filters {
253+ args. push ( "--workspace" . to_string ( ) ) ;
254+ args. push ( filter. clone ( ) ) ;
255+ }
256+ }
257+ if workspace_root {
258+ args. push ( "-w" . to_string ( ) ) ;
259+ }
260+ args. extend_from_slice ( extra_args) ;
261+ }
262+ }
263+
264+ args
265+ }
204266}
205267
206268/// The package root directory and its package.json file.
@@ -628,6 +690,22 @@ mod tests {
628690 . expect ( "Failed to write pnpm-workspace.yaml" ) ;
629691 }
630692
693+ fn create_mock_package_manager ( pm_type : PackageManagerType ) -> PackageManager {
694+ let temp_dir = create_temp_dir ( ) ;
695+ let temp_dir_path = AbsolutePathBuf :: new ( temp_dir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ;
696+ let install_dir = temp_dir_path. join ( "install" ) ;
697+
698+ PackageManager {
699+ client : pm_type,
700+ package_name : pm_type. to_string ( ) . into ( ) ,
701+ version : "1.0.0" . into ( ) ,
702+ hash : None ,
703+ bin_name : pm_type. to_string ( ) . into ( ) ,
704+ workspace_root : temp_dir_path. clone ( ) ,
705+ install_dir,
706+ }
707+ }
708+
631709 #[ test]
632710 fn test_find_package_root ( ) {
633711 let temp_dir = create_temp_dir ( ) ;
@@ -1665,29 +1743,12 @@ mod tests {
16651743 "pnpmfile.cjs should be detected before yarn.config.cjs"
16661744 ) ;
16671745 }
1668-
16691746 // Tests for get_fingerprint_ignores method
16701747 mod get_fingerprint_ignores_tests {
16711748 use vite_glob:: GlobPatternSet ;
16721749
16731750 use super :: * ;
16741751
1675- fn create_mock_package_manager ( pm_type : PackageManagerType ) -> PackageManager {
1676- let temp_dir = create_temp_dir ( ) ;
1677- let temp_dir_path = AbsolutePathBuf :: new ( temp_dir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ;
1678- let install_dir = temp_dir_path. join ( "install" ) ;
1679-
1680- PackageManager {
1681- client : pm_type,
1682- package_name : pm_type. to_string ( ) . into ( ) ,
1683- version : "1.0.0" . into ( ) ,
1684- hash : None ,
1685- bin_name : pm_type. to_string ( ) . into ( ) ,
1686- workspace_root : temp_dir_path. clone ( ) ,
1687- install_dir,
1688- }
1689- }
1690-
16911752 #[ test]
16921753 fn test_pnpm_fingerprint_ignores ( ) {
16931754 let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
@@ -1893,4 +1954,106 @@ mod tests {
18931954 assert ! ( matcher. is_match( "src/app.ts" ) , "Should ignore source files" ) ;
18941955 }
18951956 }
1957+
1958+ // Tests for build_add_args method
1959+ mod build_add_args_tests {
1960+ use super :: * ;
1961+
1962+ #[ test]
1963+ fn test_pnpm_basic_add ( ) {
1964+ let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
1965+ let args = pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ ] , false , false , & [ ] ) ;
1966+ assert_eq ! ( args, vec![ "add" , "react" ] ) ;
1967+ }
1968+
1969+ #[ test]
1970+ fn test_pnpm_add_with_filter ( ) {
1971+ let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
1972+ let args =
1973+ pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ "app" . to_string ( ) ] , false , false , & [ ] ) ;
1974+ assert_eq ! ( args, vec![ "--filter" , "app" , "add" , "react" ] ) ;
1975+ }
1976+
1977+ #[ test]
1978+ fn test_pnpm_add_workspace_root ( ) {
1979+ let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
1980+ let args = pm. build_add_args (
1981+ & [ "typescript" . to_string ( ) ] ,
1982+ & [ ] ,
1983+ true ,
1984+ false ,
1985+ & [ "-D" . to_string ( ) ] ,
1986+ ) ;
1987+ assert_eq ! ( args, vec![ "add" , "typescript" , "-w" , "-D" ] ) ;
1988+ }
1989+
1990+ #[ test]
1991+ fn test_pnpm_add_workspace_only ( ) {
1992+ let pm = create_mock_package_manager ( PackageManagerType :: Pnpm ) ;
1993+ let args = pm. build_add_args (
1994+ & [ "@myorg/utils" . to_string ( ) ] ,
1995+ & [ "app" . to_string ( ) ] ,
1996+ false ,
1997+ true ,
1998+ & [ ] ,
1999+ ) ;
2000+ assert_eq ! ( args, vec![ "--filter" , "app" , "add" , "@myorg/utils" , "--workspace" ] ) ;
2001+ }
2002+
2003+ #[ test]
2004+ fn test_yarn_basic_add ( ) {
2005+ let pm = create_mock_package_manager ( PackageManagerType :: Yarn ) ;
2006+ let args = pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ ] , false , false , & [ ] ) ;
2007+ assert_eq ! ( args, vec![ "add" , "react" ] ) ;
2008+ }
2009+
2010+ #[ test]
2011+ fn test_yarn_add_with_workspace ( ) {
2012+ let pm = create_mock_package_manager ( PackageManagerType :: Yarn ) ;
2013+ let args =
2014+ pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ "app" . to_string ( ) ] , false , false , & [ ] ) ;
2015+ assert_eq ! ( args, vec![ "workspace" , "app" , "add" , "react" ] ) ;
2016+ }
2017+
2018+ #[ test]
2019+ fn test_yarn_add_workspace_root ( ) {
2020+ let pm = create_mock_package_manager ( PackageManagerType :: Yarn ) ;
2021+ let args = pm. build_add_args (
2022+ & [ "typescript" . to_string ( ) ] ,
2023+ & [ ] ,
2024+ true ,
2025+ false ,
2026+ & [ "-D" . to_string ( ) ] ,
2027+ ) ;
2028+ assert_eq ! ( args, vec![ "add" , "typescript" , "-W" , "-D" ] ) ;
2029+ }
2030+
2031+ #[ test]
2032+ fn test_npm_basic_add ( ) {
2033+ let pm = create_mock_package_manager ( PackageManagerType :: Npm ) ;
2034+ let args = pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ ] , false , false , & [ ] ) ;
2035+ assert_eq ! ( args, vec![ "install" , "react" ] ) ;
2036+ }
2037+
2038+ #[ test]
2039+ fn test_npm_add_with_workspace ( ) {
2040+ let pm = create_mock_package_manager ( PackageManagerType :: Npm ) ;
2041+ let args =
2042+ pm. build_add_args ( & [ "react" . to_string ( ) ] , & [ "app" . to_string ( ) ] , false , false , & [ ] ) ;
2043+ assert_eq ! ( args, vec![ "install" , "react" , "--workspace" , "app" ] ) ;
2044+ }
2045+
2046+ #[ test]
2047+ fn test_npm_add_multiple_workspaces ( ) {
2048+ let pm = create_mock_package_manager ( PackageManagerType :: Npm ) ;
2049+ let args = pm. build_add_args (
2050+ & [ "lodash" . to_string ( ) ] ,
2051+ & [ "app" . to_string ( ) , "web" . to_string ( ) ] ,
2052+ false ,
2053+ false ,
2054+ & [ ] ,
2055+ ) ;
2056+ assert_eq ! ( args, vec![ "install" , "lodash" , "--workspace" , "app" , "--workspace" , "web" ] ) ;
2057+ }
2058+ }
18962059}
0 commit comments