1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum SynapseClientError {
6 #[error("Connection error: {0}")]
7 Connection(String),
8 #[error("Request error: {0}")]
9 Request(String),
10 #[error("Query error: {query_name}: {message}")]
11 Query { query_name: String, message: String },
12}
13
14pub type Result<T> = std::result::Result<T, SynapseClientError>;
15
16#[derive(Debug, Clone)]
29pub struct Client {
30 base_url: String,
31 http: reqwest::Client,
32}
33
34impl Client {
35 pub fn new(base_url: &str) -> Self {
36 Self {
37 base_url: base_url.trim_end_matches('/').to_string(),
38 http: reqwest::Client::new(),
39 }
40 }
41
42 pub fn with_timeout(base_url: &str, timeout: std::time::Duration) -> Self {
43 Self {
44 base_url: base_url.trim_end_matches('/').to_string(),
45 http: reqwest::Client::builder()
46 .timeout(timeout)
47 .build()
48 .unwrap_or_default(),
49 }
50 }
51
52 pub async fn emit(&self, event: &str, payload: serde_json::Value) -> Result<serde_json::Value> {
54 let url = format!("{}/emit", self.base_url);
55 let body = serde_json::json!({
56 "event": event,
57 "payload": payload,
58 });
59
60 let resp = self
61 .http
62 .post(&url)
63 .json(&body)
64 .send()
65 .await
66 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
67
68 if !resp.status().is_success() {
69 let msg = resp.text().await.unwrap_or_default();
70 return Err(SynapseClientError::Request(msg));
71 }
72
73 resp.json()
74 .await
75 .map_err(|e| SynapseClientError::Request(e.to_string()))
76 }
77
78 pub async fn query(
80 &self,
81 query_name: &str,
82 params: serde_json::Value,
83 ) -> Result<serde_json::Value> {
84 let url = format!("{}/query", self.base_url);
85 let body = serde_json::json!({
86 "query": query_name,
87 "params": params,
88 });
89
90 let resp = self
91 .http
92 .post(&url)
93 .json(&body)
94 .send()
95 .await
96 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
97
98 if !resp.status().is_success() {
99 let msg = resp.text().await.unwrap_or_default();
100 return Err(SynapseClientError::Query {
101 query_name: query_name.into(),
102 message: msg,
103 });
104 }
105
106 resp.json()
107 .await
108 .map_err(|e| SynapseClientError::Request(e.to_string()))
109 }
110
111 pub async fn health(&self) -> Result<HealthResponse> {
113 let url = format!("{}/health", self.base_url);
114 let resp = self
115 .http
116 .get(&url)
117 .send()
118 .await
119 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
120
121 resp.json()
122 .await
123 .map_err(|e| SynapseClientError::Request(e.to_string()))
124 }
125
126 pub async fn status(&self) -> Result<StatusResponse> {
128 let url = format!("{}/status", self.base_url);
129 let resp = self
130 .http
131 .get(&url)
132 .send()
133 .await
134 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
135
136 resp.json()
137 .await
138 .map_err(|e| SynapseClientError::Request(e.to_string()))
139 }
140
141 pub async fn reload(&self) -> Result<serde_json::Value> {
143 let url = format!("{}/reload", self.base_url);
144 let resp = self
145 .http
146 .post(&url)
147 .send()
148 .await
149 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
150
151 if !resp.status().is_success() {
152 let msg = resp.text().await.unwrap_or_default();
153 return Err(SynapseClientError::Request(msg));
154 }
155
156 resp.json()
157 .await
158 .map_err(|e| SynapseClientError::Request(e.to_string()))
159 }
160
161 pub async fn clear(&self) -> Result<serde_json::Value> {
163 let url = format!("{}/clear", self.base_url);
164 let resp = self
165 .http
166 .post(&url)
167 .send()
168 .await
169 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
170
171 if !resp.status().is_success() {
172 let msg = resp.text().await.unwrap_or_default();
173 return Err(SynapseClientError::Request(msg));
174 }
175
176 resp.json()
177 .await
178 .map_err(|e| SynapseClientError::Request(e.to_string()))
179 }
180
181 pub async fn inspect(&self) -> Result<serde_json::Value> {
183 let url = format!("{}/inspect", self.base_url);
184 let resp = self
185 .http
186 .get(&url)
187 .send()
188 .await
189 .map_err(|e| SynapseClientError::Connection(e.to_string()))?;
190
191 if !resp.status().is_success() {
192 let msg = resp.text().await.unwrap_or_default();
193 return Err(SynapseClientError::Request(msg));
194 }
195
196 resp.json()
197 .await
198 .map_err(|e| SynapseClientError::Request(e.to_string()))
199 }
200
201 pub async fn ping(&self) -> bool {
203 self.health().await.is_ok()
204 }
205}
206
207#[derive(Debug, Serialize, Deserialize)]
208pub struct HealthResponse {
209 pub status: String,
210 pub uptime_secs: i64,
211}
212
213#[derive(Debug, Serialize, Deserialize)]
214pub struct StatusResponse {
215 pub status: String,
216 pub handlers: Vec<String>,
217 pub queries: Vec<String>,
218 pub memories: Vec<String>,
219 pub uptime_secs: i64,
220}