busbar_sf_agentscript/graph/
wasm.rs1use super::{export, render, RefGraph};
10use wasm_bindgen::prelude::*;
11
12#[wasm_bindgen]
18pub fn build_graph(ast: JsValue) -> Result<JsValue, JsValue> {
19 let agent: crate::AgentFile = serde_wasm_bindgen::from_value(ast)
20 .map_err(|e| JsValue::from_str(&format!("Failed to deserialize AST: {}", e)))?;
21
22 let graph = RefGraph::from_ast(&agent)
23 .map_err(|e| JsValue::from_str(&format!("Failed to build graph: {}", e)))?;
24
25 let repr = export::GraphRepr::from(&graph);
26 serde_wasm_bindgen::to_value(&repr)
27 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
28}
29
30#[wasm_bindgen]
32pub fn build_graph_from_source(source: &str) -> Result<JsValue, JsValue> {
33 let graph = parse_and_build(source)?;
34 let repr = export::GraphRepr::from(&graph);
35 serde_wasm_bindgen::to_value(&repr)
36 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
37}
38
39#[wasm_bindgen]
45pub fn validate_graph(source: &str) -> Result<JsValue, JsValue> {
46 let graph = parse_and_build(source)?;
47 let result = graph.validate();
48 let repr = export::ValidationResultRepr::from(&result);
49 serde_wasm_bindgen::to_value(&repr)
50 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
51}
52
53#[wasm_bindgen]
59pub fn get_graph_stats(source: &str) -> Result<JsValue, JsValue> {
60 let graph = parse_and_build(source)?;
61 let stats = graph.stats();
62 serde_wasm_bindgen::to_value(&stats)
63 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
64}
65
66#[wasm_bindgen]
72pub fn find_topic_usages(source: &str, topic_name: &str) -> Result<JsValue, JsValue> {
73 let graph = parse_and_build(source)?;
74
75 let topic_idx = graph
76 .get_topic(topic_name)
77 .ok_or_else(|| JsValue::from_str(&format!("Topic '{}' not found", topic_name)))?;
78
79 let usages = graph.find_usages(topic_idx);
80 let nodes: Vec<export::NodeRepr> = usages
81 .nodes
82 .iter()
83 .filter_map(|&idx| graph.get_node(idx).map(export::NodeRepr::from))
84 .collect();
85
86 serde_wasm_bindgen::to_value(&nodes)
87 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
88}
89
90#[wasm_bindgen]
92pub fn find_topic_transitions(source: &str, topic_name: &str) -> Result<JsValue, JsValue> {
93 let graph = parse_and_build(source)?;
94
95 let topic_idx = graph
96 .get_topic(topic_name)
97 .ok_or_else(|| JsValue::from_str(&format!("Topic '{}' not found", topic_name)))?;
98
99 let transitions = graph.find_outgoing_transitions(topic_idx);
100 let nodes: Vec<export::NodeRepr> = transitions
101 .nodes
102 .iter()
103 .filter_map(|&idx| graph.get_node(idx).map(export::NodeRepr::from))
104 .collect();
105
106 serde_wasm_bindgen::to_value(&nodes)
107 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
108}
109
110#[wasm_bindgen]
112pub fn find_variable_usages(source: &str, var_name: &str) -> Result<String, JsValue> {
113 let graph = parse_and_build(source)?;
114
115 let var_idx = graph
116 .get_variable(var_name)
117 .ok_or_else(|| JsValue::from_str(&format!("Variable '{}' not found", var_name)))?;
118
119 let readers = graph.find_variable_readers(var_idx);
120 let writers = graph.find_variable_writers(var_idx);
121
122 let result = export::VariableUsagesRepr {
123 readers: readers
124 .nodes
125 .iter()
126 .filter_map(|&idx| graph.get_node(idx).map(export::UsageInfoRepr::from_node))
127 .collect(),
128 writers: writers
129 .nodes
130 .iter()
131 .filter_map(|&idx| graph.get_node(idx).map(export::UsageInfoRepr::from_node))
132 .collect(),
133 };
134
135 serde_json::to_string(&result)
136 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
137}
138
139#[wasm_bindgen]
145pub fn render_topic_flow(source: &str) -> Result<String, JsValue> {
146 let graph = parse_and_build(source)?;
147 Ok(render::render_topic_flow(&graph))
148}
149
150#[wasm_bindgen]
152pub fn render_graph(source: &str, view: &str) -> Result<String, JsValue> {
153 let graph = parse_and_build(source)?;
154
155 match view {
156 "topics" => Ok(render::render_topic_flow(&graph)),
157 "actions" => Ok(render::render_actions_view(&graph)),
158 "full" => Ok(render::render_full_view(&graph)),
159 _ => Err(JsValue::from_str("Invalid view type. Use 'topics', 'actions', or 'full'")),
160 }
161}
162
163#[wasm_bindgen]
169pub fn export_graph_json(source: &str) -> Result<String, JsValue> {
170 let graph = parse_and_build(source)?;
171 let export = export::GraphExport::from_graph(&graph);
172 serde_json::to_string_pretty(&export)
173 .map_err(|e| JsValue::from_str(&format!("JSON serialization error: {}", e)))
174}
175
176#[wasm_bindgen]
178pub fn export_graph_json_compact(source: &str) -> Result<String, JsValue> {
179 let graph = parse_and_build(source)?;
180 let repr = export::GraphRepr::from(&graph);
181 serde_json::to_string(&repr)
182 .map_err(|e| JsValue::from_str(&format!("JSON serialization error: {}", e)))
183}
184
185#[wasm_bindgen]
193pub fn export_graphml(source: &str) -> Result<String, JsValue> {
194 let graph = parse_and_build(source)?;
195 Ok(render::render_graphml(&graph))
196}
197
198#[wasm_bindgen]
204pub fn extract_dependencies(source: &str) -> Result<JsValue, JsValue> {
205 let agent = crate::parse(source).map_err(|errs| JsValue::from_str(&errs.join("\n")))?;
206
207 let report = super::dependencies::extract_dependencies(&agent);
208 serde_wasm_bindgen::to_value(&report)
209 .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
210}
211
212#[wasm_bindgen]
214pub fn uses_sobject(source: &str, sobject_name: &str) -> Result<bool, JsValue> {
215 let agent = crate::parse(source).map_err(|errs| JsValue::from_str(&errs.join("\n")))?;
216 let report = super::dependencies::extract_dependencies(&agent);
217 Ok(report.uses_sobject(sobject_name))
218}
219
220#[wasm_bindgen]
222pub fn uses_flow(source: &str, flow_name: &str) -> Result<bool, JsValue> {
223 let agent = crate::parse(source).map_err(|errs| JsValue::from_str(&errs.join("\n")))?;
224 let report = super::dependencies::extract_dependencies(&agent);
225 Ok(report.uses_flow(flow_name))
226}
227
228#[wasm_bindgen]
230pub fn uses_apex_class(source: &str, class_name: &str) -> Result<bool, JsValue> {
231 let agent = crate::parse(source).map_err(|errs| JsValue::from_str(&errs.join("\n")))?;
232 let report = super::dependencies::extract_dependencies(&agent);
233 Ok(report.uses_apex_class(class_name))
234}
235
236#[wasm_bindgen]
242pub fn graph_version() -> String {
243 env!("CARGO_PKG_VERSION").to_string()
244}
245
246fn parse_and_build(source: &str) -> Result<RefGraph, JsValue> {
252 let agent = crate::parse(source).map_err(|errs| JsValue::from_str(&errs.join("\n")))?;
253
254 RefGraph::from_ast(&agent)
255 .map_err(|e| JsValue::from_str(&format!("Failed to build graph: {}", e)))
256}