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 env.entry("NODE_OPTIONS".to_string())
96 .or_insert("--max-old-space-size=16384".to_string());
97
98 env.entry("HOT_RELOAD".to_string()).or_insert("true".to_string());
100 env.entry("WATCH".to_string()).or_insert("true".to_string());
101 env.entry("LIVE_RELOAD_PORT".to_string())
102 .or_insert(DefaultLiveReloadPort.to_string());
103
104 env.entry("Level".to_string()).or_insert("silent".to_string());
106 env.entry("RUST_LOG".to_string()).or_insert("info".to_string());
107}
108
109fn MergeShellEnv(env:&mut HashMap<String, String>) {
117 let RelevantVars = [
118 "Browser",
119 "Bundle",
120 "Clean",
121 "Compile",
122 "Debug",
123 "Dependency",
124 "Mountain",
125 "Wind",
126 "Electron",
127 "BrowserProxy",
128 "NODE_ENV",
129 "NODE_VERSION",
130 "NODE_OPTIONS",
131 "RUST_LOG",
132 "AIR_LOG_JSON",
133 "AIR_LOG_FILE",
134 "Level",
135 "HOT_RELOAD",
136 "WATCH",
137 "LIVE_RELOAD_PORT",
138 ];
139
140 for Var in RelevantVars {
141 if let Ok(Value) = std::env::var(Var) {
142 env.insert(Var.to_string(), Value);
143 }
144 }
145}
146
147pub fn Validate(Env:&HashMap<String, String>) -> Vec<String> {
157 let mut Errors = Vec::new();
158
159 if !Env.contains_key("NODE_VERSION") {
161 Errors.push("NODE_VERSION environment variable is required".to_string());
162 }
163
164 if !Env.contains_key("NODE_ENV") {
166 Errors.push("NODE_ENV environment variable is required".to_string());
167 }
168
169 let Workbenches = ["Browser", "Wind", "Mountain", "Electron"];
171 let HasWorkbench = Workbenches.iter().any(|W| Env.get(*W).map(|V| V == "true").unwrap_or(false));
172
173 if !HasWorkbench {
174 Errors.push("At least one workbench must be enabled (Browser, Wind, Mountain, or Electron)".to_string());
175 }
176
177 if let Some(PortStr) = Env.get("LIVE_RELOAD_PORT") {
179 if let Ok(Port) = PortStr.parse::<u16>() {
180 if Port == 0 {
181 Errors.push("LIVE_RELOAD_PORT cannot be 0".to_string());
182 }
183 } else {
184 Errors.push("LIVE_RELOAD_PORT must be a valid port number".to_string());
185 }
186 }
187
188 Errors
189}
190
191pub fn get_workbench(env:&HashMap<String, String>) -> Option<String> {
201 let workbenches = [
202 ("Browser", "Browser"),
203 ("Wind", "Wind"),
204 ("Mountain", "Mountain"),
205 ("Electron", "Electron"),
206 ];
207
208 for (var, name) in workbenches {
209 if env.get(var).map(|v| v == "true").unwrap_or(false) {
210 return Some(name.to_string());
211 }
212 }
213
214 None
215}
216
217pub fn is_debug(env:&HashMap<String, String>) -> bool { env.get(DebugEnv).map(|v| v == "true").unwrap_or(false) }
227
228pub fn is_hot_reload_enabled(env:&HashMap<String, String>) -> bool {
238 env.get(HotReloadEnv).map(|v| v == "true").unwrap_or(true)
239}
240
241pub fn is_watch_enabled(env:&HashMap<String, String>) -> bool { env.get(WatchEnv).map(|v| v == "true").unwrap_or(true) }
251
252pub fn format_for_display(env:&HashMap<String, String>) -> String {
262 let mut lines:Vec<String> = env
263 .iter()
264 .map(|(k, v)| {
265 let display_value = if v.is_empty() { "(empty)".to_string() } else { v.clone() };
266 format!(" {} = {}", k, display_value)
267 })
268 .collect();
269
270 lines.sort();
271 lines.join("\n")
272}
273
274pub fn filter_run_vars(env:&HashMap<String, String>) -> HashMap<String, String> {
284 let run_prefixes = [
285 "NODE_",
286 "HOT_",
287 "WATCH",
288 "LIVE_",
289 "AIR_",
290 "RUST_",
291 "Browser",
292 "Bundle",
293 "Clean",
294 "Compile",
295 "Debug",
296 "Dependency",
297 "Mountain",
298 "Wind",
299 "Electron",
300 "Level",
301 ];
302
303 env.iter()
304 .filter(|(k, _)| run_prefixes.iter().any(|prefix| k.starts_with(prefix)))
305 .map(|(k, v)| (k.clone(), v.clone()))
306 .collect()
307}