1use crate::models::Profile;
4use std::env;
5use std::path::PathBuf;
6use std::time::Duration;
7
8#[derive(Debug, Clone)]
10pub struct ChaserConfig {
11 pub context_limit: usize,
13
14 pub timeout_ms: u64,
16
17 pub profile: Profile,
19
20 pub lazy_init: bool,
22
23 pub chrome_path: Option<PathBuf>,
25
26 pub headless: bool,
28
29 pub viewport_width: u32,
31
32 pub viewport_height: u32,
34
35 pub extra_args: Vec<String>,
49
50 pub virtual_display: bool,
55}
56
57impl Default for ChaserConfig {
58 fn default() -> Self {
59 Self {
60 context_limit: 20,
61 timeout_ms: 60000,
62 profile: Profile::Windows,
63 lazy_init: false,
64 chrome_path: None,
65 headless: false,
66 viewport_width: 1920,
67 viewport_height: 1080,
68 extra_args: Vec::new(),
69 virtual_display: false,
70 }
71 }
72}
73
74impl ChaserConfig {
75 pub fn from_env() -> Self {
87 let mut config = Self::default();
88
89 if let Ok(val) = env::var("CHASER_CONTEXT_LIMIT") {
90 if let Ok(limit) = val.parse() {
91 config.context_limit = limit;
92 }
93 }
94
95 if let Ok(val) = env::var("CHASER_TIMEOUT") {
96 if let Ok(timeout) = val.parse() {
97 config.timeout_ms = timeout;
98 }
99 }
100
101 if let Ok(val) = env::var("CHASER_PROFILE") {
102 if let Some(profile) = Profile::parse(&val) {
103 config.profile = profile;
104 }
105 }
106
107 if let Ok(val) = env::var("CHASER_LAZY_INIT") {
108 config.lazy_init = val.eq_ignore_ascii_case("true") || val == "1";
109 }
110
111 if let Ok(val) = env::var("CHROME_BIN") {
112 config.chrome_path = Some(PathBuf::from(val));
113 }
114
115 if let Ok(val) = env::var("CHASER_HEADLESS") {
116 config.headless = val.eq_ignore_ascii_case("true") || val == "1";
117 }
118
119 if let Ok(val) = env::var("CHASER_EXTRA_ARGS") {
120 config.extra_args = val.split_whitespace().map(|s| s.to_string()).collect();
121 }
122
123 if let Ok(val) = env::var("CHASER_VIRTUAL_DISPLAY") {
124 config.virtual_display = val.eq_ignore_ascii_case("true") || val == "1";
125 }
126
127 config
128 }
129
130 pub fn with_context_limit(mut self, limit: usize) -> Self {
132 self.context_limit = limit;
133 self
134 }
135
136 pub fn with_timeout_ms(mut self, timeout: u64) -> Self {
138 self.timeout_ms = timeout;
139 self
140 }
141
142 pub fn with_timeout(mut self, timeout: Duration) -> Self {
144 self.timeout_ms = timeout.as_millis() as u64;
145 self
146 }
147
148 pub fn with_profile(mut self, profile: Profile) -> Self {
150 self.profile = profile;
151 self
152 }
153
154 pub fn with_lazy_init(mut self, lazy: bool) -> Self {
156 self.lazy_init = lazy;
157 self
158 }
159
160 pub fn with_chrome_path(mut self, path: impl Into<PathBuf>) -> Self {
162 self.chrome_path = Some(path.into());
163 self
164 }
165
166 pub fn with_headless(mut self, headless: bool) -> Self {
168 self.headless = headless;
169 self
170 }
171
172 pub fn with_viewport(mut self, width: u32, height: u32) -> Self {
174 self.viewport_width = width;
175 self.viewport_height = height;
176 self
177 }
178
179 pub fn with_extra_args<I, S>(mut self, args: I) -> Self
182 where
183 I: IntoIterator<Item = S>,
184 S: Into<String>,
185 {
186 self.extra_args = args.into_iter().map(Into::into).collect();
187 self
188 }
189
190 pub fn add_extra_arg(mut self, arg: impl Into<String>) -> Self {
194 self.extra_args.push(arg.into());
195 self
196 }
197
198 pub fn with_virtual_display(mut self, enabled: bool) -> Self {
200 self.virtual_display = enabled;
201 self
202 }
203
204 pub fn timeout(&self) -> Duration {
206 Duration::from_millis(self.timeout_ms)
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn test_default_config() {
216 let config = ChaserConfig::default();
217 assert_eq!(config.context_limit, 20);
218 assert_eq!(config.timeout_ms, 60000);
219 assert_eq!(config.profile, Profile::Windows);
220 assert!(!config.lazy_init);
221 assert!(!config.headless);
222 assert!(config.extra_args.is_empty());
223 }
224
225 #[test]
226 fn test_with_extra_args_replaces() {
227 let config = ChaserConfig::default().with_extra_args(["--no-sandbox", "--disable-gpu"]);
228 assert_eq!(config.extra_args, vec!["--no-sandbox", "--disable-gpu"]);
229 let config2 = config.with_extra_args(vec!["--foo"]);
231 assert_eq!(config2.extra_args, vec!["--foo"]);
232 }
233
234 #[test]
235 fn test_add_extra_arg_appends() {
236 let config = ChaserConfig::default()
237 .add_extra_arg("--no-sandbox")
238 .add_extra_arg("--disable-gpu");
239 assert_eq!(config.extra_args, vec!["--no-sandbox", "--disable-gpu"]);
240 }
241
242 #[test]
243 fn test_builder_pattern() {
244 let config = ChaserConfig::default()
245 .with_context_limit(10)
246 .with_timeout_ms(30000)
247 .with_profile(Profile::Linux)
248 .with_lazy_init(true)
249 .with_headless(true);
250
251 assert_eq!(config.context_limit, 10);
252 assert_eq!(config.timeout_ms, 30000);
253 assert_eq!(config.profile, Profile::Linux);
254 assert!(config.lazy_init);
255 assert!(config.headless);
256 }
257}