#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct JobBinding {
pub kind: &'static str,
pub version: i16,
pub handler: &'static str,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct CommandBinding {
pub name: &'static str,
pub function: &'static str,
}
#[derive(Debug, Clone, PartialEq, Eq, 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 [crate::events::ListenerBinding],
pub jobs: &'static [JobBinding],
pub commands: &'static [CommandBinding],
pub schedules: &'static [crate::jobs::ScheduleBinding],
pub pages: &'static [&'static str],
}
impl ModuleDescriptor {
pub const fn new(name: &'static str) -> Self {
Self {
name,
imports: &[],
exports: &[],
controllers: &[],
controller_methods: &[],
services: &[],
policies: &[],
routes: &[],
listeners: &[],
jobs: &[],
commands: &[],
schedules: &[],
pages: &[],
}
}
}
#[derive(Debug, Clone, 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()
}
pub use crate::events::ListenerBinding;
pub use crate::jobs::{ScheduleBinding, ScheduleCadence};
#[cfg(test)]
mod tests {
use super::*;
use crate::jobs::ScheduleCadence;
#[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_new_has_empty_lists() {
const DESC: ModuleDescriptor = ModuleDescriptor::new("Links");
assert_eq!(DESC.name, "Links");
assert!(DESC.imports.is_empty());
assert!(DESC.controllers.is_empty());
assert!(DESC.routes.is_empty());
}
#[test]
fn module_node_map_builds_from_descriptors() {
const DESCRIPTORS: &[ModuleDescriptor] =
&[ModuleDescriptor::new("A"), ModuleDescriptor::new("B")];
let map = module_node_map(DESCRIPTORS);
assert_eq!(map.len(), 2);
assert!(map.contains_key("A"));
assert!(map.contains_key("B"));
}
#[test]
fn job_binding_serializes_to_json() {
let binding = JobBinding {
kind: "send_email",
version: 2,
handler: "handle_send_email",
};
let json = serde_json::to_string(&binding).unwrap();
assert!(json.contains("\"kind\":\"send_email\""), "{json}");
assert!(json.contains("\"version\":2"), "{json}");
assert!(json.contains("\"handler\":\"handle_send_email\""), "{json}");
}
}