Skip to main content

mudra_cli/
config.rs

1//! Configuration management for the currency converter
2
3use crate::{CurrencyError, Result};
4use std::time::Duration;
5
6/// Configuration for the currency converter client
7#[derive(Debug, Clone)]
8pub struct Config {
9    /// Base URL for the API
10    pub base_url: String,
11    /// API key (optional for some services)
12    pub api_key: Option<String>,
13    /// Request timeout duration
14    pub timeout: Duration,
15    /// User agent string for requests
16    pub user_agent: String,
17    /// Maximum number of retries for failed requests
18    pub max_retries: u32,
19}
20
21impl Config {
22    /// Create a new configuration with default values
23    pub fn new() -> Self {
24        Config {
25            // We'll use exchangerate-api.com for this example (free tier available)
26            base_url: "https://v6.exchangerate-api.com/v6".to_string(),
27            api_key: None,
28            timeout: Duration::from_secs(30),
29            user_agent: format!("currency-converter/{}", env!("CARGO_PKG_VERSION")),
30            max_retries: 3,
31        }
32    }
33
34    /// Set the API key from environment variable or explicit value
35    pub fn with_api_key<S: Into<String>>(mut self, api_key: S) -> Self {
36        self.api_key = Some(api_key.into());
37        self
38    }
39
40    /// Set the base URL
41    pub fn with_base_url<S: Into<String>>(mut self, base_url: S) -> Self {
42        self.base_url = base_url.into();
43        self
44    }
45
46    /// Set the request timeout
47    pub fn with_timeout(mut self, timeout: Duration) -> Self {
48        self.timeout = timeout;
49        self
50    }
51
52    /// Load configuration from environment variables
53    pub fn from_env() -> Result<Self> {
54        let mut config = Config::new();
55
56        // Try to load API key from environment
57        if let Ok(api_key) = std::env::var("EXCHANGE_API_KEY") {
58            config.api_key = Some(api_key);
59        }
60
61        // Try to load base URL from environment (optional)
62        if let Ok(base_url) = std::env::var("EXCHANGE_BASE_URL") {
63            config.base_url = base_url;
64        }
65
66        // Validate that we have an API key (required for most services)
67        if config.api_key.is_none() {
68            return Err(CurrencyError::configuration(
69                "API key not found. Set EXCHANGE_API_KEY environment variable or use with_api_key()",
70            ));
71        }
72
73        Ok(config)
74    }
75
76    /// Get the API key, returning an error if not set
77    pub fn get_api_key(&self) -> Result<&str> {
78        self.api_key
79            .as_deref()
80            .ok_or_else(|| CurrencyError::configuration("API key not configured"))
81    }
82}