#![allow(mismatched_lifetime_syntaxes)]
#![allow(missing_docs)]
#![allow(unused_imports)]
#![allow(clippy::needless_lifetimes)]
#![allow(clippy::too_many_arguments)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "requests")]
pub mod api_calls;
#[cfg(feature = "requests")]
pub mod api_tokens;
#[cfg(feature = "requests")]
pub mod apps;
#[cfg(feature = "requests")]
pub mod executor;
#[cfg(feature = "requests")]
pub mod file;
#[cfg(feature = "requests")]
pub mod hidden;
#[cfg(feature = "requests")]
pub mod meta;
mod methods;
#[cfg(feature = "requests")]
pub mod ml;
#[cfg(feature = "requests")]
pub mod modeling;
#[cfg(feature = "requests")]
pub mod oauth2;
#[cfg(feature = "requests")]
pub mod orgs;
#[cfg(feature = "requests")]
pub mod payments;
#[cfg(feature = "requests")]
pub mod projects;
#[cfg(feature = "requests")]
pub mod service_accounts;
#[cfg(feature = "requests")]
pub mod store;
#[cfg(test)]
mod tests;
pub mod types;
#[cfg(feature = "requests")]
pub mod unit;
#[cfg(feature = "requests")]
pub mod users;
#[cfg(feature = "requests")]
use std::env;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "requests")]
static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
#[derive(Clone, Debug)]
#[cfg(feature = "requests")]
pub struct Client {
token: String,
base_url: String,
#[cfg(feature = "retry")]
client: reqwest_middleware::ClientWithMiddleware,
#[cfg(feature = "retry")]
#[cfg(not(target_arch = "wasm32"))]
#[allow(dead_code)]
client_http1_only: reqwest_middleware::ClientWithMiddleware,
#[cfg(not(feature = "retry"))]
client: reqwest::Client,
#[cfg(not(feature = "retry"))]
#[cfg(not(target_arch = "wasm32"))]
#[allow(dead_code)]
client_http1_only: reqwest::Client,
}
#[cfg(feature = "retry")]
#[cfg(feature = "requests")]
pub struct RequestBuilder(pub reqwest_middleware::RequestBuilder);
#[cfg(not(feature = "retry"))]
#[cfg(feature = "requests")]
pub struct RequestBuilder(pub reqwest::RequestBuilder);
#[cfg(feature = "requests")]
impl Client {
#[tracing::instrument(skip(token))]
#[cfg(not(target_arch = "wasm32"))]
pub fn new_from_reqwest<T>(
token: T,
builder_http: reqwest::ClientBuilder,
builder_websocket: reqwest::ClientBuilder,
) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(feature = "retry")]
{
let retry_policy =
reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
match (builder_http.build(), builder_websocket.build()) {
(Ok(c), Ok(c1)) => {
let client = reqwest_middleware::ClientBuilder::new(c)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
let client_http1_only = reqwest_middleware::ClientBuilder::new(c1)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
Client {
token: token.to_string(),
base_url: "https://api.zoo.dev".to_string(),
client,
client_http1_only,
}
}
(Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
}
}
#[cfg(not(feature = "retry"))]
{
match (builder_http.build(), builder_websocket.build()) {
(Ok(c), Ok(c1)) => Client {
token: token.to_string(),
base_url: "https://api.zoo.dev".to_string(),
client: c,
client_http1_only: c1,
},
(Err(e), _) | (_, Err(e)) => panic!("creating reqwest client failed: {:?}", e),
}
}
}
#[tracing::instrument(skip(token))]
#[cfg(target_arch = "wasm32")]
pub fn new_from_reqwest<T>(token: T, builder_http: reqwest::ClientBuilder) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(feature = "retry")]
{
let retry_policy =
reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
match builder_http.build() {
Ok(c) => {
let client = reqwest_middleware::ClientBuilder::new(c)
.with(reqwest_tracing::TracingMiddleware::default())
.with(reqwest_conditional_middleware::ConditionalMiddleware::new(
reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
|req: &reqwest::Request| req.try_clone().is_some(),
))
.build();
Client {
token: token.to_string(),
base_url: "https://api.zoo.dev".to_string(),
client,
}
}
Err(e) => panic!("creating reqwest client failed: {:?}", e),
}
}
#[cfg(not(feature = "retry"))]
{
match builder_http.build() {
Ok(c) => Client {
token: token.to_string(),
base_url: "https://api.zoo.dev".to_string(),
client: c,
},
Err(e) => panic!("creating reqwest client failed: {:?}", e),
}
}
}
#[tracing::instrument(skip(token))]
pub fn new<T>(token: T) -> Self
where
T: ToString + std::fmt::Debug,
{
#[cfg(not(target_arch = "wasm32"))]
let client = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
#[cfg(target_arch = "wasm32")]
let client = reqwest::Client::builder();
#[cfg(not(target_arch = "wasm32"))]
let client_http1 = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.http1_only();
#[cfg(not(target_arch = "wasm32"))]
return Self::new_from_reqwest(token, client, client_http1);
#[cfg(target_arch = "wasm32")]
Self::new_from_reqwest(token, client)
}
#[tracing::instrument]
pub fn set_base_url<H>(&mut self, base_url: H)
where
H: Into<String> + std::fmt::Display + std::fmt::Debug,
{
self.base_url = base_url.to_string().trim_end_matches('/').to_string();
}
#[tracing::instrument]
pub fn new_from_env() -> Self {
let token = if let Ok(token) = env::var("KITTYCAD_API_TOKEN") {
token
} else if let Ok(token) = env::var("ZOO_API_TOKEN") {
token
} else {
panic!("must set KITTYCAD_API_TOKEN or ZOO_API_TOKEN");
};
let base_url = if let Ok(base_url) = env::var("KITTYCAD_HOST") {
base_url
} else if let Ok(base_url) = env::var("ZOO_HOST") {
base_url
} else {
"https://api.zoo.dev".to_string()
};
let mut c = Client::new(token);
c.set_base_url(base_url);
c
}
#[tracing::instrument]
pub async fn request_raw(
&self,
method: reqwest::Method,
uri: &str,
body: Option<reqwest::Body>,
) -> anyhow::Result<RequestBuilder> {
let u = if uri.starts_with("https://") || uri.starts_with("http://") {
uri.to_string()
} else {
format!("{}/{}", self.base_url, uri.trim_start_matches('/'))
};
let mut req = self.client.request(method, &u);
req = req.bearer_auth(&self.token);
req = req.header(
reqwest::header::ACCEPT,
reqwest::header::HeaderValue::from_static("application/json"),
);
req = req.header(
reqwest::header::CONTENT_TYPE,
reqwest::header::HeaderValue::from_static("application/json"),
);
if let Some(body) = body {
req = req.body(body);
}
Ok(RequestBuilder(req))
}
pub fn api_calls(&self) -> api_calls::ApiCalls {
api_calls::ApiCalls::new(self.clone())
}
pub fn api_tokens(&self) -> api_tokens::ApiTokens {
api_tokens::ApiTokens::new(self.clone())
}
pub fn apps(&self) -> apps::Apps {
apps::Apps::new(self.clone())
}
pub fn executor(&self) -> executor::Executor {
executor::Executor::new(self.clone())
}
pub fn file(&self) -> file::File {
file::File::new(self.clone())
}
pub fn hidden(&self) -> hidden::Hidden {
hidden::Hidden::new(self.clone())
}
pub fn meta(&self) -> meta::Meta {
meta::Meta::new(self.clone())
}
pub fn ml(&self) -> ml::Ml {
ml::Ml::new(self.clone())
}
pub fn modeling(&self) -> modeling::Modeling {
modeling::Modeling::new(self.clone())
}
pub fn oauth2(&self) -> oauth2::Oauth2 {
oauth2::Oauth2::new(self.clone())
}
pub fn orgs(&self) -> orgs::Orgs {
orgs::Orgs::new(self.clone())
}
pub fn payments(&self) -> payments::Payments {
payments::Payments::new(self.clone())
}
pub fn projects(&self) -> projects::Projects {
projects::Projects::new(self.clone())
}
pub fn service_accounts(&self) -> service_accounts::ServiceAccounts {
service_accounts::ServiceAccounts::new(self.clone())
}
pub fn store(&self) -> store::Store {
store::Store::new(self.clone())
}
pub fn unit(&self) -> unit::Unit {
unit::Unit::new(self.clone())
}
pub fn users(&self) -> users::Users {
users::Users::new(self.clone())
}
}