Skip to main content

raxit_core/
config.rs

1//! Configuration types for RAXIT scanning
2
3use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5
6/// Output format for scan results
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8#[serde(rename_all = "lowercase")]
9pub enum OutputFormat {
10    #[default]
11    Yaml,
12    Json,
13}
14
15impl OutputFormat {
16    /// Get format from string
17    pub fn from_string(s: &str) -> Self {
18        match s {
19            "json" => Self::Json,
20            _ => Self::Yaml,
21        }
22    }
23}
24
25/// Configuration for RAXIT scan
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ScanConfig {
28    /// Path to scan (directory or file)
29    pub path: PathBuf,
30
31    /// Output format (yaml or json)
32    pub format: OutputFormat,
33
34    /// File patterns to include (glob patterns)
35    #[serde(default = "default_include_patterns")]
36    pub include: Vec<String>,
37
38    /// File patterns to exclude (glob patterns)
39    #[serde(default = "default_exclude_patterns")]
40    pub exclude: Vec<String>,
41
42    /// Enable parallel processing
43    #[serde(default = "default_parallel")]
44    pub parallel: bool,
45
46    /// Maximum number of threads for parallel processing
47    #[serde(default)]
48    pub max_threads: Option<usize>,
49
50    /// Enable incremental scanning with cache
51    #[serde(default)]
52    pub incremental: bool,
53
54    /// Cache directory for incremental scanning
55    #[serde(default = "default_cache_dir")]
56    pub cache_dir: PathBuf,
57
58    /// Enable verbose output
59    #[serde(default)]
60    pub verbose: bool,
61}
62
63fn default_include_patterns() -> Vec<String> {
64    vec!["**/*.py".to_string()]
65}
66
67fn default_exclude_patterns() -> Vec<String> {
68    vec![
69        "**/node_modules/**".to_string(),
70        "**/.venv/**".to_string(),
71        "**/__pycache__/**".to_string(),
72        "**/dist/**".to_string(),
73        "**/build/**".to_string(),
74        "**/.git/**".to_string(),
75    ]
76}
77
78fn default_parallel() -> bool {
79    true
80}
81
82fn default_cache_dir() -> PathBuf {
83    PathBuf::from(".raxit/cache")
84}
85
86impl Default for ScanConfig {
87    fn default() -> Self {
88        Self {
89            path: PathBuf::from("."),
90            format: OutputFormat::Yaml,
91            include: default_include_patterns(),
92            exclude: default_exclude_patterns(),
93            parallel: default_parallel(),
94            max_threads: None,
95            incremental: false,
96            cache_dir: default_cache_dir(),
97            verbose: false,
98        }
99    }
100}
101
102impl ScanConfig {
103    /// Create a new config with the given path
104    pub fn new(path: impl Into<PathBuf>) -> Self {
105        Self {
106            path: path.into(),
107            ..Default::default()
108        }
109    }
110
111    /// Set the scan path
112    pub fn with_path(mut self, path: impl Into<PathBuf>) -> Self {
113        self.path = path.into();
114        self
115    }
116
117    /// Set the output format
118    pub fn with_format(mut self, format: impl AsRef<str>) -> Self {
119        self.format = match format.as_ref() {
120            "json" => OutputFormat::Json,
121            _ => OutputFormat::Yaml,
122        };
123        self
124    }
125
126    /// Add include pattern
127    pub fn with_include(mut self, pattern: impl Into<String>) -> Self {
128        self.include.push(pattern.into());
129        self
130    }
131
132    /// Add exclude pattern
133    pub fn with_exclude(mut self, pattern: impl Into<String>) -> Self {
134        self.exclude.push(pattern.into());
135        self
136    }
137
138    /// Enable/disable parallel processing
139    pub fn with_parallel(mut self, parallel: bool) -> Self {
140        self.parallel = parallel;
141        self
142    }
143
144    /// Set max threads
145    pub fn with_max_threads(mut self, threads: usize) -> Self {
146        self.max_threads = Some(threads);
147        self
148    }
149
150    /// Enable incremental scanning
151    pub fn with_incremental(mut self, incremental: bool) -> Self {
152        self.incremental = incremental;
153        self
154    }
155
156    /// Enable verbose output
157    pub fn with_verbose(mut self, verbose: bool) -> Self {
158        self.verbose = verbose;
159        self
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_default_config() {
169        let config = ScanConfig::default();
170        assert_eq!(config.path, PathBuf::from("."));
171        assert_eq!(config.format, OutputFormat::Yaml);
172        assert!(config.parallel);
173    }
174
175    #[test]
176    fn test_builder_pattern() {
177        let config = ScanConfig::default()
178            .with_path("/my/project")
179            .with_format("json")
180            .with_parallel(false);
181
182        assert_eq!(config.path, PathBuf::from("/my/project"));
183        assert_eq!(config.format, OutputFormat::Json);
184        assert!(!config.parallel);
185    }
186}