1use std::time::Duration;
4
5pub const DEFAULT_API_HOST: &str = "https://app.outlit.ai";
7
8pub const DEFAULT_FLUSH_INTERVAL: Duration = Duration::from_secs(10);
10
11pub const DEFAULT_MAX_BATCH_SIZE: usize = 100;
13
14pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
16
17#[derive(Debug, Clone)]
19pub struct Config {
20 pub(crate) public_key: String,
21 pub(crate) api_host: String,
22 pub(crate) flush_interval: Duration,
23 pub(crate) max_batch_size: usize,
24 pub(crate) timeout: Duration,
25}
26
27impl Config {
28 pub fn public_key(&self) -> &str {
30 &self.public_key
31 }
32
33 pub fn api_host(&self) -> &str {
35 &self.api_host
36 }
37
38 pub fn flush_interval(&self) -> Duration {
40 self.flush_interval
41 }
42
43 pub fn max_batch_size(&self) -> usize {
45 self.max_batch_size
46 }
47
48 pub fn timeout(&self) -> Duration {
50 self.timeout
51 }
52}
53
54#[derive(Debug)]
56pub struct OutlitBuilder {
57 public_key: String,
58 api_host: Option<String>,
59 flush_interval: Option<Duration>,
60 max_batch_size: Option<usize>,
61 timeout: Option<Duration>,
62}
63
64impl OutlitBuilder {
65 pub fn new(public_key: impl Into<String>) -> Self {
67 Self {
68 public_key: public_key.into(),
69 api_host: None,
70 flush_interval: None,
71 max_batch_size: None,
72 timeout: None,
73 }
74 }
75
76 pub fn api_host(mut self, host: impl Into<String>) -> Self {
78 self.api_host = Some(host.into());
79 self
80 }
81
82 pub fn flush_interval(mut self, interval: Duration) -> Self {
84 self.flush_interval = Some(interval);
85 self
86 }
87
88 pub fn max_batch_size(mut self, size: usize) -> Self {
90 self.max_batch_size = Some(size);
91 self
92 }
93
94 pub fn timeout(mut self, timeout: Duration) -> Self {
96 self.timeout = Some(timeout);
97 self
98 }
99
100 pub(crate) fn build_config(self) -> Result<Config, crate::Error> {
102 if self.public_key.trim().is_empty() {
103 return Err(crate::Error::Config("public_key cannot be empty".into()));
104 }
105
106 if let Some(ref host) = self.api_host {
107 if host.trim().is_empty() {
108 return Err(crate::Error::Config("api_host cannot be empty".into()));
109 }
110 }
111
112 Ok(Config {
113 public_key: self.public_key,
114 api_host: self.api_host.unwrap_or_else(|| DEFAULT_API_HOST.into()),
115 flush_interval: self.flush_interval.unwrap_or(DEFAULT_FLUSH_INTERVAL),
116 max_batch_size: self.max_batch_size.unwrap_or(DEFAULT_MAX_BATCH_SIZE),
117 timeout: self.timeout.unwrap_or(DEFAULT_TIMEOUT),
118 })
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_builder_defaults() {
128 let config = OutlitBuilder::new("pk_test").build_config().unwrap();
129
130 assert_eq!(config.public_key(), "pk_test");
131 assert_eq!(config.api_host(), DEFAULT_API_HOST);
132 assert_eq!(config.flush_interval(), DEFAULT_FLUSH_INTERVAL);
133 assert_eq!(config.max_batch_size(), DEFAULT_MAX_BATCH_SIZE);
134 assert_eq!(config.timeout(), DEFAULT_TIMEOUT);
135 }
136
137 #[test]
138 fn test_builder_custom_values() {
139 let config = OutlitBuilder::new("pk_test")
140 .api_host("https://custom.example.com")
141 .flush_interval(Duration::from_secs(5))
142 .max_batch_size(50)
143 .timeout(Duration::from_secs(30))
144 .build_config()
145 .unwrap();
146
147 assert_eq!(config.api_host(), "https://custom.example.com");
148 assert_eq!(config.flush_interval(), Duration::from_secs(5));
149 assert_eq!(config.max_batch_size(), 50);
150 assert_eq!(config.timeout(), Duration::from_secs(30));
151 }
152
153 #[test]
154 fn test_builder_empty_public_key_fails() {
155 let result = OutlitBuilder::new("").build_config();
156 assert!(result.is_err());
157 }
158
159 #[test]
160 fn test_builder_whitespace_public_key_fails() {
161 let result = OutlitBuilder::new(" ").build_config();
162 assert!(result.is_err());
163 }
164
165 #[test]
166 fn test_builder_whitespace_api_host_fails() {
167 let result = OutlitBuilder::new("pk_test").api_host(" ").build_config();
168 assert!(result.is_err());
169 }
170
171 #[test]
172 fn test_builder_accepts_string_and_str() {
173 let _ = OutlitBuilder::new("pk_test");
175 let _ = OutlitBuilder::new(String::from("pk_test"));
177 let _ = OutlitBuilder::new("pk_test").api_host("https://example.com");
179 let _ = OutlitBuilder::new("pk_test").api_host(String::from("https://example.com"));
180 }
181}