espforge_lib/resolver/actions/
global.rs1use crate::config::EspforgeConfiguration;
2use crate::manifest::ComponentManifest;
3use crate::register_action_strategy;
4use crate::resolver::actions::{ActionStrategy, ValidationResult};
5use anyhow::{Context, Result, anyhow};
6use espforge_macros::auto_register_action_strategy;
7use serde_yaml_ng::Value;
8use std::collections::HashMap;
9use tera::Tera;
10
11#[derive(Default)]
12#[auto_register_action_strategy]
13pub struct GlobalActionStrategy;
14
15impl GlobalActionStrategy {
16 fn parse_key<'a>(&self, key: &'a str) -> Option<(&'a str, &'a str)> {
17 let parts: Vec<&str> = key.split('.').collect();
19 if parts.len() < 2 {
20 return None;
21 }
22 Some((parts[0], parts[1]))
23 }
24}
25
26impl ActionStrategy for GlobalActionStrategy {
27 fn can_handle(&self, key: &str) -> bool {
28 !key.starts_with('$') && key.contains('.')
31 }
32
33 fn validate(
34 &self,
35 key: &str,
36 _value: &Value,
37 _config: &EspforgeConfiguration,
38 manifests: &HashMap<String, ComponentManifest>,
39 ) -> ValidationResult {
40 let Some((module_name, method_name)) = self.parse_key(key) else {
41 return ValidationResult::Ignored;
42 };
43
44 if let Some(manifest) = manifests.get(module_name) {
45 if manifest.methods.contains_key(method_name) {
46 ValidationResult::Ok(format!(
47 "Validated global action '{}' on module '{}'",
48 method_name, module_name
49 ))
50 } else {
51 ValidationResult::Error(format!(
52 "Method '{}' not found on global module '{}'",
53 method_name, module_name
54 ))
55 }
56 } else {
57 ValidationResult::Ignored
62 }
63 }
64
65 fn render(
66 &self,
67 key: &str,
68 value: &Value,
69 _config: &EspforgeConfiguration,
70 manifests: &HashMap<String, ComponentManifest>,
71 tera: &mut Tera,
72 ) -> Result<String> {
73 let (module_name, method_name) = self
74 .parse_key(key)
75 .ok_or_else(|| anyhow!("Invalid key format"))?;
76
77 let manifest = manifests
78 .get(module_name)
79 .ok_or_else(|| anyhow!("Global module '{}' not found", module_name))?;
80
81 let method_def = manifest.methods.get(method_name).ok_or_else(|| {
82 anyhow!(
83 "Method '{}' not found in module '{}'",
84 method_name,
85 module_name
86 )
87 })?;
88
89 let mut context = tera::Context::new();
90 context.insert("target", module_name); context.insert("args", value);
92
93 tera.render_str(&method_def.template, &context)
94 .with_context(|| format!("Failed to render global action {}", key))
95 }
96}
97
98