1#![allow(elided_named_lifetimes)]
56#![allow(missing_docs)]
57#![allow(unused_imports)]
58#![allow(clippy::needless_lifetimes)]
59#![allow(clippy::too_many_arguments)]
60#![cfg_attr(docsrs, feature(doc_cfg))]
61
62#[cfg(feature = "requests")]
63pub mod company_managers;
64#[cfg(feature = "requests")]
65pub mod countries;
66#[cfg(feature = "requests")]
67pub mod employments;
68mod methods;
69#[cfg(feature = "requests")]
70pub mod sandbox;
71#[cfg(test)]
72mod tests;
73#[cfg(feature = "requests")]
74pub mod time_off;
75pub mod types;
76pub mod utils;
77
78#[cfg(feature = "requests")]
79use std::env;
80
81#[cfg(not(target_arch = "wasm32"))]
82#[cfg(feature = "requests")]
83static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
84
85#[derive(Clone, Debug)]
87#[cfg(feature = "requests")]
88pub struct Client {
89 token: String,
90 base_url: String,
91
92 #[cfg(feature = "retry")]
93 client: reqwest_middleware::ClientWithMiddleware,
94 #[cfg(feature = "retry")]
95 #[cfg(not(target_arch = "wasm32"))]
96 #[allow(dead_code)]
97 client_http1_only: reqwest_middleware::ClientWithMiddleware,
98
99 #[cfg(not(feature = "retry"))]
100 client: reqwest::Client,
101 #[cfg(not(feature = "retry"))]
102 #[cfg(not(target_arch = "wasm32"))]
103 #[allow(dead_code)]
104 client_http1_only: reqwest::Client,
105}
106
107#[cfg(feature = "retry")]
109#[cfg(feature = "requests")]
110pub struct RequestBuilder(pub reqwest_middleware::RequestBuilder);
111#[cfg(not(feature = "retry"))]
112#[cfg(feature = "requests")]
113pub struct RequestBuilder(pub reqwest::RequestBuilder);
114
115#[cfg(feature = "requests")]
116impl Client {
117 #[tracing::instrument]
122 #[cfg(not(target_arch = "wasm32"))]
123 pub fn new_from_reqwest<T>(
124 token: T,
125 builder_http: reqwest::ClientBuilder,
126 builder_websocket: reqwest::ClientBuilder,
127 ) -> Self
128 where
129 T: ToString + std::fmt::Debug,
130 {
131 #[cfg(feature = "retry")]
132 {
133 let retry_policy =
135 reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
136 match (builder_http.build(), builder_websocket.build()) {
137 (Ok(c), Ok(c1)) => {
138 let client = reqwest_middleware::ClientBuilder::new(c)
139 .with(reqwest_tracing::TracingMiddleware::default())
141 .with(reqwest_conditional_middleware::ConditionalMiddleware::new(
143 reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
144 |req: &reqwest::Request| req.try_clone().is_some(),
145 ))
146 .build();
147 let client_http1_only = reqwest_middleware::ClientBuilder::new(c1)
148 .with(reqwest_tracing::TracingMiddleware::default())
149 .with(reqwest_conditional_middleware::ConditionalMiddleware::new(
150 reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
151 |req: &reqwest::Request| req.try_clone().is_some(),
152 ))
153 .build();
154 Client {
155 token: token.to_string(),
156 base_url: "https://gateway.remote.com".to_string(),
157
158 client,
159 client_http1_only,
160 }
161 }
162 (Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
163 }
164 }
165 #[cfg(not(feature = "retry"))]
166 {
167 match (builder_http.build(), builder_websocket.build()) {
168 (Ok(c), Ok(c1)) => Client {
169 token: token.to_string(),
170 base_url: "https://gateway.remote.com".to_string(),
171
172 client: c,
173 client_http1_only: c1,
174 },
175 (Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
176 }
177 }
178 }
179
180 #[tracing::instrument]
185 #[cfg(target_arch = "wasm32")]
186 pub fn new_from_reqwest<T>(token: T, builder_http: reqwest::ClientBuilder) -> Self
187 where
188 T: ToString + std::fmt::Debug,
189 {
190 #[cfg(feature = "retry")]
191 {
192 let retry_policy =
194 reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
195 match builder_http.build() {
196 Ok(c) => {
197 let client = reqwest_middleware::ClientBuilder::new(c)
198 .with(reqwest_tracing::TracingMiddleware::default())
200 .with(reqwest_conditional_middleware::ConditionalMiddleware::new(
202 reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
203 |req: &reqwest::Request| req.try_clone().is_some(),
204 ))
205 .build();
206 Client {
207 token: token.to_string(),
208 base_url: "https://gateway.remote.com".to_string(),
209
210 client,
211 }
212 }
213 Err(e) => panic!("creating reqwest client failed: {:?}", e),
214 }
215 }
216 #[cfg(not(feature = "retry"))]
217 {
218 match builder_http.build() {
219 Ok(c) => Client {
220 token: token.to_string(),
221 base_url: "https://gateway.remote.com".to_string(),
222
223 client: c,
224 },
225 Err(e) => panic!("creating reqwest client failed: {:?}", e),
226 }
227 }
228 }
229
230 #[tracing::instrument]
234 pub fn new<T>(token: T) -> Self
235 where
236 T: ToString + std::fmt::Debug,
237 {
238 #[cfg(not(target_arch = "wasm32"))]
239 let client = reqwest::Client::builder()
240 .user_agent(APP_USER_AGENT)
241 .timeout(std::time::Duration::from_secs(600))
243 .connect_timeout(std::time::Duration::from_secs(60));
244 #[cfg(target_arch = "wasm32")]
245 let client = reqwest::Client::builder();
246 #[cfg(not(target_arch = "wasm32"))]
247 let client_http1 = reqwest::Client::builder()
248 .user_agent(APP_USER_AGENT)
250 .timeout(std::time::Duration::from_secs(600))
251 .connect_timeout(std::time::Duration::from_secs(60))
252 .http1_only();
253 #[cfg(not(target_arch = "wasm32"))]
254 return Self::new_from_reqwest(token, client, client_http1);
255 #[cfg(target_arch = "wasm32")]
256 Self::new_from_reqwest(token, client)
257 }
258
259 #[tracing::instrument]
261 pub fn set_base_url<H>(&mut self, base_url: H)
262 where
263 H: Into<String> + std::fmt::Display + std::fmt::Debug,
264 {
265 self.base_url = base_url.to_string().trim_end_matches('/').to_string();
266 }
267
268 #[tracing::instrument]
270 pub fn new_from_env() -> Self {
271 let token = env::var("REMOTE_API_TOKEN").expect("must set REMOTE_API_TOKEN");
272 let base_url = env::var("REMOTE_HOST").unwrap_or("https://gateway.remote.com".to_string());
273
274 let mut c = Client::new(token);
275 c.set_base_url(base_url);
276 c
277 }
278
279 #[tracing::instrument]
281 pub async fn request_raw(
282 &self,
283 method: reqwest::Method,
284 uri: &str,
285 body: Option<reqwest::Body>,
286 ) -> anyhow::Result<RequestBuilder> {
287 let u = if uri.starts_with("https://") || uri.starts_with("http://") {
288 uri.to_string()
289 } else {
290 format!("{}/{}", self.base_url, uri.trim_start_matches('/'))
291 };
292
293 let mut req = self.client.request(method, &u);
294
295 req = req.bearer_auth(&self.token);
297
298 req = req.header(
300 reqwest::header::ACCEPT,
301 reqwest::header::HeaderValue::from_static("application/json"),
302 );
303 req = req.header(
304 reqwest::header::CONTENT_TYPE,
305 reqwest::header::HeaderValue::from_static("application/json"),
306 );
307
308 if let Some(body) = body {
309 req = req.body(body);
310 }
311
312 Ok(RequestBuilder(req))
313 }
314
315 pub fn company_managers(&self) -> company_managers::CompanyManagers {
317 company_managers::CompanyManagers::new(self.clone())
318 }
319
320 pub fn countries(&self) -> countries::Countries {
322 countries::Countries::new(self.clone())
323 }
324
325 pub fn employments(&self) -> employments::Employments {
327 employments::Employments::new(self.clone())
328 }
329
330 pub fn sandbox(&self) -> sandbox::Sandbox {
332 sandbox::Sandbox::new(self.clone())
333 }
334
335 pub fn time_off(&self) -> time_off::TimeOff {
337 time_off::TimeOff::new(self.clone())
338 }
339}