plux_lua_manager/
config.rs

1//! Configuration handling for Lua plugins.
2//!
3//! This module provides types and functions for loading and validating
4//! plugin configuration files. Each Lua plugin should include a `config.toml`
5//! file in its root directory that specifies metadata and dependencies.
6//!
7//! # Example
8//!
9//! ```toml
10//! # config.toml
11//! name = "my_plugin"
12//! description = "A sample plugin"
13//! author = "Plugin Author"
14//! version = "0.1.0"
15//!
16//! [dependencies]
17//! other_plugin = "^1.0.0"
18//!
19//! [optional_dependencies]
20//! optional_feature = "^2.0.0"
21//! ```
22
23use std::{collections::HashMap, path::PathBuf};
24
25use plux_rs::{Depend, StdInfo};
26use semver::VersionReq;
27use serde::{Deserialize, Serialize};
28
29use crate::error::ConfigError;
30
31/// Plugin configuration loaded from a `config.toml` file.
32///
33/// This struct represents the configuration for a Lua plugin, including
34/// metadata like name, description, and version, as well as dependency
35/// information.
36#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
37#[serde(deny_unknown_fields)]
38pub struct Config {
39    /// The name of the plugin.
40    ///
41    /// This should be a unique identifier for the plugin, using only
42    /// alphanumeric characters and underscores.
43    pub name: String,
44
45    /// A brief description of what the plugin does.
46    pub description: String,
47
48    /// The author of the plugin.
49    pub author: String,
50
51    /// An optional SPDX license identifier.
52    pub license: Option<String>,
53
54    /// Required dependencies for this plugin.
55    ///
56    /// Maps plugin names to version requirements using semantic versioning.
57    /// Example: `other_plugin = "^1.0.0"`
58    pub depends: Option<HashMap<String, VersionReq>>,
59
60    /// Optional dependencies for this plugin.
61    ///
62    /// These dependencies are not required for the plugin to function,
63    /// but may enable additional features if available.
64    pub optional_depends: Option<HashMap<String, VersionReq>>,
65}
66
67/// Loads and validates a plugin's configuration.
68///
69/// This function reads the `config.toml` file from the specified plugin
70/// directory, parses it into a `Config` struct, and converts it into
71/// the standard plugin information format used by the plugin system.
72///
73/// # Arguments
74///
75/// * `plugin_path` - Path to the plugin directory containing `config.toml`
76///
77/// # Errors
78///
79/// Returns an error if:
80/// - The config file is missing or unreadable
81/// - The config file contains invalid TOML
82/// - Required fields are missing or have invalid values
83pub fn load_config(plugin_path: &PathBuf) -> Result<(Config, StdInfo), ConfigError> {
84    let config_path = plugin_path.join("config.toml");
85    if !config_path.exists() {
86        return Err(ConfigError::NotFound);
87    }
88
89    let config_content = std::fs::read_to_string(&config_path)?;
90    let config: Config = toml::from_str(&config_content)?;
91
92    let info = StdInfo {
93        depends: config.depends.clone().map_or(vec![], |depends| {
94            depends
95                .into_iter()
96                .map(|(id, version)| Depend::new(id, version))
97                .collect()
98        }),
99        optional_depends: config.optional_depends.clone().map_or(vec![], |depends| {
100            depends
101                .into_iter()
102                .map(|(id, version)| Depend::new(id, version))
103                .collect()
104        }),
105    };
106
107    Ok((config, info))
108}