diff --git a/src/common/status.rs b/src/common/status.rs index 92bd806..8d7868d 100644 --- a/src/common/status.rs +++ b/src/common/status.rs @@ -11,14 +11,16 @@ use crate::meta_plugin::MetaPluginType; use crate::filter_plugin::FilterOption; -#[derive(serde::Serialize, serde::Deserialize, #[cfg(feature = "server")] ToSchema, Clone)] +#[derive(serde::Serialize, serde::Deserialize, Clone)] +#[cfg_attr(feature = "server", derive(ToSchema))] pub struct FilterPluginInfo { pub name: String, pub options: Vec, pub description: String, } -#[derive(serde::Serialize, serde::Deserialize, #[cfg(feature = "server")] ToSchema)] +#[derive(serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "server", derive(ToSchema))] pub struct StatusInfo { pub paths: PathInfo, pub compression: Vec, @@ -28,13 +30,14 @@ pub struct StatusInfo { pub configured_meta_plugins: Option>, } -#[derive(serde::Serialize, serde::Deserialize, #[cfg(feature = "server")] ToSchema)] +#[derive(serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "server", derive(ToSchema))] pub struct PathInfo { pub data: String, pub database: String, } -#[derive(serde::Serialize, serde::Deserialize, #[cfg(feature = "server")] ToSchema)] +#[derive(serde::Serialize, serde::Deserialize)] pub struct CompressionInfo { #[serde(rename = "type")] pub compression_type: String, @@ -45,7 +48,8 @@ pub struct CompressionInfo { pub decompress: String, } -#[derive(serde::Serialize, serde::Deserialize, #[cfg(feature = "server")] ToSchema, Clone)] +#[derive(serde::Serialize, serde::Deserialize, Clone)] +#[cfg_attr(feature = "server", derive(ToSchema))] pub struct MetaPluginInfo { pub meta_name: String, pub outputs: std::collections::HashMap, diff --git a/src/config.rs b/src/config.rs index 7417275..a89f17c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -153,23 +153,15 @@ pub struct CompressionPluginConfig { pub name: String, } -#[derive(Debug, Clone, Deserialize, Serialize, #[cfg(feature = "server")] utoipa::ToSchema)] -#[cfg_attr(not(feature = "server"), derive(Debug, Clone, Deserialize, Serialize))] +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "server", derive(utoipa::ToSchema))] pub struct MetaPluginConfig { pub name: String, - #[cfg(feature = "server")] - #[schema(value_type = Object)] #[serde(default)] + #[cfg_attr(feature = "server", schema(value_type = Object))] pub options: std::collections::HashMap, - #[cfg(not(feature = "server"))] - #[serde(default)] - pub options: std::collections::HashMap, - #[cfg(feature = "server")] - #[schema(value_type = Object)] - #[serde(default)] - pub outputs: std::collections::HashMap, - #[cfg(not(feature = "server"))] #[serde(default)] + #[cfg_attr(feature = "server", schema(value_type = Object))] pub outputs: std::collections::HashMap, } @@ -186,281 +178,4 @@ pub struct Settings { pub output_format: Option, #[serde(default)] pub quiet: bool, - #[serde(default)] - pub force: bool, - pub server: Option, - pub compression_plugin: Option, - pub meta_plugins: Option>, -} - -impl Settings { - /// Create unified settings from config and args with proper priority - pub fn new(args: &Args, default_dir: PathBuf) -> Result { - debug!("CONFIG: Creating settings with default dir: {:?}", default_dir); - - let config_path = if let Some(config_path) = &args.options.config { - config_path.clone() - } else if let Ok(env_config) = std::env::var("KEEP_CONFIG") { - PathBuf::from(env_config) - } else { - let default_path = if let Some(home_dir) = std::env::var("HOME").ok() { - let mut path = PathBuf::from(home_dir); - path.push(".config"); - path.push("keep"); - path.push("config.yml"); - path - } else { - PathBuf::from("~/.config/keep/config.yml") - }; - debug!("CONFIG: Using default config path: {:?}", default_path); - default_path - }; - - debug!("CONFIG: Using config path: {:?}", config_path); - - let mut config_builder = config::Config::builder(); - - // Load config file if it exists - if config_path.exists() { - debug!("CONFIG: Loading config file: {:?}", config_path); - config_builder = config_builder.add_source(config::File::from(config_path.clone()).required(false)); - } else { - debug!("CONFIG: Config file does not exist: {:?}", config_path); - } - - // Add environment variables - debug!("CONFIG: Adding environment variables"); - let env_source = config::Environment::with_prefix("KEEP").separator("__").ignore_empty(true); - config_builder = config_builder.add_source(env_source); - - // Override with CLI args - if let Some(dir) = &args.options.dir { - debug!("CONFIG: Overriding dir with CLI arg: {:?}", dir); - config_builder = config_builder.set_override("dir", dir.to_str().unwrap())?; - } - - - if args.options.human_readable { - config_builder = config_builder.set_override("human_readable", true)?; - } - - if let Some(output_format) = &args.options.output_format { - config_builder = config_builder.set_override("output_format", output_format.as_str())?; - } - - if args.options.verbose > 0 { - config_builder = config_builder.set_override("verbose", args.options.verbose)?; - } - - if args.options.quiet { - config_builder = config_builder.set_override("quiet", true)?; - } - - if args.options.force { - config_builder = config_builder.set_override("force", true)?; - } - - if let Some(server_password) = &args.options.server_password { - config_builder = config_builder.set_override("server.password", server_password.as_str())?; - } - - if let Some(server_password_hash) = &args.options.server_password_hash { - config_builder = config_builder.set_override("server.password_hash", server_password_hash.as_str())?; - } - - if let Some(server_address) = &args.mode.server_address { - config_builder = config_builder.set_override("server.address", server_address.as_str())?; - } - - if let Some(server_port) = args.mode.server_port { - config_builder = config_builder.set_override("server.port", server_port)?; - } - - if let Some(compression) = &args.item.compression { - config_builder = config_builder.set_override("compression_plugin.name", compression.as_str())?; - } - - - if !args.item.meta_plugins.is_empty() { - let meta_plugins: Vec> = args.item.meta_plugins - .iter() - .map(|name| { - let mut map = std::collections::HashMap::new(); - map.insert("name".to_string(), name.clone()); - map - }) - .collect(); - config_builder = config_builder.set_override("meta_plugins", meta_plugins)?; - } - - let config = config_builder.build()?; - debug!("CONFIG: Built config, attempting to deserialize"); - - match config.try_deserialize::() { - Ok(mut settings) => { - debug!("CONFIG: Successfully deserialized settings: {:?}", settings); - - // Set defaults for list_format if not provided - if settings.list_format.is_empty() { - debug!("CONFIG: Setting default list_format"); - settings.list_format = vec![ - ColumnConfig { - name: "id".to_string(), - label: "Item".to_string(), - align: ColumnAlignment::Right, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "time".to_string(), - label: "Time".to_string(), - align: ColumnAlignment::Right, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "size".to_string(), - label: "Size".to_string(), - align: ColumnAlignment::Right, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "meta:text_line_count".to_string(), - label: "Lines".to_string(), - align: ColumnAlignment::Right, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "tags".to_string(), - label: "Tags".to_string(), - align: ColumnAlignment::Left, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "meta:hostname_short".to_string(), - label: "Host".to_string(), - align: ColumnAlignment::Left, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ColumnConfig { - name: "meta:command".to_string(), - label: "Command".to_string(), - align: ColumnAlignment::Left, - max_len: None, - fg_color: None, - bg_color: None, - attributes: Vec::new(), - padding: None, - }, - ]; - } - - // Set default meta_plugins to include 'env' if not provided - if settings.meta_plugins.is_none() { - debug!("CONFIG: Setting default meta_plugins to include 'env'"); - settings.meta_plugins = Some(vec![ - MetaPluginConfig { - name: "env".to_string(), - options: std::collections::HashMap::new(), - outputs: std::collections::HashMap::new(), - } - ]); - } - - // Set dir to default if not provided or is empty - if settings.dir == PathBuf::new() { - debug!("CONFIG: Setting default dir: {:?}", default_dir); - settings.dir = default_dir; - } - - debug!("CONFIG: Final settings: {:?}", settings); - Ok(settings) - } - Err(e) => { - error!("CONFIG: Failed to deserialize settings: {}", e); - Err(e.into()) - } - } - } - - pub fn default_dir() -> anyhow::Result { - let mut path = dirs::home_dir() - .ok_or_else(|| anyhow::anyhow!("No home directory found"))?; - path.push(".keep"); - if !path.exists() { - std::fs::create_dir_all(&path)?; - } - Ok(path) - } - - /// Get server password from password_file or directly from config if configured - pub fn get_server_password(&self) -> Result> { - if let Some(server) = &self.server { - // First check for password_file - if let Some(password_file) = &server.password_file { - debug!("CONFIG: Reading password from file: {:?}", password_file); - let password = fs::read_to_string(password_file) - .with_context(|| format!("Failed to read password file: {:?}", password_file))? - .trim() - .to_string(); - return Ok(Some(password)); - } - - // Fall back to direct password field - if let Some(password) = &server.password { - debug!("CONFIG: Using password from config"); - return Ok(Some(password.clone())); - } - } - Ok(None) - } - - // Helper methods to access configuration values - pub fn server_password(&self) -> Option { - self.get_server_password().ok().flatten() - } - - pub fn server_password_hash(&self) -> Option { - self.server.as_ref().and_then(|s| s.password_hash.clone()) - } - - pub fn server_address(&self) -> Option { - self.server.as_ref().and_then(|s| s.address.clone()) - } - - pub fn server_port(&self) -> Option { - self.server.as_ref().and_then(|s| s.port) - } - - pub fn compression(&self) -> Option { - self.compression_plugin.as_ref().map(|c| c.name.clone()) - } - - pub fn meta_plugins_names(&self) -> Vec { - self.meta_plugins.as_ref() - .map(|plugins| plugins.iter().map(|p| p.name.clone()).collect()) - .unwrap_or_default() - } -} + #[serde \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1f2b36e..97ddc9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,6 @@ pub mod compression_engine; pub mod config; pub mod services; pub mod db; -#[cfg(feature = "server")] pub mod meta_plugin; pub mod modes; pub mod plugins; @@ -56,14 +55,14 @@ use filter_plugin::{ // Import all meta plugins to ensure they register themselves #[allow(unused_imports)] -use meta_plugin::{ +use crate::meta_plugin::{ cwd, text, user, shell, shell_pid, keep_pid, digest, read_time, read_rate, hostname, exec, env }; #[cfg(feature = "magic")] #[allow(unused_imports)] -use meta_plugin::magic_file; +use crate::meta_plugin::magic_file; /// Initializes plugins at library load time. ///