rush_sync_server/setup/
setup_toml.rs1use crate::core::prelude::*;
3use std::path::PathBuf;
4use tokio::fs;
5
6const DEFAULT_CONFIG: &str = r#"[general]
8max_messages = 1000
9typewriter_delay = 5
10input_max_length = 100
11max_history = 30
12poll_rate = 16
13log_level = "info"
14current_theme = "dark"
15
16[language]
17current = "en"
18
19# =====================================================
20# SERVER CONFIGURATION
21# =====================================================
22[server]
23# Port Management
24port_range_start = 8080 # Starting port for auto-allocation
25port_range_end = 8180 # Maximum port for auto-allocation
26max_concurrent = 10 # Maximum simultaneous servers
27shutdown_timeout = 5 # Graceful shutdown timeout (seconds)
28startup_delay_ms = 500 # Delay after server creation (milliseconds)
29workers = 1 # Actix workers per server
30auto_open_browser = true # Automatically open browser
31
32# HTTPS/TLS Configuration
33enable_https = true # Enable HTTPS support
34https_port_offset = 1000 # HTTPS port = HTTP port + offset
35cert_dir = ".rss/certs" # Certificate storage directory
36auto_cert = true # Generate certificates automatically
37cert_validity_days = 365 # Certificate validity (days)
38
39# Production Settings
40use_lets_encrypt = false # Use Let's Encrypt (requires public domain)
41production_domain = "localhost" # Production domain name
42
43# =====================================================
44# REVERSE PROXY CONFIGURATION
45# =====================================================
46[proxy]
47enabled = true # Enable integrated reverse proxy
48port = 8000 # Proxy listening port
49bind_address = "127.0.0.1" # Proxy bind address
50health_check_interval = 30 # Health check interval (seconds)
51timeout_ms = 5000 # Request timeout (milliseconds)
52
53# For production use:
54# port = 80 # Standard HTTP Port
55# bind_address = "0.0.0.0" # All interfaces (for external access)
56
57# =====================================================
58# LOGGING CONFIGURATION
59# =====================================================
60[logging]
61max_file_size_mb = 100 # Log rotation size (100MB per file)
62max_archive_files = 9 # Archive generations (9 backups)
63compress_archives = true # GZIP compression for archives
64log_requests = true # Enable request logging
65log_security_alerts = true # Enable security monitoring
66log_performance = true # Enable performance metrics
67
68# =====================================================
69# THEME DEFINITIONS
70# =====================================================
71[theme.dark]
72output_bg = "Black"
73output_text = "White"
74output_cursor = "PIPE"
75output_cursor_color = "White"
76input_bg = "White"
77input_text = "Black"
78input_cursor_prefix = "/// "
79input_cursor = "PIPE"
80input_cursor_color = "Black"
81
82[theme.light]
83output_bg = "White"
84output_text = "Black"
85output_cursor = "PIPE"
86output_cursor_color = "Black"
87input_bg = "Black"
88input_text = "White"
89input_cursor_prefix = "/// "
90input_cursor = "PIPE"
91input_cursor_color = "White"
92
93[theme.green]
94output_bg = "Black"
95output_text = "Green"
96output_cursor = "BLOCK"
97output_cursor_color = "Green"
98input_bg = "LightGreen"
99input_text = "Black"
100input_cursor_prefix = "$ "
101input_cursor = "BLOCK"
102input_cursor_color = "Black"
103
104[theme.blue]
105output_bg = "White"
106output_text = "LightBlue"
107output_cursor = "UNDERSCORE"
108output_cursor_color = "Blue"
109input_bg = "Blue"
110input_text = "White"
111input_cursor_prefix = "> "
112input_cursor = "UNDERSCORE"
113input_cursor_color = "White"
114"#;
115
116pub async fn ensure_config_exists() -> Result<PathBuf> {
117 let config_path = get_primary_config_path()?;
118
119 if let Some(parent) = config_path.parent() {
121 fs::create_dir_all(parent).await.map_err(AppError::Io)?;
122 }
123
124 if !config_path.exists() {
126 fs::write(&config_path, DEFAULT_CONFIG)
127 .await
128 .map_err(AppError::Io)?;
129
130 log::info!(
131 "{}",
132 get_translation(
133 "system.config.file_created",
134 &[&config_path.display().to_string()]
135 )
136 );
137 }
138
139 Ok(config_path)
140}
141
142pub fn get_config_paths() -> Vec<PathBuf> {
143 let mut paths = Vec::new();
144
145 if let Ok(exe_path) = std::env::current_exe() {
146 if let Some(base_dir) = exe_path.parent() {
147 paths.push(base_dir.join(".rss/rush.toml"));
149 paths.push(base_dir.join("rush.toml"));
150 paths.push(base_dir.join("config/rush.toml"));
151 }
152 }
153
154 #[cfg(debug_assertions)]
156 {
157 paths.push(PathBuf::from("rush.toml"));
158 paths.push(PathBuf::from("src/rush.toml"));
159 }
160
161 paths
162}
163
164fn get_primary_config_path() -> Result<PathBuf> {
165 let exe_path = std::env::current_exe().map_err(AppError::Io)?;
166 let base_dir = exe_path
167 .parent()
168 .ok_or_else(|| AppError::Validation(get_translation("system.config.dir_error", &[])))?;
169
170 Ok(base_dir.join(".rss/rush.toml"))
171}