fly_sdk/
apps.rs

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}