cellstate/entity/
event_dag.rs

1//! `cellstate event-dag` — Query the event DAG (causal event graph).
2//!
3//! Subcommands: get, ancestors, descendants, siblings, lca, by-kind.
4
5use anyhow::Result;
6use clap::{Arg, ArgMatches, Command};
7
8use super::client::ApiClient;
9use super::output::OutputConfig;
10
11const BASE: &str = "/api/v1/event-dag";
12
13pub fn build_command() -> Command {
14    Command::new("event-dag")
15        .about("Query the event DAG (causal event graph)")
16        .subcommand_required(true)
17        .subcommand(
18            Command::new("get")
19                .about("Get an event by ID")
20                .arg(Arg::new("id").required(true).help("Event ID")),
21        )
22        .subcommand(
23            Command::new("ancestors")
24                .about("Get ancestors of an event")
25                .arg(Arg::new("id").required(true).help("Event ID")),
26        )
27        .subcommand(
28            Command::new("descendants")
29                .about("Get descendants of an event")
30                .arg(Arg::new("id").required(true).help("Event ID")),
31        )
32        .subcommand(
33            Command::new("siblings")
34                .about("Get siblings of an event")
35                .arg(Arg::new("id").required(true).help("Event ID")),
36        )
37        .subcommand(
38            Command::new("lca")
39                .about("Find lowest common ancestor of two events")
40                .arg(Arg::new("id").required(true).help("First event ID"))
41                .arg(Arg::new("other-id").required(true).help("Second event ID")),
42        )
43        .subcommand(
44            Command::new("by-kind")
45                .about("List events by kind")
46                .arg(Arg::new("kind").required(true).help("Event kind")),
47        )
48}
49
50pub async fn dispatch(
51    matches: &ArgMatches,
52    client: &ApiClient,
53    output: &OutputConfig,
54    _session: &crate::session::CliSession,
55) -> Result<()> {
56    match matches.subcommand() {
57        Some(("get", sub)) => {
58            let id = sub.get_one::<String>("id").unwrap();
59            let resp: serde_json::Value = client.get_raw(&format!("{BASE}/{id}")).await?;
60            output.print_value(&resp);
61        }
62        Some(("ancestors", sub)) => {
63            let id = sub.get_one::<String>("id").unwrap();
64            let resp: serde_json::Value = client.get_raw(&format!("{BASE}/{id}/ancestors")).await?;
65            output.print_value(&resp);
66        }
67        Some(("descendants", sub)) => {
68            let id = sub.get_one::<String>("id").unwrap();
69            let resp: serde_json::Value =
70                client.get_raw(&format!("{BASE}/{id}/descendants")).await?;
71            output.print_value(&resp);
72        }
73        Some(("siblings", sub)) => {
74            let id = sub.get_one::<String>("id").unwrap();
75            let resp: serde_json::Value = client.get_raw(&format!("{BASE}/{id}/siblings")).await?;
76            output.print_value(&resp);
77        }
78        Some(("lca", sub)) => {
79            let id = sub.get_one::<String>("id").unwrap();
80            let other_id = sub.get_one::<String>("other-id").unwrap();
81            let resp: serde_json::Value = client
82                .get_raw(&format!("{BASE}/{id}/lca/{other_id}"))
83                .await?;
84            output.print_value(&resp);
85        }
86        Some(("by-kind", sub)) => {
87            let kind = sub.get_one::<String>("kind").unwrap();
88            let resp: serde_json::Value = client.get_raw(&format!("{BASE}/by-kind/{kind}")).await?;
89            output.print_value(&resp);
90        }
91        _ => unreachable!("subcommand_required(true) prevents this"),
92    }
93    Ok(())
94}