use std::sync::Arc;
use camel_component_api::{CamelError, ComponentBundle, ComponentRegistrar};
use camel_language_api::MinijinjaLimitsConfig;
use serde::Deserialize;
use crate::component::TemplateComponent;
use crate::config::ExternalTemplateLimitsConfig;
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct TemplateBundleConfig {
#[serde(default)]
pub limits: ExternalTemplateLimitsConfig,
#[serde(default)]
pub render_limits: MinijinjaLimitsConfig,
}
pub struct TemplateBundle {
config: TemplateBundleConfig,
}
impl ComponentBundle for TemplateBundle {
fn config_key() -> &'static str {
"template"
}
fn from_toml(value: toml::Value) -> Result<Self, CamelError> {
let config: TemplateBundleConfig = value
.try_into()
.map_err(|e: toml::de::Error| CamelError::Config(e.to_string()))?;
Ok(Self { config })
}
fn register_all(self, ctx: &mut dyn ComponentRegistrar) {
let component = TemplateComponent::new(self.config.limits, self.config.render_limits);
ctx.register_component_dyn(Arc::new(component));
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestRegistrar {
schemes: Vec<String>,
}
impl ComponentRegistrar for TestRegistrar {
fn register_component_dyn(&mut self, component: Arc<dyn camel_component_api::Component>) {
self.schemes.push(component.scheme().to_string());
}
}
#[test]
fn config_key_is_template() {
assert_eq!(TemplateBundle::config_key(), "template");
}
#[test]
fn from_toml_empty_uses_defaults() {
let value: toml::Value = toml::from_str("").unwrap();
let bundle = TemplateBundle::from_toml(value);
assert!(bundle.is_ok(), "empty TOML must use defaults");
}
#[test]
fn from_toml_parses_both_limit_layers() {
let raw = r#"
limits.max-include-count = 8
render-limits.fuel = 1234
"#;
let value: toml::Value = toml::from_str(raw).unwrap();
let bundle = TemplateBundle::from_toml(value).expect("both limit layers must deserialize");
assert_eq!(bundle.config.limits.max_include_count, Some(8));
assert_eq!(bundle.config.render_limits.fuel, Some(1234));
}
#[test]
fn from_toml_rejects_unknown_field() {
let raw = "bogus = 1\n";
let value: toml::Value = toml::from_str(raw).unwrap();
let result = TemplateBundle::from_toml(value);
assert!(result.is_err(), "deny_unknown_fields must reject `bogus`");
}
#[test]
fn register_all_registers_template_scheme() {
let bundle = TemplateBundle::from_toml(toml::Value::Table(toml::map::Map::new())).unwrap();
let mut registrar = TestRegistrar { schemes: vec![] };
bundle.register_all(&mut registrar);
assert_eq!(registrar.schemes, vec!["template"]);
}
}