mielin_cli/types/
node.rs

1//! Node-related data structures
2
3use crate::output::MultiFormatDisplay;
4use comfy_table::{presets::UTF8_FULL, Cell, Color, ContentArrangement, Table};
5use serde::Serialize;
6
7#[derive(Debug, Serialize)]
8pub struct NodeInfo {
9    pub id: String,
10    pub role: String,
11    pub state: String,
12    pub address: String,
13    pub agents: usize,
14    pub uptime: String,
15    pub version: String,
16}
17
18#[derive(Debug, Serialize)]
19pub struct NodeList {
20    pub nodes: Vec<NodeInfo>,
21    pub total: usize,
22}
23
24impl MultiFormatDisplay for NodeList {
25    fn to_table(&self) -> Table {
26        let mut table = Table::new();
27        table
28            .load_preset(UTF8_FULL)
29            .set_content_arrangement(ContentArrangement::Dynamic)
30            .set_header(vec![
31                Cell::new("ID").fg(Color::Cyan),
32                Cell::new("ROLE").fg(Color::Cyan),
33                Cell::new("STATE").fg(Color::Cyan),
34                Cell::new("ADDRESS").fg(Color::Cyan),
35                Cell::new("AGENTS").fg(Color::Cyan),
36                Cell::new("UPTIME").fg(Color::Cyan),
37            ]);
38
39        for node in &self.nodes {
40            let state_color = match node.state.as_str() {
41                "Running" => Color::Green,
42                "Stopped" => Color::Red,
43                _ => Color::Yellow,
44            };
45
46            table.add_row(vec![
47                Cell::new(&node.id[..8]),
48                Cell::new(&node.role),
49                Cell::new(&node.state).fg(state_color),
50                Cell::new(&node.address),
51                Cell::new(node.agents.to_string()),
52                Cell::new(&node.uptime),
53            ]);
54        }
55
56        table
57    }
58
59    fn to_quiet(&self) -> String {
60        self.nodes
61            .iter()
62            .map(|n| n.id.clone())
63            .collect::<Vec<_>>()
64            .join("\n")
65    }
66}
67
68#[derive(Debug, Serialize)]
69pub struct MeshStatus {
70    pub state: String,
71    pub local_node: String,
72    pub connected_peers: usize,
73    pub total_agents: usize,
74    pub gossip_round: u64,
75    pub dht_entries: usize,
76}
77
78impl MultiFormatDisplay for MeshStatus {
79    fn to_table(&self) -> Table {
80        let mut table = Table::new();
81        table
82            .load_preset(UTF8_FULL)
83            .set_content_arrangement(ContentArrangement::Dynamic);
84
85        let state_color = match self.state.as_str() {
86            "Healthy" => Color::Green,
87            "Degraded" => Color::Yellow,
88            "Critical" => Color::Red,
89            _ => Color::White,
90        };
91
92        table.add_row(vec![
93            Cell::new("Status").fg(Color::Cyan),
94            Cell::new(&self.state).fg(state_color),
95        ]);
96        table.add_row(vec![
97            Cell::new("Local Node").fg(Color::Cyan),
98            Cell::new(&self.local_node),
99        ]);
100        table.add_row(vec![
101            Cell::new("Connected Peers").fg(Color::Cyan),
102            Cell::new(self.connected_peers.to_string()),
103        ]);
104        table.add_row(vec![
105            Cell::new("Total Agents").fg(Color::Cyan),
106            Cell::new(self.total_agents.to_string()),
107        ]);
108        table.add_row(vec![
109            Cell::new("Gossip Round").fg(Color::Cyan),
110            Cell::new(self.gossip_round.to_string()),
111        ]);
112        table.add_row(vec![
113            Cell::new("DHT Entries").fg(Color::Cyan),
114            Cell::new(self.dht_entries.to_string()),
115        ]);
116
117        table
118    }
119
120    fn to_quiet(&self) -> String {
121        self.state.clone()
122    }
123}