lmrc-cli 0.3.16

CLI tool for scaffolding LMRC Stack infrastructure projects
Documentation
//! Configuration management

use serde::{Deserialize, Serialize};
use std::collections::HashMap;

// Re-export common config types
pub use lmrc_http_common::config::{ServerConfig, DatabaseConfig as BaseDbConfig};

#[derive(Debug, Clone)]
pub struct Config {
    pub server: ServerConfig,
    pub database: DatabaseConfig,
    pub auth: AuthConfig,
    pub routing: RoutingConfig,
}

/// Gateway-specific database configuration
#[derive(Debug, Clone)]
pub struct DatabaseConfig {
    /// Infrastructure database URL (for infra auth)
    pub infra_url: String,
    /// User database URL (for user auth) - optional if users handle their own auth
    pub user_url: Option<String>,
}

#[derive(Debug, Clone)]
pub struct AuthConfig {
    pub session_expiration_hours: i64,
}

#[derive(Debug, Clone)]
pub struct RoutingConfig {
    /// Backend URL for infra-api
    pub infra_api_url: String,
    /// Backend URL for infra-front
    pub infra_front_url: String,
    /// User service routes: subdomain -> backend URL
    pub user_routes: HashMap<String, String>,
}

#[derive(Debug, Deserialize, Serialize)]
struct UserRouteEntry {
    subdomain: String,
    backend: String,
}

impl Config {
    pub fn from_env() -> anyhow::Result<Self> {
        // Parse user routes from JSON array
        let user_routes_json = std::env::var("USER_ROUTES")
            .unwrap_or_else(|_| "[]".to_string());
        let user_route_entries: Vec<UserRouteEntry> = serde_json::from_str(&user_routes_json)?;
        let mut user_routes = HashMap::new();
        for entry in user_route_entries {
            user_routes.insert(entry.subdomain, entry.backend);
        }

        // Load server config using lmrc-http-common
        let server = ServerConfig {
            host: std::env::var("GATEWAY_HOST")
                .unwrap_or_else(|_| "0.0.0.0".to_string()),
            port: std::env::var("GATEWAY_PORT")
                .unwrap_or_else(|_| "8080".to_string())
                .parse()?,
            cors_origins: std::env::var("CORS_ORIGINS")
                .unwrap_or_else(|_| "http://localhost:3000".to_string())
                .split(',')
                .map(|s| s.trim().to_string())
                .collect(),
        };

        Ok(Self {
            server,
            database: DatabaseConfig {
                infra_url: std::env::var("INFRA_DATABASE_URL")
                    .expect("INFRA_DATABASE_URL must be set"),
                user_url: std::env::var("USER_DATABASE_URL").ok(),
            },
            auth: AuthConfig {
                session_expiration_hours: std::env::var("SESSION_EXPIRATION_HOURS")
                    .unwrap_or_else(|_| "168".to_string())
                    .parse()?,
            },
            routing: RoutingConfig {
                infra_api_url: std::env::var("INFRA_API_URL")
                    .unwrap_or_else(|_| "http://infra-api:8080".to_string()),
                infra_front_url: std::env::var("INFRA_FRONT_URL")
                    .unwrap_or_else(|_| "http://infra-front:3000".to_string()),
                user_routes,
            },
        })
    }
}