1use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5use std::time::{SystemTime, UNIX_EPOCH};
6use tokio::sync::{broadcast, RwLock};
7use vibe_graph_core::{GitChangeSnapshot, SourceCodeGraph};
8
9pub struct ApiState {
11 pub graph: Arc<RwLock<SourceCodeGraph>>,
13 pub git_changes: Arc<RwLock<GitChangeSnapshot>>,
15 pub tx: broadcast::Sender<WsServerMessage>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ApiResponse<T> {
22 pub data: T,
24 pub timestamp: u64,
26}
27
28impl<T> ApiResponse<T> {
29 pub fn new(data: T) -> Self {
31 let timestamp = SystemTime::now()
32 .duration_since(UNIX_EPOCH)
33 .map(|d| d.as_millis() as u64)
34 .unwrap_or(0);
35 Self { data, timestamp }
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct HealthResponse {
42 pub status: String,
44 pub nodes: usize,
46 pub edges: usize,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52#[serde(tag = "type", rename_all = "snake_case")]
53pub enum WsServerMessage {
54 GitChanges {
56 data: GitChangeSnapshot,
58 },
59 GraphUpdated {
61 node_count: usize,
63 edge_count: usize,
65 },
66 Error {
68 code: String,
70 message: String,
72 },
73 Pong,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79#[serde(tag = "type", rename_all = "snake_case")]
80pub enum WsClientMessage {
81 Subscribe {
83 topics: Vec<String>,
85 },
86 Ping,
88}