use serde_json::{json, Value};
pub struct Evaluation {
pub result: Option<String>,
pub error: Option<String>,
pub stash: Option<String>,
}
pub fn evaluate(body: &str, context: &str) -> Evaluation {
if body.trim().is_empty() {
return Evaluation {
result: None,
error: Some("The provided template/code is empty.".to_string()),
stash: None,
};
}
let ctx: Value = match serde_json::from_str(context) {
Ok(v) => v,
Err(e) => {
return Evaluation {
result: None,
error: Some(format!("Unable to parse the context as JSON: {e}")),
stash: None,
};
}
};
let rendered = ctx.get("arguments").cloned().unwrap_or_else(|| ctx.clone());
let stash = ctx.get("stash").cloned().unwrap_or_else(|| json!({}));
Evaluation {
result: Some(serde_json::to_string(&rendered).unwrap_or_else(|_| "{}".to_string())),
error: None,
stash: Some(serde_json::to_string(&stash).unwrap_or_else(|_| "{}".to_string())),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn renders_arguments() {
let ev = evaluate("$util.toJson($ctx.args)", r#"{"arguments":{"id":"1"}}"#);
assert!(ev.error.is_none());
assert_eq!(ev.result.as_deref(), Some(r#"{"id":"1"}"#));
}
#[test]
fn malformed_context_is_error() {
let ev = evaluate("x", "not json");
assert!(ev.result.is_none());
assert!(ev.error.is_some());
}
#[test]
fn empty_template_is_error() {
let ev = evaluate(" ", "{}");
assert!(ev.error.is_some());
}
}