Skip to main content

xbp_cli/cli/
router.rs

1use super::app::AppContext;
2use super::commands::{Cli, Commands};
3use super::error::CliResult;
4use super::handle_dns;
5#[cfg(feature = "docker")]
6use super::handle_docker;
7use super::handle_domains;
8#[cfg(feature = "kubernetes")]
9use super::handle_kubernetes;
10#[cfg(feature = "monitoring")]
11use super::handle_monitoring;
12#[cfg(feature = "nordvpn")]
13use super::handle_nordvpn;
14#[cfg(feature = "secrets")]
15use super::handle_secrets;
16use super::{
17    handle_api, handle_cloudflared, handle_commit, handle_config, handle_curl, handle_diag,
18    handle_done, handle_env, handle_flush, handle_generate, handle_init, handle_install,
19    handle_list, handle_login, handle_logs, handle_logs_flag, handle_monitor, handle_network,
20    handle_nginx, handle_no_command, handle_ports, handle_publish, handle_redeploy,
21    handle_redeploy_v2, handle_resurrect, handle_service, handle_services, handle_setup,
22    handle_snapshot, handle_ssh, handle_start, handle_stop, handle_tail, handle_version,
23};
24use std::future::Future;
25use std::pin::Pin;
26
27type DispatchFuture<'a> = Pin<Box<dyn Future<Output = CliResult<()>> + 'a>>;
28
29pub fn dispatch(cli: Cli, ctx: &mut AppContext) -> DispatchFuture<'_> {
30    let debug = ctx.debug();
31    let Cli {
32        logs,
33        list,
34        port,
35        command,
36        ..
37    } = cli;
38
39    if logs {
40        return Box::pin(handle_logs_flag());
41    }
42
43    if list && command.is_none() {
44        return Box::pin(handle_list(debug));
45    }
46
47    match command {
48        Some(Commands::Ports(cmd)) => Box::pin(handle_ports(cmd, port, debug)),
49        Some(Commands::Commit(cmd)) => Box::pin(handle_commit(cmd)),
50        Some(Commands::Init) => Box::pin(handle_init(debug)),
51        Some(Commands::Setup) => Box::pin(handle_setup(debug)),
52        Some(Commands::Redeploy { service_name }) => Box::pin(handle_redeploy(service_name, debug)),
53        Some(Commands::RedeployV2(cmd)) => Box::pin(handle_redeploy_v2(cmd, debug)),
54        Some(Commands::Config(cmd)) => Box::pin(handle_config(cmd, debug)),
55        Some(Commands::Install { list, package }) => Box::pin(handle_install(package, list, debug)),
56        Some(Commands::Logs(cmd)) => Box::pin(handle_logs(cmd, debug)),
57        Some(Commands::Ssh(cmd)) => Box::pin(handle_ssh(cmd, debug)),
58        Some(Commands::Cloudflared(cmd)) => Box::pin(handle_cloudflared(cmd, debug)),
59        Some(Commands::List) => Box::pin(handle_list(debug)),
60        Some(Commands::Curl(cmd)) => Box::pin(handle_curl(cmd, debug)),
61        Some(Commands::Services) => Box::pin(handle_services(debug)),
62        Some(Commands::Service {
63            command,
64            service_name,
65        }) => Box::pin(handle_service(command, service_name, debug)),
66        Some(Commands::Nginx(cmd)) => Box::pin(handle_nginx(cmd.command, debug)),
67        Some(Commands::Network(cmd)) => Box::pin(handle_network(cmd, debug)),
68        Some(Commands::Diag(cmd)) => Box::pin(handle_diag(cmd, debug)),
69        Some(Commands::Monitor(cmd)) => Box::pin(handle_monitor(cmd, debug)),
70        Some(Commands::Snapshot) => Box::pin(handle_snapshot(debug)),
71        Some(Commands::Resurrect) => Box::pin(handle_resurrect(debug)),
72        Some(Commands::Stop { target }) => Box::pin(handle_stop(target, debug)),
73        Some(Commands::Flush { target }) => Box::pin(handle_flush(target, debug)),
74        Some(Commands::Login) => Box::pin(handle_login()),
75        Some(Commands::Version(cmd)) => Box::pin(handle_version(cmd, debug)),
76        Some(Commands::Publish(cmd)) => Box::pin(handle_publish(cmd, debug)),
77        Some(Commands::Env { target }) => Box::pin(handle_env(target, debug)),
78        Some(Commands::Tail(cmd)) => Box::pin(handle_tail(cmd, debug)),
79        Some(Commands::Start { args }) => Box::pin(handle_start(args, debug)),
80        Some(Commands::Generate(cmd)) => Box::pin(handle_generate(cmd, debug)),
81        Some(Commands::Api(cmd)) => Box::pin(handle_api(cmd, debug)),
82        #[cfg(feature = "docker")]
83        Some(Commands::Docker(cmd)) => Box::pin(handle_docker(cmd, debug)),
84        #[cfg(feature = "secrets")]
85        Some(Commands::Secrets(cmd)) => Box::pin(handle_secrets(cmd, debug)),
86        Some(Commands::Dns(cmd)) => Box::pin(handle_dns(cmd, debug)),
87        Some(Commands::Domains(cmd)) => Box::pin(handle_domains(cmd, debug)),
88        Some(Commands::Done(cmd)) => Box::pin(handle_done(cmd, debug)),
89        #[cfg(feature = "kubernetes")]
90        Some(Commands::Kubernetes(cmd)) => Box::pin(handle_kubernetes(cmd, debug)),
91        #[cfg(feature = "nordvpn")]
92        Some(Commands::Nordvpn(cmd)) => Box::pin(handle_nordvpn(cmd, debug)),
93        #[cfg(feature = "monitoring")]
94        Some(Commands::Monitoring(cmd)) => Box::pin(handle_monitoring(cmd)),
95        None => {
96            // preserve previous no-command behavior
97            Box::pin(handle_no_command(port, debug))
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105    use clap::Parser;
106
107    #[test]
108    fn dispatch_future_is_boxed_and_small() {
109        let cli = Cli::parse_from(["xbp", "login"]);
110        let mut ctx = AppContext::new(false);
111        let future = dispatch(cli, &mut ctx);
112        assert!(std::mem::size_of_val(&future) <= 2 * std::mem::size_of::<usize>());
113    }
114}