use crate::config::ClientConfig;
use crate::errors::{Result, ZealError};
use crate::orchestrator::OrchestratorAPI;
use crate::templates::TemplatesAPI;
use crate::traces::TracesAPI;
use crate::types::HealthCheckResponse;
use crate::webhooks::WebhooksAPI;
pub struct ZealClient {
config: ClientConfig,
http_client: reqwest::Client,
templates_api: TemplatesAPI,
orchestrator_api: OrchestratorAPI,
traces_api: TracesAPI,
webhooks_api: WebhooksAPI,
}
impl ZealClient {
pub fn new(config: ClientConfig) -> Result<Self> {
if config.base_url.is_empty() {
return Err(ZealError::configuration_error("Base URL cannot be empty"));
}
let mut client_builder = reqwest::Client::builder()
.timeout(config.default_timeout)
.pool_idle_timeout(config.performance.idle_timeout)
.pool_max_idle_per_host(config.performance.max_idle_connections)
.tcp_keepalive(config.performance.tcp_keepalive)
.user_agent(&config.user_agent);
if !config.verify_tls {
client_builder = client_builder.danger_accept_invalid_certs(true);
}
if config.performance.http2_prior_knowledge {
client_builder = client_builder.http2_prior_knowledge();
}
if config.performance.compression {
}
let http_client = client_builder.build()?;
let base_url = &config.base_url;
let templates_api = TemplatesAPI::with_client(base_url, http_client.clone());
let orchestrator_api = OrchestratorAPI::with_client(base_url, http_client.clone());
let traces_api = TracesAPI::with_client(base_url, http_client.clone());
let webhooks_api = WebhooksAPI::with_client(base_url, http_client.clone());
Ok(Self {
config,
http_client,
templates_api,
orchestrator_api,
traces_api,
webhooks_api,
})
}
pub async fn health(&self) -> Result<HealthCheckResponse> {
let url = format!(
"{}/api/zip/health",
self.config.base_url.trim_end_matches('/')
);
let response = self.http_client.get(&url).send().await?;
let status = response.status();
if !status.is_success() {
return Err(ZealError::api_error(
status.as_u16(),
format!("Health check failed: {}", status),
None,
));
}
let health_response = response.json::<HealthCheckResponse>().await?;
Ok(health_response)
}
pub fn base_url(&self) -> &str {
&self.config.base_url
}
#[allow(dead_code)]
pub(crate) fn http_client(&self) -> &reqwest::Client {
&self.http_client
}
pub fn config(&self) -> &ClientConfig {
&self.config
}
pub fn templates(&self) -> &TemplatesAPI {
&self.templates_api
}
pub fn orchestrator(&self) -> &OrchestratorAPI {
&self.orchestrator_api
}
pub fn traces(&self) -> &TracesAPI {
&self.traces_api
}
pub fn webhooks(&self) -> &WebhooksAPI {
&self.webhooks_api
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::ClientConfig;
#[test]
fn test_client_creation() {
let config = ClientConfig {
base_url: "http://localhost:3000".to_string(),
..Default::default()
};
let client = ZealClient::new(config);
assert!(client.is_ok());
}
#[test]
fn test_client_creation_empty_url() {
let config = ClientConfig {
base_url: "".to_string(),
..Default::default()
};
let client = ZealClient::new(config);
assert!(client.is_err());
}
#[test]
fn test_base_url() {
let config = ClientConfig {
base_url: "http://localhost:3000".to_string(),
..Default::default()
};
let client = ZealClient::new(config).unwrap();
assert_eq!(client.base_url(), "http://localhost:3000");
}
}