use std::time::Duration;
use crate::auth::Auth;
use crate::config::BaseUrl;
use crate::error::{Error, Result};
use crate::http::HttpClient;
use crate::resources::{
ActivitiesApi, ApiKeysApi, AssignmentsApi, AuthApi, DocumentsApi, FieldsApi, PublicApi,
SignerSelfApi, SignersApi, TagsApi, TemplatesApi, WebhooksApi,
};
pub(crate) const DEFAULT_USER_AGENT: &str = concat!("assinafy-rust/", env!("CARGO_PKG_VERSION"));
#[derive(Clone)]
pub struct Client {
http: HttpClient,
}
impl Client {
pub fn builder() -> ClientBuilder {
ClientBuilder::default()
}
pub fn from_api_key<S: Into<String>>(api_key: S) -> Result<Self> {
ClientBuilder::default().api_key(api_key).build()
}
pub fn with_auth(&self, auth: Auth) -> Self {
Client {
http: self.http.with_auth(auth),
}
}
pub fn auth(&self) -> &Auth {
self.http.auth()
}
pub fn base_url(&self) -> &url::Url {
self.http.base_url()
}
pub fn public(&self) -> PublicApi<'_> {
PublicApi::new(&self.http)
}
pub fn auth_api(&self) -> AuthApi<'_> {
AuthApi::new(&self.http)
}
pub fn api_keys(&self) -> ApiKeysApi<'_> {
ApiKeysApi::new(&self.http)
}
pub fn signers<S: Into<String>>(&self, account_id: S) -> SignersApi<'_> {
SignersApi::new(&self.http, account_id.into())
}
pub fn signer_self(&self) -> SignerSelfApi<'_> {
SignerSelfApi::new(&self.http)
}
pub fn documents(&self) -> DocumentsApi<'_> {
DocumentsApi::new(&self.http)
}
pub fn assignments(&self) -> AssignmentsApi<'_> {
AssignmentsApi::new(&self.http)
}
pub fn tags<S: Into<String>>(&self, account_id: S) -> TagsApi<'_> {
TagsApi::new(&self.http, account_id.into())
}
pub fn fields<S: Into<String>>(&self, account_id: S) -> FieldsApi<'_> {
FieldsApi::new(&self.http, account_id.into())
}
pub fn templates<S: Into<String>>(&self, account_id: S) -> TemplatesApi<'_> {
TemplatesApi::new(&self.http, account_id.into())
}
pub fn webhooks<S: Into<String>>(&self, account_id: S) -> WebhooksApi<'_> {
WebhooksApi::new(&self.http, account_id.into())
}
pub fn activities(&self) -> ActivitiesApi<'_> {
ActivitiesApi::new(&self.http)
}
#[allow(dead_code)]
pub(crate) fn http(&self) -> &HttpClient {
&self.http
}
}
impl std::fmt::Debug for Client {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Client")
.field("base_url", &self.base_url().as_str())
.finish()
}
}
#[derive(Debug, Default, Clone)]
pub struct ClientBuilder {
base_url: Option<BaseUrl>,
auth: Option<Auth>,
timeout: Option<Duration>,
connect_timeout: Option<Duration>,
user_agent: Option<String>,
http_client: Option<reqwest::Client>,
}
impl ClientBuilder {
pub fn base_url(mut self, base: BaseUrl) -> Self {
self.base_url = Some(base);
self
}
pub fn production(self) -> Self {
self.base_url(BaseUrl::Production)
}
pub fn sandbox(self) -> Self {
self.base_url(BaseUrl::Sandbox)
}
pub fn auth(mut self, auth: Auth) -> Self {
self.auth = Some(auth);
self
}
pub fn api_key<S: Into<String>>(self, key: S) -> Self {
self.auth(Auth::ApiKey(key.into()))
}
pub fn bearer<S: Into<String>>(self, token: S) -> Self {
self.auth(Auth::Bearer(token.into()))
}
pub fn access_token<S: Into<String>>(self, token: S) -> Self {
self.auth(Auth::AccessToken(token.into()))
}
pub fn access_code<S: Into<String>>(self, code: S) -> Self {
self.auth(Auth::AccessCode(code.into()))
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn connect_timeout(mut self, timeout: Duration) -> Self {
self.connect_timeout = Some(timeout);
self
}
pub fn user_agent<S: Into<String>>(mut self, ua: S) -> Self {
self.user_agent = Some(ua.into());
self
}
pub fn http_client(mut self, client: reqwest::Client) -> Self {
self.http_client = Some(client);
self
}
pub fn build(self) -> Result<Client> {
let base = self.base_url.unwrap_or_default();
let auth = self.auth.unwrap_or_default();
let user_agent = self
.user_agent
.unwrap_or_else(|| DEFAULT_USER_AGENT.to_string());
let http = match self.http_client {
Some(c) => c,
None => {
let builder = reqwest::Client::builder()
.user_agent(&user_agent)
.timeout(self.timeout.unwrap_or_else(|| Duration::from_secs(60)))
.connect_timeout(
self.connect_timeout
.unwrap_or_else(|| Duration::from_secs(10)),
);
builder
.build()
.map_err(|e| Error::Config(format!("failed to build http client: {e}")))?
}
};
Ok(Client {
http: HttpClient::new(http, base, auth, user_agent),
})
}
}