use crate::application::projection_registry::TargetForm;
use crate::domain::error::WireResult;
use crate::infrastructure::template::TemplateEngine;
use async_trait::async_trait;
#[async_trait]
pub trait Projection: Send + Sync {
fn kind(&self) -> &'static str;
async fn render(&self, input: ProjectionInput<'_>) -> WireResult<String>;
}
pub struct ProjectionInput<'a> {
pub spec_result: &'a serde_json::Value,
pub template: &'a str,
pub template_engine: &'a dyn TemplateEngine,
pub target_form: TargetForm,
pub persona_id: Option<&'a str>,
pub config: &'a serde_json::Value,
}
#[derive(Default)]
pub struct StaticProjection;
impl StaticProjection {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl Projection for StaticProjection {
fn kind(&self) -> &'static str {
"static"
}
async fn render(&self, input: ProjectionInput<'_>) -> WireResult<String> {
input
.template_engine
.render(input.template, input.spec_result)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::infrastructure::template::HandlebarsEngine;
use serde_json::json;
#[tokio::test]
async fn static_projection_kind_is_static() {
assert_eq!(StaticProjection::new().kind(), "static");
}
#[tokio::test]
async fn static_projection_delegates_to_template_engine() {
let eng = HandlebarsEngine::new();
let data = json!({"name": "alpha"});
let cfg = json!({});
let input = ProjectionInput {
spec_result: &data,
template: "Hi, {{name}}!",
template_engine: &eng,
target_form: TargetForm::Prompt,
persona_id: None,
config: &cfg,
};
let out = StaticProjection::new().render(input).await.unwrap();
assert_eq!(out, "Hi, alpha!");
}
}