1use crate::API_BASE_URL;
2use reqwest::Client;
3use serde::{Deserialize, Serialize};
4use std::error::Error;
5
6#[derive(Serialize, Deserialize, Debug)]
7pub struct AppResponse {
8 pub id: String,
9 pub created_at: u64,
10}
11
12#[derive(Serialize, Deserialize, Debug)]
13struct AppsResponse {
14 pub total_apps: u64,
15 pub apps: Vec<App>,
16}
17
18#[derive(Serialize, Deserialize, Debug)]
19pub struct App {
20 pub id: String,
21 pub name: String,
22 pub machine_count: u64,
23 pub network: String,
24}
25
26#[derive(Serialize, Deserialize, Debug)]
27pub struct Organization {
28 pub name: String,
29 pub slug: String,
30}
31
32#[derive(Serialize, Deserialize, Debug)]
33pub struct CreateAppRequest {
34 pub app_name: String,
35 pub org_slug: String,
36}
37
38pub struct AppManager {
39 client: Client,
40 api_token: String,
41}
42
43impl AppManager {
44 pub fn new(client: Client, api_token: String) -> Self {
45 Self { client, api_token }
46 }
47
48 pub async fn create(
49 &self,
50 app_name: &str,
51 org_slug: &str,
52 ) -> Result<AppResponse, Box<dyn Error>> {
53 let url = format!("{}/apps", API_BASE_URL);
54 let request_body = CreateAppRequest {
55 app_name: app_name.to_string(),
56 org_slug: org_slug.to_string(),
57 };
58
59 let response = self
60 .client
61 .post(&url)
62 .bearer_auth(&self.api_token)
63 .header("Content-Type", "application/json")
64 .json(&request_body)
65 .send()
66 .await?;
67
68 if response.status() == reqwest::StatusCode::CREATED {
69 let response_text = response.text().await?;
70 let app_response: AppResponse = serde_json::from_str(&response_text)?;
71 println!("Created app: {:?}", app_response);
72 Ok(app_response)
73 } else {
74 let error_message = response.text().await?;
75 println!("Error response: {}", error_message);
76 Err(Box::new(std::io::Error::new(
77 std::io::ErrorKind::Other,
78 "App creation failed",
79 )))
80 }
81 }
82
83 pub async fn delete(&self, app_name: &str, force: bool) -> Result<(), Box<dyn Error>> {
84 let url = if force {
85 format!("{}/apps/{}?force=true", API_BASE_URL, app_name)
86 } else {
87 format!("{}/apps/{}", API_BASE_URL, app_name)
88 };
89
90 let response = self
91 .client
92 .delete(&url)
93 .bearer_auth(&self.api_token)
94 .send()
95 .await?;
96
97 if response.status() == reqwest::StatusCode::ACCEPTED {
98 println!("Deleted app {}", app_name);
99 } else {
100 println!("Failed to delete {}: {:?}", app_name, response.status());
101 }
102
103 Ok(())
104 }
105
106 pub async fn list(&self, org_slug: &str) -> Result<Vec<App>, Box<dyn Error>> {
107 let url = format!("{}/apps?org_slug={}", API_BASE_URL, org_slug);
108
109 let response = self
110 .client
111 .get(&url)
112 .bearer_auth(&self.api_token)
113 .send()
114 .await?;
115
116 if response.status() == reqwest::StatusCode::OK {
117 let response_text = response.text().await?;
118 let apps_response: AppsResponse = serde_json::from_str(&response_text)?;
119 println!("List of apps: {:?}", apps_response.apps);
120 Ok(apps_response.apps)
121 } else {
122 println!("Failed to list apps: {:?}", response.status());
123 Err(Box::new(std::io::Error::new(
124 std::io::ErrorKind::Other,
125 "Failed to list apps",
126 )))
127 }
128 }
129}