Skip to main content

zad_cli/cli/
service_list.rs

1use clap::Args;
2use serde::Serialize;
3
4use zad::config;
5use zad::error::Result;
6use zad::service::registry::SERVICES;
7
8#[derive(Debug, Args)]
9pub struct ListArgs {
10    /// Emit machine-readable JSON instead of the human-readable table.
11    #[arg(long)]
12    pub json: bool,
13}
14
15#[derive(Debug, Serialize)]
16struct ListOutput {
17    command: &'static str,
18    services: Vec<ServiceRow>,
19}
20
21#[derive(Debug, Serialize)]
22struct ServiceRow {
23    name: &'static str,
24    global: bool,
25    local: bool,
26    enabled: bool,
27}
28
29pub fn run(args: ListArgs) -> Result<()> {
30    let slug = config::path::project_slug()?;
31    let project_path = config::path::project_config_path()?;
32    let project_cfg = config::load_from(&project_path)?;
33
34    let mut rows = Vec::with_capacity(SERVICES.len());
35    let mut any_configured = false;
36    for name in SERVICES {
37        let global = config::path::global_service_config_path(name)?.exists();
38        let local = config::path::project_service_config_path_for(&slug, name)?.exists();
39        let enabled = project_cfg.has_service(name);
40        if global || local || enabled {
41            any_configured = true;
42        }
43        rows.push(ServiceRow {
44            name,
45            global,
46            local,
47            enabled,
48        });
49    }
50
51    if args.json {
52        let out = ListOutput {
53            command: "service.list",
54            services: rows,
55        };
56        println!("{}", serde_json::to_string_pretty(&out).unwrap());
57        return Ok(());
58    }
59
60    let name_w = rows
61        .iter()
62        .map(|r| r.name.len())
63        .chain(std::iter::once("SERVICE".len()))
64        .max()
65        .unwrap_or(0);
66    let global_w = "GLOBAL".len();
67    let local_w = "LOCAL".len();
68
69    println!(
70        "{:name_w$}  {:global_w$}  {:local_w$}  PROJECT",
71        "SERVICE", "GLOBAL", "LOCAL"
72    );
73    for row in &rows {
74        println!(
75            "{:name_w$}  {:global_w$}  {:local_w$}  {}",
76            row.name,
77            yes_no(row.global),
78            yes_no(row.local),
79            if row.enabled { "enabled" } else { "disabled" },
80        );
81    }
82
83    if !any_configured {
84        println!();
85        println!("No services configured. Run `zad service create <service>` to start.");
86    }
87
88    Ok(())
89}
90
91fn yes_no(b: bool) -> &'static str {
92    if b { "yes" } else { "no" }
93}