xerv_core/flow/
trigger.rs1use crate::traits::{TriggerConfig, TriggerType};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct TriggerDefinition {
34 pub id: String,
36
37 #[serde(rename = "type")]
39 pub trigger_type: String,
40
41 #[serde(default)]
43 pub params: serde_yaml::Value,
44
45 #[serde(default = "default_enabled")]
47 pub enabled: bool,
48
49 #[serde(default)]
51 pub description: Option<String>,
52}
53
54fn default_enabled() -> bool {
55 true
56}
57
58impl TriggerDefinition {
59 pub fn new(id: impl Into<String>, trigger_type: impl Into<String>) -> Self {
61 Self {
62 id: id.into(),
63 trigger_type: trigger_type.into(),
64 params: serde_yaml::Value::Null,
65 enabled: true,
66 description: None,
67 }
68 }
69
70 pub fn with_params(mut self, params: serde_yaml::Value) -> Self {
72 self.params = params;
73 self
74 }
75
76 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
78 self.description = Some(desc.into());
79 self
80 }
81
82 pub fn disabled(mut self) -> Self {
84 self.enabled = false;
85 self
86 }
87
88 pub fn parsed_type(&self) -> Option<TriggerType> {
90 TriggerType::from_str(&self.trigger_type)
91 }
92
93 pub fn to_trigger_config(&self) -> Option<TriggerConfig> {
95 let trigger_type = self.parsed_type()?;
96 Some(TriggerConfig {
97 id: self.id.clone(),
98 trigger_type,
99 params: self.params.clone(),
100 })
101 }
102
103 pub fn get_string(&self, key: &str) -> Option<&str> {
105 self.params.get(key).and_then(|v| v.as_str())
106 }
107
108 pub fn get_i64(&self, key: &str) -> Option<i64> {
110 self.params.get(key).and_then(|v| v.as_i64())
111 }
112
113 pub fn get_bool(&self, key: &str) -> Option<bool> {
115 self.params.get(key).and_then(|v| v.as_bool())
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn deserialize_webhook_trigger() {
125 let yaml = r#"
126id: api_webhook
127type: webhook
128params:
129 host: "0.0.0.0"
130 port: 8080
131 path: "/orders"
132"#;
133 let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
134 assert_eq!(trigger.id, "api_webhook");
135 assert_eq!(trigger.trigger_type, "webhook");
136 assert_eq!(trigger.parsed_type(), Some(TriggerType::Webhook));
137 assert_eq!(trigger.get_string("host"), Some("0.0.0.0"));
138 assert_eq!(trigger.get_i64("port"), Some(8080));
139 assert!(trigger.enabled);
140 }
141
142 #[test]
143 fn deserialize_cron_trigger() {
144 let yaml = r#"
145id: hourly_sync
146type: cron
147params:
148 schedule: "0 0 * * * *"
149description: "Runs every hour"
150"#;
151 let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
152 assert_eq!(trigger.id, "hourly_sync");
153 assert_eq!(trigger.trigger_type, "cron");
154 assert_eq!(trigger.parsed_type(), Some(TriggerType::Cron));
155 assert_eq!(trigger.get_string("schedule"), Some("0 0 * * * *"));
156 assert_eq!(trigger.description, Some("Runs every hour".to_string()));
157 }
158
159 #[test]
160 fn to_trigger_config() {
161 let def = TriggerDefinition::new("test", "webhook")
162 .with_params(serde_yaml::Value::Mapping(serde_yaml::Mapping::new()));
163
164 let config = def.to_trigger_config().unwrap();
165 assert_eq!(config.id, "test");
166 assert_eq!(config.trigger_type, TriggerType::Webhook);
167 }
168
169 #[test]
170 fn invalid_trigger_type() {
171 let def = TriggerDefinition::new("test", "invalid_type");
172 assert!(def.parsed_type().is_none());
173 assert!(def.to_trigger_config().is_none());
174 }
175
176 #[test]
177 fn disabled_trigger() {
178 let yaml = r#"
179id: disabled_webhook
180type: webhook
181enabled: false
182"#;
183 let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
184 assert!(!trigger.enabled);
185 }
186}