rusty_files/server/
config.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Deserialize, Serialize)]
5pub struct ServerConfig {
6    pub server: ServerSettings,
7    pub database: DatabaseSettings,
8    pub security: SecuritySettings,
9    pub performance: PerformanceSettings,
10    pub logging: LoggingSettings,
11}
12
13#[derive(Debug, Clone, Deserialize, Serialize)]
14pub struct ServerSettings {
15    pub host: String,
16    pub port: u16,
17    pub workers: usize,
18    pub keep_alive: u64,
19    pub client_timeout: u64,
20    pub enable_cors: bool,
21    pub cors_origins: Vec<String>,
22}
23
24#[derive(Debug, Clone, Deserialize, Serialize)]
25pub struct DatabaseSettings {
26    pub path: PathBuf,
27    pub pool_size: u32,
28    pub max_connections: u32,
29    pub connection_timeout: u64,
30}
31
32#[derive(Debug, Clone, Deserialize, Serialize)]
33pub struct SecuritySettings {
34    pub enable_auth: bool,
35    pub jwt_secret: String,
36    pub jwt_expiry: u64,
37    pub api_key: Option<String>,
38    pub rate_limit_per_minute: u32,
39}
40
41#[derive(Debug, Clone, Deserialize, Serialize)]
42pub struct PerformanceSettings {
43    pub max_search_results: usize,
44    pub search_timeout_ms: u64,
45    pub index_batch_size: usize,
46    pub cache_size: usize,
47    pub enable_compression: bool,
48}
49
50#[derive(Debug, Clone, Deserialize, Serialize)]
51pub struct LoggingSettings {
52    pub level: String,
53    pub format: String, // "json" or "pretty"
54    pub file: Option<PathBuf>,
55}
56
57impl Default for ServerConfig {
58    fn default() -> Self {
59        Self {
60            server: ServerSettings {
61                host: "127.0.0.1".to_string(),
62                port: 8080,
63                workers: num_cpus::get(),
64                keep_alive: 75,
65                client_timeout: 30,
66                enable_cors: true,
67                cors_origins: vec!["http://localhost:*".to_string()],
68            },
69            database: DatabaseSettings {
70                path: PathBuf::from("./filesearch.db"),
71                pool_size: 10,
72                max_connections: 100,
73                connection_timeout: 30,
74            },
75            security: SecuritySettings {
76                enable_auth: false,
77                jwt_secret: uuid::Uuid::new_v4().to_string(),
78                jwt_expiry: 3600,
79                api_key: None,
80                rate_limit_per_minute: 100,
81            },
82            performance: PerformanceSettings {
83                max_search_results: 1000,
84                search_timeout_ms: 5000,
85                index_batch_size: 1000,
86                cache_size: 10000,
87                enable_compression: true,
88            },
89            logging: LoggingSettings {
90                level: "info".to_string(),
91                format: "pretty".to_string(),
92                file: None,
93            },
94        }
95    }
96}
97
98impl ServerConfig {
99    pub fn from_file(path: &PathBuf) -> anyhow::Result<Self> {
100        let settings = config::Config::builder()
101            .add_source(config::File::from(path.as_ref()))
102            .add_source(config::Environment::with_prefix("FILESEARCH"))
103            .build()?;
104
105        Ok(settings.try_deserialize()?)
106    }
107
108    pub fn load() -> anyhow::Result<Self> {
109        // Try to load from default locations
110        let config_paths = vec![
111            PathBuf::from("config/default.toml"),
112            PathBuf::from("config.toml"),
113            PathBuf::from("./default.toml"),
114        ];
115
116        for path in config_paths {
117            if path.exists() {
118                return Self::from_file(&path);
119            }
120        }
121
122        // If no config file found, use defaults
123        Ok(Self::default())
124    }
125}