linear_motion/config/
loader.rs1use super::models::AppConfig;
2use crate::{Error, Result};
3use directories::ProjectDirs;
4use std::path::{Path, PathBuf};
5use tracing::{debug, info};
6
7pub struct ConfigLoader;
8
9impl ConfigLoader {
10 pub fn get_default_config_path() -> Result<PathBuf> {
11 let project_dirs = ProjectDirs::from("com", "linear-motion", "linear-motion")
12 .ok_or_else(|| Error::Other("Could not determine user directories".to_string()))?;
13
14 Ok(project_dirs.config_dir().join("config.json"))
15 }
16
17 pub fn ensure_config_dir() -> Result<PathBuf> {
18 let project_dirs = ProjectDirs::from("com", "linear-motion", "linear-motion")
19 .ok_or_else(|| Error::Other("Could not determine user directories".to_string()))?;
20
21 let config_dir = project_dirs.config_dir();
22 std::fs::create_dir_all(config_dir)?;
23
24 Ok(config_dir.to_path_buf())
25 }
26
27 pub fn get_default_database_path() -> Result<PathBuf> {
28 let project_dirs = ProjectDirs::from("com", "linear-motion", "linear-motion")
29 .ok_or_else(|| Error::Other("Could not determine user directories".to_string()))?;
30
31 Ok(project_dirs.data_dir().join("linear-motion.db"))
32 }
33
34 pub fn ensure_data_dir() -> Result<PathBuf> {
35 let project_dirs = ProjectDirs::from("com", "linear-motion", "linear-motion")
36 .ok_or_else(|| Error::Other("Could not determine user directories".to_string()))?;
37
38 let data_dir = project_dirs.data_dir();
39 std::fs::create_dir_all(data_dir)?;
40
41 Ok(data_dir.to_path_buf())
42 }
43 pub async fn load_from_file<P: AsRef<Path>>(path: P) -> Result<AppConfig> {
44 let path = path.as_ref();
45 debug!("Loading configuration from: {}", path.display());
46
47 if !path.exists() {
48 return Err(Error::Other(format!(
49 "Configuration file {} not found. Run 'linear-motion init' first.",
50 path.display()
51 )));
52 }
53
54 let content = tokio::fs::read_to_string(path).await?;
55 let config: AppConfig = serde_json::from_str(&content)?;
56
57 config.validate()?;
59
60 debug!("configuration loaded successfully from {}", path.display());
61 debug!(
62 "config: {} sync sources, database: {:?}",
63 config.sync_sources.len(),
64 config.database_path()
65 );
66
67 Ok(config)
68 }
69
70 pub fn load_from_file_sync<P: AsRef<Path>>(path: P) -> Result<AppConfig> {
71 let path = path.as_ref();
72 debug!("Loading configuration from: {}", path.display());
73
74 if !path.exists() {
75 return Err(Error::Other(format!(
76 "Configuration file {} not found. Run 'linear-motion init' first.",
77 path.display()
78 )));
79 }
80
81 let content = std::fs::read_to_string(path)?;
82 let config: AppConfig = serde_json::from_str(&content)?;
83
84 config.validate()?;
86
87 info!("Configuration loaded successfully from {}", path.display());
88 debug!(
89 "Config: {} sync sources, database: {:?}",
90 config.sync_sources.len(),
91 config.database_path()
92 );
93
94 Ok(config)
95 }
96
97 pub fn validate_json_file<P: AsRef<Path>>(path: P) -> Result<()> {
98 let path = path.as_ref();
99
100 if !path.exists() {
101 return Err(Error::Other(format!(
102 "Configuration file {} not found",
103 path.display()
104 )));
105 }
106
107 let content = std::fs::read_to_string(path)?;
108 let config: AppConfig = serde_json::from_str(&content)
109 .map_err(|e| Error::Other(format!("JSON parsing error: {}", e)))?;
110
111 config.validate()?;
112
113 Ok(())
114 }
115}