moduforge_rules_engine/handler/function/module/
zen.rs1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use crate::handler::custom_node_adapter::CustomNodeAdapter;
6use crate::handler::function::error::{FunctionResult, ResultExt};
7use crate::handler::function::listener::{RuntimeEvent, RuntimeListener};
8use crate::handler::function::module::export_default;
9use crate::handler::function::serde::JsValue;
10use crate::handler::graph::{DecisionGraph, DecisionGraphConfig};
11use crate::loader::DecisionLoader;
12use rquickjs::module::{Declarations, Exports, ModuleDef};
13use rquickjs::prelude::{Async, Func, Opt};
14use rquickjs::{CatchResultExt, Ctx, Function, Object};
15
16pub struct ZenListener<Loader, Adapter> {
17 pub loader: Arc<Loader>,
18 pub adapter: Arc<Adapter>,
19}
20
21impl<Loader: DecisionLoader + 'static, Adapter: CustomNodeAdapter + 'static>
22 RuntimeListener for ZenListener<Loader, Adapter>
23{
24 fn on_event<'js>(
25 &self,
26 ctx: Ctx<'js>,
27 event: RuntimeEvent,
28 ) -> Pin<Box<dyn Future<Output = FunctionResult> + 'js>> {
29 let loader = self.loader.clone();
30 let adapter = self.adapter.clone();
31
32 Box::pin(async move {
33 if event != RuntimeEvent::Startup {
34 return Ok(());
35 };
36
37 ctx.globals()
38 .set(
39 "__evaluate",
40 Func::from(Async(
41 move |ctx: Ctx<'js>,
42 key: String,
43 context: JsValue,
44 opts: Opt<Object<'js>>| {
45 let loader = loader.clone();
46 let adapter = adapter.clone();
47
48 async move {
49 let config: Object = ctx
50 .globals()
51 .get("config")
52 .or_throw(&ctx)?;
53
54 let iteration: u8 =
55 config.get("iteration").or_throw(&ctx)?;
56 let max_depth: u8 =
57 config.get("maxDepth").or_throw(&ctx)?;
58 let trace = opts
59 .0
60 .map(|opt| {
61 opt.get::<_, bool>("trace")
62 .unwrap_or_default()
63 })
64 .unwrap_or_default();
65
66 let load_result =
67 loader.load(key.as_str()).await;
68 let decision_content =
69 load_result.or_throw(&ctx)?;
70 let mut sub_tree = DecisionGraph::try_new(
71 DecisionGraphConfig {
72 content: decision_content,
73 max_depth,
74 loader,
75 adapter,
76 iteration: iteration + 1,
77 trace,
78 validator_cache: None,
79 },
80 )
81 .or_throw(&ctx)?;
82
83 let response = sub_tree
84 .evaluate(context.0)
85 .await
86 .or_throw(&ctx)?;
87 let k = serde_json::to_value(response)
88 .or_throw(&ctx)?
89 .into();
90
91 return rquickjs::Result::Ok(JsValue(k));
92 }
93 },
94 )),
95 )
96 .catch(&ctx)?;
97
98 Ok(())
99 })
100 }
101}
102
103fn evaluate_expression<'js>(
104 ctx: Ctx<'js>,
105 expression: String,
106 context: JsValue,
107) -> rquickjs::Result<JsValue> {
108 let s = moduforge_rules_expression::evaluate_expression(
109 expression.as_str(),
110 context.0,
111 )
112 .or_throw(&ctx)?;
113
114 Ok(JsValue(s))
115}
116
117fn evaluate_unary_expression<'js>(
118 ctx: Ctx<'js>,
119 expression: String,
120 context: JsValue,
121) -> rquickjs::Result<bool> {
122 let s = moduforge_rules_expression::evaluate_unary_expression(
123 expression.as_str(),
124 context.0,
125 )
126 .or_throw(&ctx)?;
127
128 Ok(s)
129}
130
131fn evaluate<'js>(
132 ctx: Ctx<'js>,
133 key: String,
134 context: JsValue,
135 opts: Opt<Object<'js>>,
136) -> rquickjs::Result<rquickjs::Value<'js>> {
137 let s: Function = ctx.globals().get("__evaluate").or_throw(&ctx)?;
138 let result: rquickjs::Value =
139 s.call((key, context, opts)).or_throw(&ctx)?;
140 Ok(result)
141}
142
143pub struct ZenModule;
144
145impl ModuleDef for ZenModule {
146 fn declare<'js>(decl: &Declarations<'js>) -> rquickjs::Result<()> {
147 decl.declare("evaluateExpression")?;
148 decl.declare("evaluateUnaryExpression")?;
149 decl.declare("evaluate")?;
150
151 decl.declare("default")?;
152
153 Ok(())
154 }
155
156 fn evaluate<'js>(
157 ctx: &Ctx<'js>,
158 exports: &Exports<'js>,
159 ) -> rquickjs::Result<()> {
160 export_default(ctx, exports, |default| {
161 default
162 .set("evaluateExpression", Func::from(evaluate_expression))?;
163 default.set(
164 "evaluateUnaryExpression",
165 Func::from(evaluate_unary_expression),
166 )?;
167 default.set("evaluate", Func::from(evaluate))?;
168
169 Ok(())
170 })
171 }
172}