use crate::{Context, MiddlewareResult};
pub trait Middleware: Default {
const NAME: &'static str;
const DESCRIPTION: &'static str = "";
type Input: serde::de::DeserializeOwned + Default + schemars::JsonSchema;
type Output: serde::Serialize + schemars::JsonSchema;
fn execute(&self, ctx: &Context, input: Self::Input) -> MiddlewareResult<Self::Output>;
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::testing::{MockHost, run};
#[derive(serde::Deserialize, Default, schemars::JsonSchema)]
#[serde(default)]
struct GreetInput {
name: String,
times: i64,
}
#[derive(serde::Serialize, schemars::JsonSchema)]
struct GreetOutput {
count: i64,
}
#[derive(Default)]
struct Greet;
impl Middleware for Greet {
const NAME: &'static str = "greet";
const DESCRIPTION: &'static str = "greets";
type Input = GreetInput;
type Output = GreetOutput;
fn execute(&self, ctx: &Context, input: Self::Input) -> MiddlewareResult<Self::Output> {
ctx.log_info(&format!("hi {}", input.name));
MiddlewareResult::ok(GreetOutput { count: input.times })
}
}
#[test]
fn input_derives_a_json_schema() {
let schema = serde_json::to_value(schemars::schema_for!(GreetInput)).unwrap();
assert!(
schema.pointer("/properties/name").is_some(),
"schema must expose properties.name; got {schema}"
);
}
#[test]
fn run_drives_a_middleware_natively() {
let host = MockHost::new();
let ctx = Context::new(&host, "/w".into(), "s".into());
let input: GreetInput = crate::config::from_json_value(r#"{"name":"ada","times":"3"}"#).unwrap();
let w = run(&Greet, &ctx, input).into_wit();
assert!(w.successful);
assert_eq!(host.logs()[0].1, "hi ada");
assert_eq!(w.output.iter().find(|(k, _)| k == "count").unwrap().1, "3");
}
}