koios_sdk/client/
builder.rsuse crate::{
client::{AuthConfig, Client, Config},
error::Result,
network::Network,
};
use chrono::{DateTime, Utc};
use governor::Quota;
use std::time::Duration;
#[derive(Debug, Default)]
pub struct ClientBuilder {
config: Config,
}
impl ClientBuilder {
pub fn new() -> Self {
Self {
config: Config::default(),
}
}
pub fn network(mut self, network: Network) -> Self {
self.config.network = network;
self.config.custom_url = None; self
}
pub fn base_url<S: Into<String>>(mut self, url: S) -> Self {
self.config.custom_url = Some(url.into());
self
}
pub fn auth_token<S: Into<String>>(mut self, token: S) -> Self {
self.config.auth = Some(AuthConfig::new(token.into()));
self
}
pub fn auth_token_with_expiry<S: Into<String>>(
mut self,
token: S,
expiry: DateTime<Utc>,
) -> Self {
self.config.auth = Some(AuthConfig::with_expiry(token.into(), expiry));
self
}
pub fn auth(mut self, auth: AuthConfig) -> Self {
self.config.auth = Some(auth);
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.config.timeout = timeout;
self
}
pub fn rate_limit(mut self, quota: Quota) -> Self {
self.config.rate_limit = quota;
self
}
pub fn build(self) -> Result<Client> {
Client::with_config(self.config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_builder_default() {
let client = ClientBuilder::new().build().unwrap();
assert_eq!(client.base_url(), crate::DEFAULT_API_URL);
}
#[test]
fn test_builder_with_auth() {
let client = ClientBuilder::new()
.auth_token("test-token")
.build()
.unwrap();
let rt = tokio::runtime::Runtime::new().unwrap();
assert!(rt.block_on(client.has_valid_auth()));
assert_eq!(client.auth_token(), Some("test-token".to_string()));
}
#[test]
fn test_builder_with_auth_expiry() {
let expiry = Utc::now() + chrono::Duration::hours(1);
let client = ClientBuilder::new()
.auth_token_with_expiry("test-token", expiry)
.build()
.unwrap();
let rt = tokio::runtime::Runtime::new().unwrap();
assert!(rt.block_on(client.has_valid_auth()));
assert_eq!(client.auth_token(), Some("test-token".to_string()));
}
#[test]
fn test_builder_with_expired_auth() {
let expiry = Utc::now() - chrono::Duration::hours(1);
let client = ClientBuilder::new()
.auth_token_with_expiry("test-token", expiry)
.build()
.unwrap();
let rt = tokio::runtime::Runtime::new().unwrap();
assert!(!rt.block_on(client.has_valid_auth()));
assert_eq!(client.auth_token(), None);
}
#[test]
fn test_builder_with_custom_timeout() {
let timeout = Duration::from_secs(60);
let client = ClientBuilder::new().timeout(timeout).build().unwrap();
assert_eq!(client.base_url(), crate::DEFAULT_API_URL);
}
#[test]
fn test_builder_with_rate_limit() {
let quota = Quota::per_second(50u32.try_into().unwrap());
let client = ClientBuilder::new().rate_limit(quota).build().unwrap();
assert_eq!(client.base_url(), crate::DEFAULT_API_URL);
}
#[test]
fn test_builder_with_all_options() {
let expiry = Utc::now() + chrono::Duration::hours(1);
let client = ClientBuilder::new()
.base_url("https://custom.api.com")
.auth_token_with_expiry("test-token", expiry)
.timeout(Duration::from_secs(60))
.rate_limit(Quota::per_second(50u32.try_into().unwrap()))
.build()
.unwrap();
assert_eq!(client.base_url(), "https://custom.api.com");
assert_eq!(client.auth_token(), Some("test-token".to_string()));
}
#[test]
fn test_builder_custom_auth_config() {
let auth = AuthConfig::new("test-token".to_string());
let client = ClientBuilder::new().auth(auth).build().unwrap();
assert_eq!(client.auth_token(), Some("test-token".to_string()));
}
#[test]
fn test_builder_chaining() {
let client = ClientBuilder::new()
.base_url("https://custom.api.com")
.auth_token("test-token")
.timeout(Duration::from_secs(60))
.build()
.unwrap();
assert_eq!(client.base_url(), "https://custom.api.com");
assert_eq!(client.auth_token(), Some("test-token".to_string()));
}
}