dceapi_rs/
client.rs

1//! DCE API client.
2//!
3//! The main entry point for using the DCE API.
4
5use std::sync::Arc;
6
7use reqwest::Client as HttpClient;
8
9use crate::config::Config;
10use crate::error::{Error, Result};
11use crate::http::BaseClient;
12use crate::services::{
13    CommonService, DeliveryService, MarketService, MemberService, NewsService, SettleService,
14    TradeService,
15};
16use crate::token::TokenManager;
17
18/// DCE API client.
19///
20/// This is the main entry point for using the DCE API. It provides access to all
21/// API services through dedicated service instances.
22///
23/// # Example
24///
25/// ```no_run
26/// use dceapi::{Client, Config};
27///
28/// #[tokio::main]
29/// async fn main() -> dceapi::Result<()> {
30///     let config = Config::new()
31///         .with_api_key("your-api-key")
32///         .with_secret("your-secret");
33///     
34///     let client = Client::new(config)?;
35///     
36///     // Get current trade date
37///     let trade_date = client.common.get_curr_trade_date(None).await?;
38///     println!("Trade date: {}", trade_date.date);
39///     
40///     Ok(())
41/// }
42/// ```
43#[derive(Debug, Clone)]
44pub struct Client {
45    config: Arc<Config>,
46    token_manager: Arc<TokenManager>,
47
48    /// News service for articles and announcements.
49    pub news: NewsService,
50
51    /// Common service for trade dates and varieties.
52    pub common: CommonService,
53
54    /// Market service for quotes and market data.
55    pub market: MarketService,
56
57    /// Delivery service for delivery data.
58    pub delivery: DeliveryService,
59
60    /// Member service for member rankings.
61    pub member: MemberService,
62
63    /// Trade service for trading parameters.
64    pub trade: TradeService,
65
66    /// Settlement service for settlement parameters.
67    pub settle: SettleService,
68}
69
70impl Client {
71    /// Create a new DCE API client.
72    ///
73    /// # Arguments
74    /// * `config` - Client configuration with API credentials
75    ///
76    /// # Errors
77    /// Returns an error if the configuration is invalid (missing API key or secret).
78    ///
79    /// # Example
80    ///
81    /// ```no_run
82    /// use dceapi::{Client, Config};
83    ///
84    /// let config = Config::new()
85    ///     .with_api_key("your-api-key")
86    ///     .with_secret("your-secret");
87    ///
88    /// let client = Client::new(config).expect("Failed to create client");
89    /// ```
90    pub fn new(mut config: Config) -> Result<Self> {
91        // Apply defaults
92        config.apply_defaults();
93
94        // Validate configuration
95        config.validate()?;
96
97        // Create HTTP client
98        let http_client = HttpClient::builder()
99            .timeout(config.timeout)
100            .gzip(true)
101            .brotli(true)
102            .deflate(true)
103            .build()
104            .map_err(|e| {
105                Error::validation(
106                    "http_client",
107                    format!("failed to create HTTP client: {}", e),
108                )
109            })?;
110
111        // Create token manager
112        let token_manager = Arc::new(TokenManager::new(
113            &config.api_key,
114            &config.secret,
115            &config.base_url,
116            http_client.clone(),
117        ));
118
119        // Create base client
120        let base_client = BaseClient::new(config.clone(), http_client, token_manager.clone());
121
122        // Create client with all services
123        Ok(Client {
124            config: Arc::new(config),
125            token_manager,
126            news: NewsService::new(base_client.clone()),
127            common: CommonService::new(base_client.clone()),
128            market: MarketService::new(base_client.clone()),
129            delivery: DeliveryService::new(base_client.clone()),
130            member: MemberService::new(base_client.clone()),
131            trade: TradeService::new(base_client.clone()),
132            settle: SettleService::new(base_client),
133        })
134    }
135
136    /// Create a new client from environment variables.
137    ///
138    /// Reads `DCE_API_KEY` and `DCE_SECRET` from the environment.
139    ///
140    /// # Errors
141    /// Returns an error if the environment variables are not set.
142    pub fn from_env() -> Result<Self> {
143        let config = Config::from_env();
144        Self::new(config)
145    }
146
147    /// Get the client configuration (read-only).
148    pub fn config(&self) -> &Config {
149        &self.config
150    }
151
152    /// Get the token manager.
153    ///
154    /// This can be used for advanced token management, such as forcing a refresh.
155    pub fn token_manager(&self) -> &TokenManager {
156        &self.token_manager
157    }
158}