greentic_flow/add_step/
modes.rs

1use std::path::Path;
2
3use serde_json::{Map, Value, json};
4
5use crate::{
6    component_catalog::ComponentCatalog, config_flow::run_config_flow, error::Result,
7    loader::load_ygtc_from_str_with_schema,
8};
9
10use super::normalize::normalize_node_map;
11
12#[derive(Debug, Clone)]
13pub enum AddStepModeInput {
14    Default {
15        component_id: String,
16        pack_alias: Option<String>,
17        operation: Option<String>,
18        payload: Value,
19        routing: Option<Value>,
20    },
21    Config {
22        config_flow: String,
23        schema_path: Box<Path>,
24        answers: Map<String, Value>,
25    },
26}
27
28pub fn materialize_node(
29    mode: AddStepModeInput,
30    _catalog: &dyn ComponentCatalog,
31) -> Result<(Option<String>, Value)> {
32    match mode {
33        AddStepModeInput::Default {
34            component_id,
35            pack_alias,
36            operation,
37            payload,
38            routing,
39        } => {
40            let mut node = serde_json::Map::new();
41            node.insert(component_id.clone(), payload);
42            if let Some(alias) = pack_alias {
43                node.insert("pack_alias".to_string(), Value::String(alias));
44            }
45            if let Some(op) = operation {
46                node.insert("operation".to_string(), Value::String(op));
47            }
48            if let Some(routing) = routing {
49                node.insert("routing".to_string(), routing);
50            } else {
51                node.insert(
52                    "routing".to_string(),
53                    json!([{ "to": crate::splice::NEXT_NODE_PLACEHOLDER }]),
54                );
55            }
56            let value = Value::Object(node.clone());
57            // Ensure shape is valid up front.
58            let _ = normalize_node_map(value.clone())?;
59            Ok((None, value))
60        }
61        AddStepModeInput::Config {
62            config_flow,
63            schema_path,
64            answers,
65        } => {
66            let _doc = load_ygtc_from_str_with_schema(&config_flow, &schema_path)?; // schema validation
67            let output = run_config_flow(&config_flow, &schema_path, &answers)?;
68            let normalized = normalize_node_map(output.node.clone())?;
69            let mut hint = Some(output.node_id.clone());
70            if normalized.component_id.is_empty() {
71                hint = None;
72            }
73            Ok((hint, output.node))
74        }
75    }
76}