zad_cli/cli/
service_list.rs1use 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 #[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}