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
36impl Default for ChaserConfig {
37 fn default() -> Self {
38 Self {
39 context_limit: 20,
40 timeout_ms: 60000,
41 profile: Profile::Windows,
42 lazy_init: false,
43 chrome_path: None,
44 headless: false,
45 viewport_width: 1920,
46 viewport_height: 1080,
47 }
48 }
49}
50
51impl ChaserConfig {
52 pub fn from_env() -> Self {
62 let mut config = Self::default();
63
64 if let Ok(val) = env::var("CHASER_CONTEXT_LIMIT") {
65 if let Ok(limit) = val.parse() {
66 config.context_limit = limit;
67 }
68 }
69
70 if let Ok(val) = env::var("CHASER_TIMEOUT") {
71 if let Ok(timeout) = val.parse() {
72 config.timeout_ms = timeout;
73 }
74 }
75
76 if let Ok(val) = env::var("CHASER_PROFILE") {
77 if let Some(profile) = Profile::parse(&val) {
78 config.profile = profile;
79 }
80 }
81
82 if let Ok(val) = env::var("CHASER_LAZY_INIT") {
83 config.lazy_init = val.eq_ignore_ascii_case("true") || val == "1";
84 }
85
86 if let Ok(val) = env::var("CHROME_BIN") {
87 config.chrome_path = Some(PathBuf::from(val));
88 }
89
90 if let Ok(val) = env::var("CHASER_HEADLESS") {
91 config.headless = val.eq_ignore_ascii_case("true") || val == "1";
92 }
93
94 config
95 }
96
97 pub fn with_context_limit(mut self, limit: usize) -> Self {
99 self.context_limit = limit;
100 self
101 }
102
103 pub fn with_timeout_ms(mut self, timeout: u64) -> Self {
105 self.timeout_ms = timeout;
106 self
107 }
108
109 pub fn with_timeout(mut self, timeout: Duration) -> Self {
111 self.timeout_ms = timeout.as_millis() as u64;
112 self
113 }
114
115 pub fn with_profile(mut self, profile: Profile) -> Self {
117 self.profile = profile;
118 self
119 }
120
121 pub fn with_lazy_init(mut self, lazy: bool) -> Self {
123 self.lazy_init = lazy;
124 self
125 }
126
127 pub fn with_chrome_path(mut self, path: impl Into<PathBuf>) -> Self {
129 self.chrome_path = Some(path.into());
130 self
131 }
132
133 pub fn with_headless(mut self, headless: bool) -> Self {
135 self.headless = headless;
136 self
137 }
138
139 pub fn with_viewport(mut self, width: u32, height: u32) -> Self {
141 self.viewport_width = width;
142 self.viewport_height = height;
143 self
144 }
145
146 pub fn timeout(&self) -> Duration {
148 Duration::from_millis(self.timeout_ms)
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_default_config() {
158 let config = ChaserConfig::default();
159 assert_eq!(config.context_limit, 20);
160 assert_eq!(config.timeout_ms, 60000);
161 assert_eq!(config.profile, Profile::Windows);
162 assert!(!config.lazy_init);
163 assert!(!config.headless);
164 }
165
166 #[test]
167 fn test_builder_pattern() {
168 let config = ChaserConfig::default()
169 .with_context_limit(10)
170 .with_timeout_ms(30000)
171 .with_profile(Profile::Linux)
172 .with_lazy_init(true)
173 .with_headless(true);
174
175 assert_eq!(config.context_limit, 10);
176 assert_eq!(config.timeout_ms, 30000);
177 assert_eq!(config.profile, Profile::Linux);
178 assert!(config.lazy_init);
179 assert!(config.headless);
180 }
181}