use crate::traits::{TriggerConfig, TriggerType};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TriggerDefinition {
pub id: String,
#[serde(rename = "type")]
pub trigger_type: String,
#[serde(default)]
pub params: serde_yaml::Value,
#[serde(default = "default_enabled")]
pub enabled: bool,
#[serde(default)]
pub description: Option<String>,
}
fn default_enabled() -> bool {
true
}
impl TriggerDefinition {
pub fn new(id: impl Into<String>, trigger_type: impl Into<String>) -> Self {
Self {
id: id.into(),
trigger_type: trigger_type.into(),
params: serde_yaml::Value::Null,
enabled: true,
description: None,
}
}
pub fn with_params(mut self, params: serde_yaml::Value) -> Self {
self.params = params;
self
}
pub fn with_description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
pub fn disabled(mut self) -> Self {
self.enabled = false;
self
}
pub fn parsed_type(&self) -> Option<TriggerType> {
TriggerType::from_str(&self.trigger_type)
}
pub fn to_trigger_config(&self) -> Option<TriggerConfig> {
let trigger_type = self.parsed_type()?;
Some(TriggerConfig {
id: self.id.clone(),
trigger_type,
params: self.params.clone(),
})
}
pub fn get_string(&self, key: &str) -> Option<&str> {
self.params.get(key).and_then(|v| v.as_str())
}
pub fn get_i64(&self, key: &str) -> Option<i64> {
self.params.get(key).and_then(|v| v.as_i64())
}
pub fn get_bool(&self, key: &str) -> Option<bool> {
self.params.get(key).and_then(|v| v.as_bool())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_webhook_trigger() {
let yaml = r#"
id: api_webhook
type: webhook
params:
host: "0.0.0.0"
port: 8080
path: "/orders"
"#;
let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
assert_eq!(trigger.id, "api_webhook");
assert_eq!(trigger.trigger_type, "webhook");
assert_eq!(trigger.parsed_type(), Some(TriggerType::Webhook));
assert_eq!(trigger.get_string("host"), Some("0.0.0.0"));
assert_eq!(trigger.get_i64("port"), Some(8080));
assert!(trigger.enabled);
}
#[test]
fn deserialize_cron_trigger() {
let yaml = r#"
id: hourly_sync
type: cron
params:
schedule: "0 0 * * * *"
description: "Runs every hour"
"#;
let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
assert_eq!(trigger.id, "hourly_sync");
assert_eq!(trigger.trigger_type, "cron");
assert_eq!(trigger.parsed_type(), Some(TriggerType::Cron));
assert_eq!(trigger.get_string("schedule"), Some("0 0 * * * *"));
assert_eq!(trigger.description, Some("Runs every hour".to_string()));
}
#[test]
fn to_trigger_config() {
let def = TriggerDefinition::new("test", "webhook")
.with_params(serde_yaml::Value::Mapping(serde_yaml::Mapping::new()));
let config = def.to_trigger_config().unwrap();
assert_eq!(config.id, "test");
assert_eq!(config.trigger_type, TriggerType::Webhook);
}
#[test]
fn invalid_trigger_type() {
let def = TriggerDefinition::new("test", "invalid_type");
assert!(def.parsed_type().is_none());
assert!(def.to_trigger_config().is_none());
}
#[test]
fn disabled_trigger() {
let yaml = r#"
id: disabled_webhook
type: webhook
enabled: false
"#;
let trigger: TriggerDefinition = serde_yaml::from_str(yaml).unwrap();
assert!(!trigger.enabled);
}
}