Skip to main content

txtx_cloud/
workspace.rs

1use serde::Deserialize;
2use serde_json::json;
3use txtx_addon_kit::{reqwest, uuid::Uuid};
4
5pub async fn fetch_svm_workspaces(
6    access_token: &str,
7    service_gql_url: &str,
8) -> Result<Vec<Workspace>, String> {
9    let client = reqwest::Client::new();
10    let max_attempts = 3;
11    let mut attempts = 0;
12    loop {
13        attempts += 1;
14        let res = client
15            .post(service_gql_url)
16            .bearer_auth(access_token)
17            .json(&json!({
18                "query": r#"
19                    query GetWorkspaces {
20                        svm_workspaces {
21                            name
22                            id
23                        }
24                    }
25                "#.to_string(),
26            }))
27            .send()
28            .await
29            .map_err(|e| e.to_string())?;
30
31        if !res.status().is_success() {
32            let err = res.text().await.unwrap_or_else(|_| "Unknown error".to_string());
33            return Err(format!("received error from server: {}", err));
34        }
35
36        let response: GqlResponse<WorkspaceResponse> =
37            res.json().await.map_err(|e| format!("failed to parse response: {}", e))?;
38
39        if let Some(workspace_response) = response.data {
40            return Ok(workspace_response.svm_workspaces.clone());
41        } else {
42            if attempts >= max_attempts {
43                return Err("no workspaces found for user after multiple attempts".to_string());
44            }
45            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
46        }
47    }
48}
49
50pub async fn get_workspace_id(
51    workspace_name: &str,
52    access_token: &str,
53    service_gql_url: &str,
54) -> Result<Workspace, String> {
55    let client = reqwest::Client::new();
56    let res = client
57        .post(service_gql_url)
58        .bearer_auth(access_token)
59        .json(&json!({
60            "query": r#"
61                query GetWorkspaceByName($_eq: String = "") {
62                    svm_workspaces(where: {name: {_eq: $_eq}}) {
63                        name
64                        id
65                    }
66                }
67            "#.to_string(),
68            "variables": {
69                "_eq": workspace_name
70            }
71        }))
72        .send()
73        .await
74        .map_err(|e| e.to_string())?;
75
76    if !res.status().is_success() {
77        let err = res.text().await.unwrap_or_else(|_| "Unknown error".to_string());
78        return Err(format!("received error from server: {}", err));
79    }
80
81    let response: GqlResponse<WorkspaceResponse> =
82        res.json().await.map_err(|e| format!("failed to parse response: {}", e))?;
83
84    if let Some(workspace_response) = response.data {
85        if workspace_response.svm_workspaces.is_empty() {
86            return Err(format!("workspace '{}' not found", workspace_name));
87        }
88        Ok(workspace_response.svm_workspaces[0].clone())
89    } else {
90        Err("No data returned from server".to_string())
91    }
92}
93
94#[derive(Debug, Clone, Deserialize)]
95pub struct GqlResponse<T> {
96    pub data: Option<T>,
97}
98
99#[derive(Debug, Clone, Deserialize)]
100pub struct WorkspaceResponse {
101    pub svm_workspaces: Vec<Workspace>,
102}
103
104#[derive(Debug, Clone, Deserialize)]
105pub struct Workspace {
106    pub id: Uuid,
107    pub name: String,
108}