dagger_sdk/core/
graphql_client.rs1use std::collections::HashMap;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use base64::engine::general_purpose;
6use base64::Engine;
7use thiserror::Error;
8
9use crate::core::connect_params::ConnectParams;
10use crate::core::gql_client::{ClientConfig, GQLClient};
11
12#[async_trait]
13pub trait GraphQLClient {
14 async fn query(&self, query: &str) -> Result<Option<serde_json::Value>, GraphQLError>;
15}
16
17pub type DynGraphQLClient = Arc<dyn GraphQLClient + Send + Sync>;
18
19#[derive(Debug)]
20pub struct DefaultGraphQLClient {
21 client: GQLClient,
22}
23
24impl DefaultGraphQLClient {
25 pub fn new(conn: &ConnectParams) -> Self {
26 let token = general_purpose::URL_SAFE.encode(format!("{}:", conn.session_token));
27
28 let mut headers = HashMap::new();
29 headers.insert("Authorization".to_string(), format!("Basic {}", token));
30
31 Self {
32 client: GQLClient::new_with_config(ClientConfig {
33 endpoint: conn.url(),
34 timeout: Some(1000),
35 headers: Some(headers),
36 proxy: None,
37 }),
38 }
39 }
40}
41
42#[async_trait]
43impl GraphQLClient for DefaultGraphQLClient {
44 async fn query(&self, query: &str) -> Result<Option<serde_json::Value>, GraphQLError> {
45 let res: Option<serde_json::Value> =
46 self.client.query(query).await.map_err(map_graphql_error)?;
47
48 return Ok(res);
49 }
50}
51
52fn map_graphql_error(gql_error: crate::core::gql_client::GraphQLError) -> GraphQLError {
53 let message = gql_error.message().to_string();
54 let json = gql_error.json();
55
56 if let Some(json) = json {
57 if !json.is_empty() {
58 return GraphQLError::DomainError {
59 message,
60 fields: GraphqlErrorMessages(json.into_iter().map(|e| e.message).collect()),
61 };
62 }
63 }
64
65 GraphQLError::HttpError(message)
66}
67
68#[derive(Error, Debug)]
69pub enum GraphQLError {
70 #[error("http error: {0}")]
71 HttpError(String),
72 #[error("domain error:\n{message}\n{fields}")]
73 DomainError {
74 message: String,
75 fields: GraphqlErrorMessages,
76 },
77}
78
79#[derive(Debug, Clone)]
80pub struct GraphqlErrorMessages(Vec<String>);
81
82impl std::fmt::Display for GraphqlErrorMessages {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 for error in self.0.iter() {
85 f.write_fmt(format_args!("{error}\n"))?;
86 }
87
88 Ok(())
89 }
90}