1use reqwest::Method;
10use serde::{Deserialize, Serialize};
11
12use crate::client::{HeyoClient, HeyoClientOptions, RequestOptions};
13use crate::commands::encode_path;
14use crate::errors::HeyoError;
15
16#[derive(Debug, Clone, Deserialize, Serialize)]
17pub struct NetworkInfo {
18 pub id: String,
19 pub account_id: String,
20 pub name: String,
21 pub is_default: bool,
22 #[serde(default)]
23 pub description: Option<String>,
24 pub created_at: String,
25 pub updated_at: String,
26}
27
28#[derive(Debug, Clone, Deserialize, Serialize)]
29pub struct NetworkMember {
30 pub network_id: String,
31 pub sandbox_kind: String,
32 pub sandbox_ref: String,
33 #[serde(default)]
34 pub device_name: Option<String>,
35 pub registered_at: String,
36 #[serde(default)]
37 pub last_seen_at: Option<String>,
38}
39
40#[derive(Debug, Clone, Default, Serialize)]
41pub struct NetworkCreateOptions {
42 pub name: String,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub description: Option<String>,
45}
46
47#[derive(Debug, Clone, Default, Serialize)]
48pub struct NetworkUpdateOptions {
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub name: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
54 pub description: Option<Option<String>>,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
58#[serde(rename_all = "lowercase")]
59pub enum NetworkMemberKind {
60 Local,
61 Deployed,
62}
63
64impl NetworkMemberKind {
65 pub fn as_str(&self) -> &'static str {
66 match self {
67 NetworkMemberKind::Local => "local",
68 NetworkMemberKind::Deployed => "deployed",
69 }
70 }
71}
72
73#[derive(Debug, Clone, Serialize)]
74pub struct NetworkMemberRegistration {
75 pub sandbox_kind: NetworkMemberKind,
76 pub sandbox_ref: String,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub device_name: Option<String>,
79}
80
81#[derive(Debug, Clone, Deserialize, Serialize)]
86pub struct NetworkService {
87 pub id: String,
88 pub network_id: String,
89 pub name: String,
91 pub address: String,
93 pub sandbox_kind: String,
94 pub sandbox_ref: String,
95 pub port: u16,
96 pub protocol: String,
97 pub status: String,
98 #[serde(default)]
100 pub connection_url: Option<String>,
101 #[serde(default)]
102 pub last_seen_at: Option<String>,
103 #[serde(default)]
105 pub transport: Option<String>,
106}
107
108#[derive(Debug, Clone, Deserialize)]
111pub struct ServiceRoute {
112 pub address: String,
114 pub transport: String,
116 pub connection_url: String,
118}
119
120#[derive(Deserialize)]
121struct NetworksEnvelope {
122 #[serde(default)]
123 networks: Vec<NetworkInfo>,
124}
125
126#[derive(Deserialize)]
127struct MembersEnvelope {
128 #[serde(default)]
129 members: Vec<NetworkMember>,
130}
131
132#[derive(Clone)]
133pub struct Network {
134 info: NetworkInfo,
135 client: HeyoClient,
136}
137
138impl Network {
139 fn from_raw(client: HeyoClient, info: NetworkInfo) -> Self {
140 Self { info, client }
141 }
142
143 pub fn id(&self) -> &str {
144 &self.info.id
145 }
146
147 pub fn name(&self) -> &str {
148 &self.info.name
149 }
150
151 pub fn is_default(&self) -> bool {
152 self.info.is_default
153 }
154
155 pub fn info(&self) -> &NetworkInfo {
156 &self.info
157 }
158
159 pub fn client(&self) -> &HeyoClient {
160 &self.client
161 }
162
163 pub async fn create(
165 options: NetworkCreateOptions,
166 client_options: HeyoClientOptions,
167 ) -> Result<Self, HeyoError> {
168 let client = HeyoClient::new(client_options)?;
169 let raw: NetworkInfo = client
170 .request(
171 Method::POST,
172 "/networks",
173 Some(&options),
174 RequestOptions::default(),
175 )
176 .await?;
177 Ok(Network::from_raw(client, raw))
178 }
179
180 pub async fn list(client_options: HeyoClientOptions) -> Result<Vec<NetworkInfo>, HeyoError> {
183 let client = HeyoClient::new(client_options)?;
184 let env: NetworksEnvelope = client
185 .request(Method::GET, "/networks", None::<&()>, RequestOptions::default())
186 .await?;
187 Ok(env.networks)
188 }
189
190 pub async fn get(id: &str, client_options: HeyoClientOptions) -> Result<Self, HeyoError> {
192 let client = HeyoClient::new(client_options)?;
193 let path = format!("/networks/{}", encode_path(id));
194 let raw: NetworkInfo = client
195 .request(Method::GET, &path, None::<&()>, RequestOptions::default())
196 .await?;
197 Ok(Network::from_raw(client, raw))
198 }
199
200 pub async fn default_for_me(
202 client_options: HeyoClientOptions,
203 ) -> Result<Self, HeyoError> {
204 let client = HeyoClient::new(client_options)?;
205 let raw: NetworkInfo = client
206 .request(Method::GET, "/networks/me", None::<&()>, RequestOptions::default())
207 .await?;
208 Ok(Network::from_raw(client, raw))
209 }
210
211 pub async fn delete_by_id(
213 id: &str,
214 client_options: HeyoClientOptions,
215 ) -> Result<(), HeyoError> {
216 let client = HeyoClient::new(client_options)?;
217 let path = format!("/networks/{}", encode_path(id));
218 client
219 .request::<serde_json::Value>(
220 Method::DELETE,
221 &path,
222 None::<&()>,
223 RequestOptions::default(),
224 )
225 .await?;
226 Ok(())
227 }
228
229 pub async fn delete(self) -> Result<(), HeyoError> {
230 let path = format!("/networks/{}", encode_path(&self.info.id));
231 self.client
232 .request::<serde_json::Value>(
233 Method::DELETE,
234 &path,
235 None::<&()>,
236 RequestOptions::default(),
237 )
238 .await?;
239 Ok(())
240 }
241
242 pub async fn update(&mut self, options: NetworkUpdateOptions) -> Result<(), HeyoError> {
245 let path = format!("/networks/{}", encode_path(&self.info.id));
246 let raw: NetworkInfo = self
247 .client
248 .request(Method::PATCH, &path, Some(&options), RequestOptions::default())
249 .await?;
250 self.info = raw;
251 Ok(())
252 }
253
254 pub async fn list_services(
258 client_options: HeyoClientOptions,
259 ) -> Result<Vec<NetworkService>, HeyoError> {
260 let client = HeyoClient::new(client_options)?;
261 client
262 .request(
263 Method::GET,
264 "/networks/me/services",
265 None::<&()>,
266 RequestOptions::default(),
267 )
268 .await
269 }
270
271 pub async fn dial_service(
277 name: &str,
278 port: u16,
279 client_options: HeyoClientOptions,
280 ) -> Result<ServiceRoute, HeyoError> {
281 let client = HeyoClient::new(client_options)?;
282 let path = format!(
283 "/networks/me/services/{}/{}/dial",
284 encode_path(name),
285 port
286 );
287 client
288 .request(Method::GET, &path, None::<&()>, RequestOptions::default())
289 .await
290 }
291
292 pub async fn list_members(&self) -> Result<Vec<NetworkMember>, HeyoError> {
294 let path = format!("/networks/{}/members", encode_path(&self.info.id));
295 let env: MembersEnvelope = self
296 .client
297 .request(Method::GET, &path, None::<&()>, RequestOptions::default())
298 .await?;
299 Ok(env.members)
300 }
301
302 pub async fn add_member(
306 &self,
307 registration: NetworkMemberRegistration,
308 ) -> Result<NetworkMember, HeyoError> {
309 let path = format!("/networks/{}/members", encode_path(&self.info.id));
310 self.client
311 .request(
312 Method::POST,
313 &path,
314 Some(®istration),
315 RequestOptions::default(),
316 )
317 .await
318 }
319
320 pub async fn remove_member(
322 &self,
323 sandbox_kind: NetworkMemberKind,
324 sandbox_ref: &str,
325 ) -> Result<(), HeyoError> {
326 let path = format!(
327 "/networks/{}/members/{}/{}",
328 encode_path(&self.info.id),
329 sandbox_kind.as_str(),
330 encode_path(sandbox_ref)
331 );
332 self.client
333 .request::<serde_json::Value>(
334 Method::DELETE,
335 &path,
336 None::<&()>,
337 RequestOptions::default(),
338 )
339 .await?;
340 Ok(())
341 }
342}