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}