#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ListenerBinding {
pub event: &'static str,
pub listener: &'static str,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct JobBinding {
pub kind: &'static str,
pub version: i16,
pub handler: &'static str,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct CommandBinding {
pub name: &'static str,
pub function: &'static str,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "kind", rename_all = "snake_case"))]
pub enum ScheduleCadence {
Every { seconds: u64 },
Daily { hour: u8, minute: u8 },
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ScheduleBinding {
pub job: &'static str,
pub version: i16,
pub cadence: ScheduleCadence,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ModuleDescriptor {
pub name: &'static str,
pub imports: &'static [&'static str],
pub exports: &'static [&'static str],
pub controllers: &'static [&'static str],
pub controller_methods: &'static [&'static [super::controller_metadata::ControllerMethod]],
pub services: &'static [&'static str],
pub policies: &'static [&'static str],
pub routes: &'static [super::route_metadata::RouteDescriptor],
pub listeners: &'static [ListenerBinding],
pub jobs: &'static [JobBinding],
pub commands: &'static [CommandBinding],
pub schedules: &'static [ScheduleBinding],
}
impl ModuleDescriptor {
pub const fn new(name: &'static str) -> Self {
Self {
name,
imports: &[],
exports: &[],
controllers: &[],
controller_methods: &[],
services: &[],
policies: &[],
routes: &[],
listeners: &[],
jobs: &[],
commands: &[],
schedules: &[],
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ModuleNode {
pub name: &'static str,
pub imports: Vec<&'static str>,
}
impl From<&ModuleDescriptor> for ModuleNode {
fn from(desc: &ModuleDescriptor) -> Self {
ModuleNode {
name: desc.name,
imports: desc.imports.to_vec(),
}
}
}
pub fn module_node_map(
descriptors: &[ModuleDescriptor],
) -> std::collections::BTreeMap<&'static str, ModuleNode> {
descriptors
.iter()
.map(|d| (d.name, ModuleNode::from(d)))
.collect()
}
#[cfg(all(test, feature = "serde"))]
mod serde_tests {
use super::*;
#[test]
fn schedule_cadence_serializes_with_kind_tag() {
let every = ScheduleCadence::Every { seconds: 300 };
assert_eq!(
serde_json::to_string(&every).unwrap(),
r#"{"kind":"every","seconds":300}"#
);
let daily = ScheduleCadence::Daily { hour: 3, minute: 0 };
assert_eq!(
serde_json::to_string(&daily).unwrap(),
r#"{"kind":"daily","hour":3,"minute":0}"#
);
}
#[test]
fn module_descriptor_serializes_to_json() {
const LISTENERS: &[ListenerBinding] = &[ListenerBinding {
event: "UserRegistered",
listener: "send_welcome",
}];
const SCHEDULES: &[ScheduleBinding] = &[ScheduleBinding {
job: "cleanup_sessions",
version: 1,
cadence: ScheduleCadence::Every { seconds: 60 },
}];
const DESCRIPTOR: ModuleDescriptor = ModuleDescriptor {
name: "Links",
imports: &["Accounts"],
exports: &["LinkService"],
controllers: &["LinksController"],
controller_methods: &[],
services: &["LinkService"],
policies: &["LinkPolicy"],
routes: &[],
listeners: LISTENERS,
jobs: &[],
commands: &[],
schedules: SCHEDULES,
};
let json = serde_json::to_string(&DESCRIPTOR).unwrap();
assert!(
json.contains("\"name\":\"Links\""),
"name should serialize: {json}"
);
assert!(
json.contains("\"event\":\"UserRegistered\""),
"listener should serialize: {json}"
);
assert!(
json.contains("\"job\":\"cleanup_sessions\""),
"schedule should serialize: {json}"
);
assert!(
json.contains("\"kind\":\"every\""),
"cadence kind should serialize: {json}"
);
}
}