Skip to main content

cards2pack_core/
http_inject.rs

1//! Synthesize HTTP flow nodes from `CardKind::Http` entries.
2
3use crate::routing::{RouteEdge, RoutingGraph};
4use crate::types::{CardEntry, CardKind, HttpConfig};
5
6/// Information about each HTTP node that the emitter will render.
7#[derive(Debug, Clone, PartialEq)]
8pub struct HttpNode {
9    pub id: String,
10    pub config: HttpConfig,
11}
12
13/// Append HTTP-derived nodes to the routing graph and return the list of HTTP nodes
14/// for the emitter to materialize.
15pub fn inject_http_nodes(cards: &[CardEntry], routing: &mut RoutingGraph) -> Vec<HttpNode> {
16    let mut http_nodes = Vec::new();
17    let known: std::collections::HashSet<&str> = cards.iter().map(|c| c.id.as_str()).collect();
18
19    for card in cards {
20        let CardKind::Http(cfg) = &card.kind else {
21            continue;
22        };
23        http_nodes.push(HttpNode {
24            id: card.id.clone(),
25            config: cfg.clone(),
26        });
27
28        if let Some(next) = cfg.next_entry_id.as_deref()
29            && known.contains(next)
30        {
31            routing.edges.insert(
32                card.id.clone(),
33                vec![RouteEdge {
34                    action_id: format!("after_{}", card.id),
35                    target: next.to_owned(),
36                }],
37            );
38        }
39    }
40
41    http_nodes
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::types::CardKind;
48    use serde_json::json;
49
50    fn ac_card(id: &str) -> CardEntry {
51        CardEntry {
52            id: id.into(),
53            kind: CardKind::AdaptiveCard(json!({})),
54        }
55    }
56
57    #[test]
58    fn emits_http_node_with_next_route() {
59        let cards = vec![
60            ac_card("welcome"),
61            CardEntry {
62                id: "api".into(),
63                kind: CardKind::Http(HttpConfig {
64                    url: "https://x".into(),
65                    method: "GET".into(),
66                    next_entry_id: Some("done".into()),
67                    ..Default::default()
68                }),
69            },
70            ac_card("done"),
71        ];
72        let mut routing = RoutingGraph::default();
73        let nodes = inject_http_nodes(&cards, &mut routing);
74        assert_eq!(nodes.len(), 1);
75        assert_eq!(nodes[0].id, "api");
76        let route = routing.edges.get("api").unwrap();
77        assert_eq!(route[0].target, "done");
78    }
79}