nerve/cli/
config.rs

1//! Config Module
2//!
3//! Provides CLI configuration management and validation.
4
5use serde::{Deserialize, Serialize};
6use std::fs;
7use std::path::Path;
8
9/// CLI configuration structure
10#[derive(Debug, Serialize, Deserialize)]
11pub struct CliConfiguration {
12    /// Default output format
13    pub default_format: String,
14
15    /// Verbose mode enabled by default
16    pub verbose: bool,
17
18    /// Default configuration file path
19    pub config_file: Option<String>,
20
21    /// Color output enabled
22    pub color_output: bool,
23
24    /// Auto-refresh interval for monitoring commands
25    pub refresh_interval: u64,
26
27    /// Performance monitoring settings
28    pub performance: PerformanceConfig,
29
30    /// Debug settings
31    pub debug: DebugConfig,
32}
33
34/// Performance monitoring configuration
35#[derive(Debug, Serialize, Deserialize)]
36pub struct PerformanceConfig {
37    /// Enable real-time performance monitoring
38    pub realtime_monitoring: bool,
39
40    /// Performance sampling interval in milliseconds
41    pub sampling_interval: u64,
42
43    /// Performance history retention period
44    pub history_retention: u64,
45
46    /// Performance threshold alerts
47    pub threshold_alerts: bool,
48}
49
50/// Debug configuration
51#[derive(Debug, Serialize, Deserialize)]
52pub struct DebugConfig {
53    /// Enable detailed debugging output
54    pub detailed_debug: bool,
55
56    /// Enable stack traces
57    pub stack_traces: bool,
58
59    /// Enable memory profiling
60    pub memory_profiling: bool,
61
62    /// Enable thread profiling
63    pub thread_profiling: bool,
64
65    /// Debug log level
66    pub log_level: String,
67}
68
69impl Default for CliConfiguration {
70    fn default() -> Self {
71        Self {
72            default_format: "text".to_string(),
73            verbose: false,
74            config_file: None,
75            color_output: true,
76            refresh_interval: 5,
77            performance: PerformanceConfig::default(),
78            debug: DebugConfig::default(),
79        }
80    }
81}
82
83impl Default for PerformanceConfig {
84    fn default() -> Self {
85        Self {
86            realtime_monitoring: true,
87            sampling_interval: 1000,
88            history_retention: 3600,
89            threshold_alerts: true,
90        }
91    }
92}
93
94impl Default for DebugConfig {
95    fn default() -> Self {
96        Self {
97            detailed_debug: false,
98            stack_traces: false,
99            memory_profiling: false,
100            thread_profiling: false,
101            log_level: "info".to_string(),
102        }
103    }
104}
105
106/// CLI configuration manager
107pub struct ConfigManager {
108    config: CliConfiguration,
109}
110
111impl ConfigManager {
112    /// Create a new configuration manager
113    pub fn new() -> Self {
114        Self {
115            config: CliConfiguration::default(),
116        }
117    }
118
119    /// Load configuration from file
120    pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Box<dyn std::error::Error>> {
121        let content = fs::read_to_string(path)?;
122        self.config = serde_yaml::from_str(&content)?;
123        Ok(())
124    }
125
126    /// Save configuration to file
127    pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Box<dyn std::error::Error>> {
128        let content = serde_yaml::to_string(&self.config)?;
129        fs::write(path, content)?;
130        Ok(())
131    }
132
133    /// Get current configuration
134    pub fn get_config(&self) -> &CliConfiguration {
135        &self.config
136    }
137
138    /// Update configuration
139    pub fn update_config(&mut self, new_config: CliConfiguration) {
140        self.config = new_config;
141    }
142
143    /// Validate configuration
144    pub fn validate(&self) -> Result<(), Vec<String>> {
145        let mut errors = Vec::new();
146
147        // Validate output format
148        if !["text", "json", "yaml"].contains(&self.config.default_format.as_str()) {
149            errors.push("Invalid default format. Must be one of: text, json, yaml".to_string());
150        }
151
152        // Validate refresh interval
153        if self.config.refresh_interval == 0 {
154            errors.push("Refresh interval must be greater than 0".to_string());
155        }
156
157        // Validate performance configuration
158        if self.config.performance.sampling_interval == 0 {
159            errors.push("Performance sampling interval must be greater than 0".to_string());
160        }
161
162        // Validate debug log level
163        if !["error", "warn", "info", "debug", "trace"].contains(&self.config.debug.log_level.as_str()) {
164            errors.push("Invalid debug log level".to_string());
165        }
166
167        if errors.is_empty() {
168            Ok(())
169        } else {
170            Err(errors)
171        }
172    }
173
174    /// Generate configuration template
175    pub fn generate_template() -> String {
176        let template = CliConfiguration::default();
177        serde_yaml::to_string(&template).unwrap_or_else(|_| "# Error generating template".to_string())
178    }
179}