Maintain/Run/
Environment.rs1use std::collections::HashMap;
41
42use crate::Run::{Constant::*, Definition::Profile, Error::Result};
43
44pub fn Resolve(Profile:&Profile, MergeShell:bool, Overrides:&[(String, String)]) -> Result<HashMap<String, String>> {
62 let mut env = HashMap::new();
63
64 ApplyTemplateDefaults(&mut env);
66
67 if MergeShell {
69 MergeShellEnv(&mut env);
70 }
71
72 if let Some(ProfileEnvironment) = &Profile.env {
74 for (Key, Value) in ProfileEnvironment {
75 env.insert(Key.clone(), Value.clone());
76 }
77 }
78
79 for (Key, Value) in Overrides {
81 env.insert(Key.clone(), Value.clone());
82 }
83
84 Ok(env)
85}
86
87fn ApplyTemplateDefaults(env:&mut HashMap<String, String>) {
93 env.entry("NODE_VERSION".to_string()).or_insert("22".to_string());
95
96 env.entry("NODE_OPTIONS".to_string())
97 .or_insert("--max-old-space-size=16384".to_string());
98
99 env.entry("HOT_RELOAD".to_string()).or_insert("true".to_string());
101
102 env.entry("WATCH".to_string()).or_insert("true".to_string());
103
104 env.entry("LIVE_RELOAD_PORT".to_string())
105 .or_insert(DefaultLiveReloadPort.to_string());
106
107 env.entry("Level".to_string()).or_insert("silent".to_string());
109
110 env.entry("RUST_LOG".to_string()).or_insert("info".to_string());
111}
112
113fn MergeShellEnv(env:&mut HashMap<String, String>) {
121 let RelevantVars = [
122 "Browser",
123 "Bundle",
124 "Clean",
125 "Compile",
126 "Debug",
127 "Dependency",
128 "Mountain",
129 "Wind",
130 "Electron",
131 "BrowserProxy",
132 "NODE_ENV",
133 "NODE_VERSION",
134 "NODE_OPTIONS",
135 "RUST_LOG",
136 "AIR_LOG_JSON",
137 "AIR_LOG_FILE",
138 "Level",
139 "HOT_RELOAD",
140 "WATCH",
141 "LIVE_RELOAD_PORT",
142 ];
143
144 for Var in RelevantVars {
145 if let Ok(Value) = std::env::var(Var) {
146 env.insert(Var.to_string(), Value);
147 }
148 }
149}
150
151pub fn Validate(Env:&HashMap<String, String>) -> Vec<String> {
161 let mut Errors = Vec::new();
162
163 if !Env.contains_key("NODE_VERSION") {
165 Errors.push("NODE_VERSION environment variable is required".to_string());
166 }
167
168 if !Env.contains_key("NODE_ENV") {
170 Errors.push("NODE_ENV environment variable is required".to_string());
171 }
172
173 let Workbenches = ["Browser", "Wind", "Mountain", "Electron"];
175
176 let HasWorkbench = Workbenches.iter().any(|W| Env.get(*W).map(|V| V == "true").unwrap_or(false));
177
178 if !HasWorkbench {
179 Errors.push("At least one workbench must be enabled (Browser, Wind, Mountain, or Electron)".to_string());
180 }
181
182 if let Some(PortStr) = Env.get("LIVE_RELOAD_PORT") {
184 if let Ok(Port) = PortStr.parse::<u16>() {
185 if Port == 0 {
186 Errors.push("LIVE_RELOAD_PORT cannot be 0".to_string());
187 }
188 } else {
189 Errors.push("LIVE_RELOAD_PORT must be a valid port number".to_string());
190 }
191 }
192
193 Errors
194}
195
196pub fn get_workbench(env:&HashMap<String, String>) -> Option<String> {
206 let workbenches = [
207 ("Browser", "Browser"),
208 ("Wind", "Wind"),
209 ("Mountain", "Mountain"),
210 ("Electron", "Electron"),
211 ];
212
213 for (var, name) in workbenches {
214 if env.get(var).map(|v| v == "true").unwrap_or(false) {
215 return Some(name.to_string());
216 }
217 }
218
219 None
220}
221
222pub fn is_debug(env:&HashMap<String, String>) -> bool { env.get(DebugEnv).map(|v| v == "true").unwrap_or(false) }
232
233pub fn is_hot_reload_enabled(env:&HashMap<String, String>) -> bool {
243 env.get(HotReloadEnv).map(|v| v == "true").unwrap_or(true)
244}
245
246pub fn is_watch_enabled(env:&HashMap<String, String>) -> bool { env.get(WatchEnv).map(|v| v == "true").unwrap_or(true) }
256
257pub fn format_for_display(env:&HashMap<String, String>) -> String {
267 let mut lines:Vec<String> = env
268 .iter()
269 .map(|(k, v)| {
270 let display_value = if v.is_empty() { "(empty)".to_string() } else { v.clone() };
271 format!(" {} = {}", k, display_value)
272 })
273 .collect();
274
275 lines.sort();
276
277 lines.join("\n")
278}
279
280pub fn filter_run_vars(env:&HashMap<String, String>) -> HashMap<String, String> {
290 let run_prefixes = [
291 "NODE_",
292 "HOT_",
293 "WATCH",
294 "LIVE_",
295 "AIR_",
296 "RUST_",
297 "Browser",
298 "Bundle",
299 "Clean",
300 "Compile",
301 "Debug",
302 "Dependency",
303 "Mountain",
304 "Wind",
305 "Electron",
306 "Level",
307 ];
308
309 env.iter()
310 .filter(|(k, _)| run_prefixes.iter().any(|prefix| k.starts_with(prefix)))
311 .map(|(k, v)| (k.clone(), v.clone()))
312 .collect()
313}