@@ -1186,24 +1186,49 @@ fn shell_split(input: &str) -> Vec<String> {
11861186 tokens
11871187}
11881188
1189- /// Merge pnpm global filters args with other ones
1189+ /// Merge pnpm global filters args with other ones for standard String-based commands
11901190fn merge_pnpm_args ( filters : & [ String ] , args : & [ String ] ) -> Vec < String > {
11911191 filters
11921192 . iter ( )
11931193 . map ( |filter| format ! ( "--filter={}" , filter) )
1194- . chain ( args. iter ( ) . map ( |arg| arg . to_string ( ) ) )
1194+ . chain ( args. iter ( ) . cloned ( ) )
11951195 . collect ( )
11961196}
11971197
1198- /// Merge pnpm global filters args with other ones
1198+ /// Merge pnpm global filters args with other ones, using OsString for passthrough compatibility
11991199fn merge_pnpm_args_os ( filters : & [ String ] , args : & [ OsString ] ) -> Vec < OsString > {
12001200 filters
12011201 . iter ( )
12021202 . map ( |filter| OsString :: from ( format ! ( "--filter={}" , filter) ) )
1203- . chain ( args. iter ( ) . map ( |arg| arg . to_os_string ( ) ) )
1203+ . chain ( args. iter ( ) . cloned ( ) )
12041204 . collect ( )
12051205}
12061206
1207+ /// Validate that pnpm filters are only used in the global context, not before subcommands like build or tsc.
1208+ fn validate_pnpm_filters ( filters : & [ String ] , command : & PnpmCommands ) -> Option < String > {
1209+ // Check if this is a Build or Typecheck command with filters
1210+ match command {
1211+ PnpmCommands :: Build { .. } | PnpmCommands :: Typecheck { .. } => {
1212+ // FIXME: if filters are present, we should find out which workspaces are build before running build
1213+ if !filters. is_empty ( ) {
1214+ let cmd_name = match command {
1215+ PnpmCommands :: Build { .. } => "build" ,
1216+ PnpmCommands :: Typecheck { .. } => "tsc" ,
1217+ _ => unreachable ! ( ) ,
1218+ } ;
1219+ let msg = format ! (
1220+ "[rtk] warning: --filter is not yet supported for pnpm {}, filters preceding the subcommand will be ignored" ,
1221+ cmd_name
1222+ ) ;
1223+ eprintln ! ( "{}" , msg) ;
1224+ return Some ( msg) ;
1225+ }
1226+ None
1227+ }
1228+ _ => None ,
1229+ }
1230+ }
1231+
12071232fn main ( ) -> Result < ( ) > {
12081233 // Fire-and-forget telemetry ping (1/day, non-blocking)
12091234 telemetry:: maybe_ping ( ) ;
@@ -1426,42 +1451,49 @@ fn main() -> Result<()> {
14261451 psql_cmd:: run ( & args, cli. verbose ) ?;
14271452 }
14281453
1429- Commands :: Pnpm { filter, command } => match command {
1430- PnpmCommands :: List { depth, args } => {
1431- pnpm_cmd:: run (
1432- pnpm_cmd:: PnpmCommand :: List { depth } ,
1433- & merge_pnpm_args ( & filter, & args) ,
1434- cli. verbose ,
1435- ) ?;
1436- }
1437- PnpmCommands :: Outdated { args } => {
1438- pnpm_cmd:: run (
1439- pnpm_cmd:: PnpmCommand :: Outdated ,
1440- & merge_pnpm_args ( & filter, & args) ,
1441- cli. verbose ,
1442- ) ?;
1454+ Commands :: Pnpm { filter, command } => {
1455+ // Warns user if filters are used with unsupported subcommands like build or typecheck
1456+ if let Some ( warning) = validate_pnpm_filters ( & filter, & command) {
1457+ eprintln ! ( "{}" , warning) ;
14431458 }
1444- PnpmCommands :: Install { packages, args } => {
1445- pnpm_cmd:: run (
1446- pnpm_cmd:: PnpmCommand :: Install { packages } ,
1447- & merge_pnpm_args ( & filter, & args) ,
1448- cli. verbose ,
1449- ) ?;
1450- }
1451- PnpmCommands :: Build { args } => {
1452- let mut build_args: Vec < String > = vec ! [ "build" . into( ) ] ;
1453- build_args. extend ( args) ;
1454- let os_args: Vec < OsString > = build_args. into_iter ( ) . map ( OsString :: from) . collect ( ) ;
1455- pnpm_cmd:: run_passthrough ( & merge_pnpm_args_os ( & filter, & os_args) , cli. verbose ) ?;
1456- }
1457- PnpmCommands :: Typecheck { args } => {
1458- // FIXME: if filters are present, we should find out which workspaces are typechecked before running tsc
1459- tsc_cmd:: run ( & args, cli. verbose ) ?;
1460- }
1461- PnpmCommands :: Other ( args) => {
1462- pnpm_cmd:: run_passthrough ( & merge_pnpm_args_os ( & filter, & args) , cli. verbose ) ?;
1459+
1460+ match command {
1461+ PnpmCommands :: List { depth, args } => {
1462+ pnpm_cmd:: run (
1463+ pnpm_cmd:: PnpmCommand :: List { depth } ,
1464+ & merge_pnpm_args ( & filter, & args) ,
1465+ cli. verbose ,
1466+ ) ?;
1467+ }
1468+ PnpmCommands :: Outdated { args } => {
1469+ pnpm_cmd:: run (
1470+ pnpm_cmd:: PnpmCommand :: Outdated ,
1471+ & merge_pnpm_args ( & filter, & args) ,
1472+ cli. verbose ,
1473+ ) ?;
1474+ }
1475+ PnpmCommands :: Install { packages, args } => {
1476+ pnpm_cmd:: run (
1477+ pnpm_cmd:: PnpmCommand :: Install { packages } ,
1478+ & merge_pnpm_args ( & filter, & args) ,
1479+ cli. verbose ,
1480+ ) ?;
1481+ }
1482+ PnpmCommands :: Build { args } => {
1483+ let mut build_args: Vec < String > = vec ! [ "build" . into( ) ] ;
1484+ build_args. extend ( args) ;
1485+ let os_args: Vec < OsString > =
1486+ build_args. into_iter ( ) . map ( OsString :: from) . collect ( ) ;
1487+ pnpm_cmd:: run_passthrough ( & merge_pnpm_args_os ( & filter, & os_args) , cli. verbose ) ?;
1488+ }
1489+ PnpmCommands :: Typecheck { args } => {
1490+ tsc_cmd:: run ( & args, cli. verbose ) ?;
1491+ }
1492+ PnpmCommands :: Other ( args) => {
1493+ pnpm_cmd:: run_passthrough ( & merge_pnpm_args_os ( & filter, & args) , cli. verbose ) ?;
1494+ }
14631495 }
1464- } ,
1496+ }
14651497
14661498 Commands :: Err { command } => {
14671499 let cmd = command. join ( " " ) ;
@@ -2511,6 +2543,14 @@ mod tests {
25112543 }
25122544 }
25132545
2546+ #[ test]
2547+ fn test_merge_filters_with_no_args ( ) {
2548+ let filters = vec ! [ ] ;
2549+ let args = vec ! [ "--depth=0" . to_string( ) , "--no-verbose" . to_string( ) ] ;
2550+ let expected_args = vec ! [ "--depth=0" , "--no-verbose" ] ;
2551+ assert_eq ! ( merge_pnpm_args( & filters, & args) , expected_args) ;
2552+ }
2553+
25142554 #[ test]
25152555 fn test_merge_filters_with_args ( ) {
25162556 let filters = vec ! [ "@app1" . to_string( ) , "@app2" . to_string( ) ] ;
@@ -2529,6 +2569,14 @@ mod tests {
25292569 assert_eq ! ( merge_pnpm_args( & filters, & args) , expected_args) ;
25302570 }
25312571
2572+ #[ test]
2573+ fn test_merge_filters_with_no_args_os ( ) {
2574+ let filters = vec ! [ ] ;
2575+ let args = vec ! [ OsString :: from( "--depth=0" ) ] ;
2576+ let expected_args = vec ! [ OsString :: from( "--depth=0" ) ] ;
2577+ assert_eq ! ( merge_pnpm_args_os( & filters, & args) , expected_args) ;
2578+ }
2579+
25322580 #[ test]
25332581 fn test_merge_filters_with_args_os ( ) {
25342582 let filters = vec ! [ "@app1" . to_string( ) ] ;
@@ -2542,15 +2590,22 @@ mod tests {
25422590
25432591 #[ test]
25442592 fn test_pnpm_subcommand_with_filter ( ) {
2545- let cli = Cli :: try_parse_from ( [ "rtk" , "pnpm" , "--filter" , "@app1" , "list" ] ) . unwrap ( ) ;
2593+ let cli = Cli :: try_parse_from ( [
2594+ "rtk" , "pnpm" , "--filter" , "@app1" , "--filter" , "@app2" , "list" , "--filter" , "@app3" ,
2595+ "--filter" , "@app4" , "--prod" ,
2596+ ] )
2597+ . unwrap ( ) ;
25462598 match cli. command {
25472599 Commands :: Pnpm {
25482600 filter,
25492601 command : PnpmCommands :: List { depth, args } ,
25502602 } => {
25512603 assert_eq ! ( depth, 0 ) ;
2552- assert_eq ! ( filter, vec![ "@app1" ] ) ;
2553- assert ! ( args. is_empty( ) ) ;
2604+ assert_eq ! ( filter, vec![ "@app1" , "@app2" ] ) ;
2605+ assert_eq ! (
2606+ args,
2607+ vec![ "--filter" , "@app3" , "--filter" , "@app4" , "--prod" ]
2608+ ) ;
25542609 }
25552610 _ => panic ! ( "Expected Pnpm List command" ) ,
25562611 }
@@ -2568,4 +2623,89 @@ mod tests {
25682623 _ => panic ! ( "Expected Pnpm command" ) ,
25692624 }
25702625 }
2626+
2627+ #[ test]
2628+ fn test_pnpm_build_without_filters ( ) {
2629+ let cli = Cli :: try_parse_from ( [
2630+ "rtk" , "pnpm" , "build" , "--filter" , "@app3" , "--filter" , "@app4" ,
2631+ ] )
2632+ . unwrap ( ) ;
2633+ match cli. command {
2634+ Commands :: Pnpm { filter, command } => {
2635+ let warning = validate_pnpm_filters ( & filter, & command) ;
2636+
2637+ assert ! ( filter. is_empty( ) ) ;
2638+ assert ! ( warning. is_none( ) )
2639+ }
2640+ _ => panic ! ( "Expected Pnpm Build command" ) ,
2641+ }
2642+ }
2643+
2644+ #[ test]
2645+ fn test_pnpm_build_with_filters ( ) {
2646+ let cli = Cli :: try_parse_from ( [
2647+ "rtk" , "pnpm" , "--filter" , "@app1" , "--filter" , "@app2" , "build" , "--filter" , "@app3" ,
2648+ "--filter" , "@app4" ,
2649+ ] )
2650+ . unwrap ( ) ;
2651+ match cli. command {
2652+ Commands :: Pnpm { filter, command } => {
2653+ let warning = validate_pnpm_filters ( & filter, & command) . unwrap ( ) ;
2654+
2655+ assert_eq ! ( filter, vec![ "@app1" , "@app2" ] ) ;
2656+ assert_eq ! ( warning, "[rtk] warning: --filter is not yet supported for pnpm build, filters preceding the subcommand will be ignored" )
2657+ }
2658+ _ => panic ! ( "Expected Pnpm Build command" ) ,
2659+ }
2660+ }
2661+
2662+ #[ test]
2663+ fn test_pnpm_typecheck_without_filters ( ) {
2664+ let cli = Cli :: try_parse_from ( [
2665+ "rtk" ,
2666+ "pnpm" ,
2667+ "typecheck" ,
2668+ "--filter" ,
2669+ "@app3" ,
2670+ "--filter" ,
2671+ "@app4" ,
2672+ ] )
2673+ . unwrap ( ) ;
2674+ match cli. command {
2675+ Commands :: Pnpm { filter, command } => {
2676+ let warning = validate_pnpm_filters ( & filter, & command) ;
2677+
2678+ assert ! ( filter. is_empty( ) ) ;
2679+ assert ! ( warning. is_none( ) )
2680+ }
2681+ _ => panic ! ( "Expected Pnpm Build command" ) ,
2682+ }
2683+ }
2684+
2685+ #[ test]
2686+ fn test_pnpm_typecheck_with_filters ( ) {
2687+ let cli = Cli :: try_parse_from ( [
2688+ "rtk" ,
2689+ "pnpm" ,
2690+ "--filter" ,
2691+ "@app1" ,
2692+ "--filter" ,
2693+ "@app2" ,
2694+ "typecheck" ,
2695+ "--filter" ,
2696+ "@app3" ,
2697+ "--filter" ,
2698+ "@app4" ,
2699+ ] )
2700+ . unwrap ( ) ;
2701+ match cli. command {
2702+ Commands :: Pnpm { filter, command } => {
2703+ let warning = validate_pnpm_filters ( & filter, & command) . unwrap ( ) ;
2704+
2705+ assert_eq ! ( filter, vec![ "@app1" , "@app2" ] ) ;
2706+ assert_eq ! ( warning, "[rtk] warning: --filter is not yet supported for pnpm tsc, filters preceding the subcommand will be ignored" )
2707+ }
2708+ _ => panic ! ( "Expected Pnpm Build command" ) ,
2709+ }
2710+ }
25712711}
0 commit comments