openapi_nexus_config/
loader.rs

1//! Configuration file loader
2
3use std::fs;
4use std::path::{Path, PathBuf};
5
6use crate::config_file::ConfigFile;
7use crate::errors::ConfigError;
8use toml;
9
10/// Configuration file loader
11pub struct ConfigLoader;
12
13impl ConfigLoader {
14    /// Discover and load configuration file from standard search paths
15    ///
16    /// Search order:
17    /// 1. ./openapi-nexus-config.toml
18    /// 2. ./.openapi-nexus-config.toml
19    /// 3. ~/.config/openapi-nexus/config.toml
20    /// 4. /etc/openapi-nexus/config.toml
21    pub fn discover_config_file() -> Option<PathBuf> {
22        // 1. Current directory - openapi-nexus-config.toml
23        let current_dir_file = Path::new("openapi-nexus-config.toml");
24        if current_dir_file.exists() {
25            return Some(current_dir_file.to_path_buf());
26        }
27
28        // 2. Current directory - .openapi-nexus-config.toml
29        let hidden_file = Path::new(".openapi-nexus-config.toml");
30        if hidden_file.exists() {
31            return Some(hidden_file.to_path_buf());
32        }
33
34        // 3. User config directory - OS-specific config directory
35        // e.g., ~/.config/openapi-nexus/config.toml on Linux
36        if let Some(config_dir) = dirs::config_dir() {
37            let user_config = config_dir.join("openapi-nexus").join("config.toml");
38            if user_config.exists() {
39                return Some(user_config);
40            }
41        }
42
43        // 4. System config directory - /etc/openapi-nexus/config.toml
44        let system_config = Path::new("/etc/openapi-nexus/config.toml");
45        if system_config.exists() {
46            return Some(system_config.to_path_buf());
47        }
48
49        None
50    }
51
52    /// Load configuration from a specific file path
53    pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<ConfigFile, ConfigError> {
54        let path_buf = path.as_ref().to_path_buf();
55        let content = fs::read_to_string(path.as_ref()).map_err(|e| ConfigError::FileRead {
56            path: path_buf.clone(),
57            source: e,
58        })?;
59
60        toml::from_str(&content).map_err(|e| ConfigError::FileParse {
61            path: path_buf,
62            source: e,
63        })
64    }
65
66    /// Load configuration from discovered file or return default
67    pub fn load_or_default() -> ConfigFile {
68        Self::discover_config_file()
69            .and_then(|path| Self::load_from_file(&path).ok())
70            .unwrap_or_default()
71    }
72}