sanity_rs/client.rs
1use super::config::SanityConfig;
2use super::{
3 error::{RequestError, URLError},
4 url::SanityURL,
5};
6use reqwest::Client as ReqwestClient;
7use std::fmt::Display;
8use url::Url;
9
10/// Creates a new SanityClient.
11///
12/// # Example
13///
14/// ```
15/// use sanity_rs::client::{ create_client, SanityClient };
16/// use sanity_rs::config::SanityConfig;
17/// use sanity_rs::error::ConfigurationError;
18///
19/// let sanity_project_id = std::env::var("SANITY_PROJECT_ID")
20/// .unwrap_or("project_id".to_string());
21/// let sanity_dataset = std::env::var("SANITY_DATASET")
22/// .unwrap_or("data_set".to_string());
23/// let config = SanityConfig::new(sanity_project_id, sanity_dataset);
24/// let mut client = create_client(config);
25/// ```
26///
27/// # Arguments
28///
29/// * `config`: A `SanityConfig` struct containing the configuration for the client.
30///
31/// # Returns
32///
33/// A `SanityClient` instance.
34///
35/// # Panics
36///
37/// Panics if the client cannot be created. The error from `SanityClient::new` will be included in the panic message.
38pub fn create_client(config: SanityConfig) -> SanityClient {
39 match SanityClient::new(config) {
40 Ok(client) => client,
41 Err(e) => panic!("Error creating client: {:?}", e),
42 }
43}
44
45
46/// Represents the payload of a request.
47///
48/// This struct contains the URL, body, and query result of a request.
49pub struct RequestPayload {
50 /// The URL of the request.
51 pub query: Url,
52 /// The body of the request, if any.
53 pub body: Option<String>,
54 /// The result of the query, if any. This is likely populated after processing the request.
55 pub query_result: Option<String>,
56}
57
58impl Default for RequestPayload {
59 fn default() -> Self {
60 Self {
61 query: Url::parse("https://api.sanity.io")
62 .map_err(URLError::InvalidURL)
63 .unwrap(),
64 body: None,
65 query_result: None,
66 }
67 }
68}
69
70impl RequestPayload {
71 pub fn set_body(&mut self, body: &str) -> &Self {
72 self.body = Some(body.to_string());
73 self
74 }
75}
76
77/// A client for interacting with the Sanity.io API.
78///
79/// This struct provides methods for making requests to the Sanity API. It uses the `reqwest` crate for HTTP requests.
80pub struct SanityClient {
81 /// Configuration settings for the client.
82 pub config: SanityConfig,
83 /// The underlying HTTP client used for making requests.
84 pub client: ReqwestClient,
85 /// The payload to be sent with requests. This is likely a struct containing data relevant to the request type.
86 pub payload: RequestPayload,
87}
88
89impl SanityClient {
90 /// Creates a new Sanity client.
91 ///
92 /// # Arguments
93 ///
94 /// * `config`: A `SanityConfig` struct containing the configuration for the client.
95 ///
96 /// # Returns
97 ///
98 /// A `Result` containing the new `SanityClient` or a `RequestError` if the URL parsing fails.
99 ///
100 /// # Errors
101 ///
102 /// This function will return an error if the URL cannot be parsed.
103 pub fn new(config: SanityConfig) -> Result<Self, RequestError> {
104 let url = SanityURL::new()
105 .host(match &config.api_host {
106 Some(host) => host.to_string(),
107 None => "api.sanity.io".to_string(),
108 })
109 .use_cdn(config.use_cdn)
110 .project_id(&config.project_id)
111 .api_version(&config.api_version)
112 .dataset(&config.dataset)
113 .build()
114 .map_err(RequestError::URLParsingError)?;
115 let mut client = Self {
116 config,
117 client: ReqwestClient::new(),
118 payload: RequestPayload::default(),
119 };
120 client.payload.query = url;
121 Ok(client)
122 }
123
124 /// Sets the request body.
125 ///
126 /// This method allows you to set the request body for subsequent use.
127 pub fn body(&mut self, body: &str) -> &mut Self {
128 self.payload.set_body(body);
129 self
130 }
131
132 /// Send a query to the Sanity API
133 pub async fn query(&mut self, body: &str) -> Result<&mut Self, RequestError> {
134 let query = &mut self.payload.query;
135 SanityURL::query(query, body);
136 let v = self.client.get(query.as_str()).send();
137 let v = v.await?.text().await?;
138 self.payload.query_result = Some(v);
139 Ok(self)
140 }
141}
142
143impl Display for SanityClient {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 f.write_str(&format!("SanityClient : {:?}", self.config.project_id))
146 }
147}