nexus_common/config/file/
reader.rs1use crate::types::DynError;
2use async_trait::async_trait;
3use serde::de::DeserializeOwned;
4use std::ffi::OsStr;
5use std::fmt::Debug;
6use std::path::{Component, Path, PathBuf};
7use tracing::error;
8
9use super::ConfigLoader;
10
11pub const DEFAULT_HOME_DIR: &str = ".pubky-nexus";
13const DEFAULT_CONFIG_TOML: &str = include_str!("../../../default.config.toml");
14pub const CONFIG_FILE_NAME: &str = "config.toml";
16
17pub fn expand_home_dir(path: PathBuf) -> PathBuf {
20 if let Some(first) = path.components().next() {
21 if first == Component::Normal(OsStr::new("~")) {
22 if let Some(home) = dirs::home_dir() {
23 let without_tilde = path.iter().skip(1).collect::<PathBuf>();
25 return home.join(without_tilde);
26 }
27 }
28 }
29 path
30}
31
32#[async_trait]
33pub trait ConfigReader<T>: ConfigLoader<T>
34where
35 T: DeserializeOwned + Send + Sync + Debug,
36{
37 fn get_config_file_path(expanded_path: &Path) -> PathBuf {
39 expanded_path.join(CONFIG_FILE_NAME)
40 }
41
42 fn write_default_config_file(config_file_path: &PathBuf) -> std::io::Result<()> {
43 if let Some(parent) = config_file_path.parent() {
45 println!(
46 "Validating existence of '{}' and creating it if missing before copying '{CONFIG_FILE_NAME}' file…",
47 parent.display()
48 );
49 std::fs::create_dir_all(parent)?;
50 }
51 std::fs::write(config_file_path, DEFAULT_CONFIG_TOML)?;
53 Ok(())
54 }
55
56 async fn read_config_file(expanded_path: PathBuf) -> Result<T, DynError> {
59 let config_file_path = Self::get_config_file_path(&expanded_path);
60
61 if !config_file_path.exists() {
62 Self::write_default_config_file(&config_file_path)?;
63 }
64 println!(
65 "nexusd reading the '{CONFIG_FILE_NAME}' file from '{}'",
66 expanded_path.display()
67 );
68
69 let config = <Self as ConfigLoader<T>>::load(config_file_path)
70 .await
71 .map_err(|e| {
72 error!(
73 "Failed to load config file {:?}: {}",
74 Self::get_config_file_path(&expanded_path),
75 e
76 );
77 e
78 })?;
79 Ok(config)
80 }
81}
82
83#[async_trait]
87impl<T> ConfigReader<T> for T where T: ConfigLoader<T> + DeserializeOwned + Send + Sync + Debug {}