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}