feat: Auto-carga de variables de entorno desde archivo .env
- Agregada dependencia dotenvy para parsear archivos .env - Implementada función read_env_file() que lee y parsea archivos .env - Soporta comentarios (#), líneas vacías, y valores con/sin comillas - Auto-detección: si existe .env en WorkingDirectory, se carga automáticamente - Merge inteligente: .env primero, luego variables manuales (sobrescriben) - Las apps ahora pueden usar su .env sin tener que copiar 17+ variables manualmente - Logs claros: informa cuántas variables se cargaron desde .env - Beneficio: registrar apps es mucho más rápido y menos propenso a errores
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -281,6 +281,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
@@ -1332,6 +1338,7 @@ dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"dashmap",
|
||||
"dotenvy",
|
||||
"futures",
|
||||
"regex",
|
||||
"reqwest",
|
||||
|
||||
@@ -17,6 +17,7 @@ tokio-stream = "0.1"
|
||||
regex = "1.10"
|
||||
thiserror = "1.0"
|
||||
dashmap = "5.5"
|
||||
dotenvy = "0.15"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.8"
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::models::ServiceConfig;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::collections::HashMap;
|
||||
use crate::logger::get_logger;
|
||||
|
||||
pub struct ServiceGenerator;
|
||||
@@ -74,8 +75,21 @@ impl ServiceGenerator {
|
||||
format!("{} {}", executable, config.script_path)
|
||||
};
|
||||
|
||||
// Generar variables de entorno del usuario
|
||||
let mut env_lines: Vec<String> = config.environment
|
||||
// 1. Leer variables del archivo .env si existe
|
||||
let env_file_vars = Self::read_env_file(&config.working_directory);
|
||||
|
||||
// 2. Merge: .env primero, luego sobrescribir con variables del config
|
||||
let mut merged_env = env_file_vars.clone();
|
||||
for (key, value) in &config.environment {
|
||||
merged_env.insert(key.clone(), value.clone());
|
||||
}
|
||||
|
||||
if !env_file_vars.is_empty() {
|
||||
logger.info("ServiceGenerator", &format!("📄 Usando {} variables desde .env", env_file_vars.len()));
|
||||
}
|
||||
|
||||
// Generar variables de entorno (desde .env + config manual)
|
||||
let mut env_lines: Vec<String> = merged_env
|
||||
.iter()
|
||||
.map(|(key, value)| format!("Environment=\"{}={}\"", key, value))
|
||||
.collect();
|
||||
@@ -295,4 +309,55 @@ WantedBy=multi-user.target
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Lee el archivo .env del directorio de trabajo y retorna las variables
|
||||
pub fn read_env_file(working_directory: &str) -> HashMap<String, String> {
|
||||
let logger = get_logger();
|
||||
let env_path = Path::new(working_directory).join(".env");
|
||||
|
||||
let mut env_vars = HashMap::new();
|
||||
|
||||
if !env_path.exists() {
|
||||
logger.info("ServiceGenerator", &format!("No se encontró archivo .env en: {}", env_path.display()));
|
||||
return env_vars;
|
||||
}
|
||||
|
||||
logger.info("ServiceGenerator", &format!("Leyendo archivo .env desde: {}", env_path.display()));
|
||||
|
||||
match fs::read_to_string(&env_path) {
|
||||
Ok(content) => {
|
||||
for line in content.lines() {
|
||||
let line = line.trim();
|
||||
|
||||
// Ignorar líneas vacías y comentarios
|
||||
if line.is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parsear línea KEY=VALUE
|
||||
if let Some(pos) = line.find('=') {
|
||||
let key = line[..pos].trim().to_string();
|
||||
let mut value = line[pos + 1..].trim().to_string();
|
||||
|
||||
// Remover comillas simples o dobles
|
||||
if (value.starts_with('\'') && value.ends_with('\'')) ||
|
||||
(value.starts_with('"') && value.ends_with('"')) {
|
||||
value = value[1..value.len()-1].to_string();
|
||||
}
|
||||
|
||||
if !key.is_empty() {
|
||||
env_vars.insert(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("ServiceGenerator", &format!("✅ Cargadas {} variables desde .env", env_vars.len()));
|
||||
}
|
||||
Err(e) => {
|
||||
logger.warning("ServiceGenerator", &format!("Error leyendo .env: {}", e), None);
|
||||
}
|
||||
}
|
||||
|
||||
env_vars
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user