1use crate::api::resources::ApiClient;
2use crate::Environment;
3use crate::{ApiError, ClientConfig};
4use std::collections::HashMap;
5use std::time::Duration;
6pub struct ApiClientBuilder {
8 config: ClientConfig,
9}
10impl Default for ApiClientBuilder {
11 fn default() -> Self {
12 Self {
13 config: ClientConfig::default(),
14 }
15 }
16}
17impl ApiClientBuilder {
18 pub fn new(base_url: impl Into<String>) -> Self {
20 let mut config = ClientConfig::default();
21 config.base_url = base_url.into();
22 Self { config }
23 }
24
25 pub fn environment(mut self, environment: Environment) -> Self {
27 self.config.base_url = environment.url().to_string();
28 self
29 }
30
31 pub fn api_key(mut self, key: impl Into<String>) -> Self {
33 self.config.api_key = Some(key.into());
34 self
35 }
36
37 pub fn token(mut self, token: impl Into<String>) -> Self {
39 self.config.token = Some(token.into());
40 self
41 }
42
43 pub fn username(mut self, username: impl Into<String>) -> Self {
45 self.config.username = Some(username.into());
46 self
47 }
48
49 pub fn password(mut self, password: impl Into<String>) -> Self {
51 self.config.password = Some(password.into());
52 self
53 }
54
55 pub fn client_id(mut self, client_id: impl Into<String>) -> Self {
57 self.config.client_id = Some(client_id.into());
58 self
59 }
60
61 pub fn client_secret(mut self, client_secret: impl Into<String>) -> Self {
63 self.config.client_secret = Some(client_secret.into());
64 self
65 }
66
67 pub fn oauth_credentials(
69 mut self,
70 client_id: impl Into<String>,
71 client_secret: impl Into<String>,
72 ) -> Self {
73 self.config.client_id = Some(client_id.into());
74 self.config.client_secret = Some(client_secret.into());
75 self
76 }
77
78 pub fn timeout(mut self, timeout: Duration) -> Self {
80 self.config.timeout = timeout;
81 self
82 }
83
84 pub fn max_retries(mut self, retries: u32) -> Self {
86 self.config.max_retries = retries;
87 self
88 }
89
90 pub fn custom_header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
92 self.config.custom_headers.insert(key.into(), value.into());
93 self
94 }
95
96 pub fn custom_headers(mut self, headers: HashMap<String, String>) -> Self {
98 self.config.custom_headers.extend(headers);
99 self
100 }
101
102 pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
104 self.config.user_agent = user_agent.into();
105 self
106 }
107
108 pub fn build(self) -> Result<ApiClient, ApiError> {
110 ApiClient::new(self.config)
111 }
112}
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_environment() {
119 let builder = ApiClientBuilder::default().environment(Environment::default());
120 assert_eq!(
121 builder.config.base_url,
122 Environment::default().url().to_string()
123 );
124 }
125
126 #[test]
127 fn test_new_sets_base_url() {
128 let builder = ApiClientBuilder::new("https://api.example.com");
129 assert_eq!(builder.config.base_url, "https://api.example.com");
130 }
131
132 #[test]
133 fn test_api_key() {
134 let builder = ApiClientBuilder::new("https://api.example.com").api_key("my-key");
135 assert_eq!(builder.config.api_key, Some("my-key".to_string()));
136 }
137
138 #[test]
139 fn test_token() {
140 let builder = ApiClientBuilder::new("https://api.example.com").token("my-token");
141 assert_eq!(builder.config.token, Some("my-token".to_string()));
142 }
143
144 #[test]
145 fn test_username() {
146 let builder = ApiClientBuilder::new("https://api.example.com").username("user");
147 assert_eq!(builder.config.username, Some("user".to_string()));
148 }
149
150 #[test]
151 fn test_password() {
152 let builder = ApiClientBuilder::new("https://api.example.com").password("pass");
153 assert_eq!(builder.config.password, Some("pass".to_string()));
154 }
155
156 #[test]
157 fn test_client_id() {
158 let builder = ApiClientBuilder::new("https://api.example.com").client_id("cid");
159 assert_eq!(builder.config.client_id, Some("cid".to_string()));
160 }
161
162 #[test]
163 fn test_client_secret() {
164 let builder = ApiClientBuilder::new("https://api.example.com").client_secret("secret");
165 assert_eq!(builder.config.client_secret, Some("secret".to_string()));
166 }
167
168 #[test]
169 fn test_oauth_credentials() {
170 let builder =
171 ApiClientBuilder::new("https://api.example.com").oauth_credentials("cid", "secret");
172 assert_eq!(builder.config.client_id, Some("cid".to_string()));
173 assert_eq!(builder.config.client_secret, Some("secret".to_string()));
174 }
175
176 #[test]
177 fn test_timeout() {
178 let builder =
179 ApiClientBuilder::new("https://api.example.com").timeout(Duration::from_secs(120));
180 assert_eq!(builder.config.timeout, Duration::from_secs(120));
181 }
182
183 #[test]
184 fn test_max_retries() {
185 let builder = ApiClientBuilder::new("https://api.example.com").max_retries(5);
186 assert_eq!(builder.config.max_retries, 5);
187 }
188
189 #[test]
190 fn test_custom_header() {
191 let builder =
192 ApiClientBuilder::new("https://api.example.com").custom_header("X-Custom", "value");
193 assert_eq!(
194 builder.config.custom_headers.get("X-Custom"),
195 Some(&"value".to_string())
196 );
197 }
198
199 #[test]
200 fn test_custom_headers_multiple() {
201 let mut headers = HashMap::new();
202 headers.insert("X-One".to_string(), "1".to_string());
203 headers.insert("X-Two".to_string(), "2".to_string());
204 let builder = ApiClientBuilder::new("https://api.example.com").custom_headers(headers);
205 assert_eq!(
206 builder.config.custom_headers.get("X-One"),
207 Some(&"1".to_string())
208 );
209 assert_eq!(
210 builder.config.custom_headers.get("X-Two"),
211 Some(&"2".to_string())
212 );
213 }
214
215 #[test]
216 fn test_user_agent() {
217 let builder = ApiClientBuilder::new("https://api.example.com").user_agent("my-sdk/1.0");
218 assert_eq!(builder.config.user_agent, "my-sdk/1.0");
219 }
220
221 #[test]
222 fn test_full_builder_chain() {
223 let builder = ApiClientBuilder::new("https://api.example.com")
224 .api_key("key")
225 .token("tok")
226 .username("user")
227 .password("pass")
228 .timeout(Duration::from_secs(60))
229 .max_retries(3)
230 .custom_header("X-Foo", "bar")
231 .user_agent("test/1.0");
232 assert_eq!(builder.config.base_url, "https://api.example.com");
233 assert_eq!(builder.config.api_key, Some("key".to_string()));
234 assert_eq!(builder.config.token, Some("tok".to_string()));
235 assert_eq!(builder.config.username, Some("user".to_string()));
236 assert_eq!(builder.config.password, Some("pass".to_string()));
237 assert_eq!(builder.config.timeout, Duration::from_secs(60));
238 assert_eq!(builder.config.max_retries, 3);
239 assert_eq!(builder.config.user_agent, "test/1.0");
240 }
241
242 #[test]
243 fn test_build_succeeds() {
244 let result = ApiClientBuilder::new("https://api.example.com").build();
245 assert!(result.is_ok());
246 }
247}