mockforge_core/graph/
mod.rs

1//! Graph visualization data structures for MockForge
2//!
3//! This module provides data structures for representing mock environments
4//! as a dependency graph, showing endpoints, their relationships, state transitions,
5//! and micro-mock connections.
6
7pub mod builder;
8pub mod relationships;
9
10pub use builder::GraphBuilder;
11
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15/// Complete graph data structure containing all nodes, edges, and clusters
16#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase")]
18pub struct GraphData {
19    /// All nodes in the graph (endpoints, services, workspaces)
20    pub nodes: Vec<GraphNode>,
21
22    /// All edges in the graph (dependencies, state transitions, service calls)
23    pub edges: Vec<GraphEdge>,
24
25    /// Clusters for grouping related nodes (micro-mocks, workspaces)
26    pub clusters: Vec<GraphCluster>,
27}
28
29impl GraphData {
30    /// Create a new empty graph
31    pub fn new() -> Self {
32        Self {
33            nodes: Vec::new(),
34            edges: Vec::new(),
35            clusters: Vec::new(),
36        }
37    }
38
39    /// Add a node to the graph
40    pub fn add_node(&mut self, node: GraphNode) {
41        self.nodes.push(node);
42    }
43
44    /// Add an edge to the graph
45    pub fn add_edge(&mut self, edge: GraphEdge) {
46        self.edges.push(edge);
47    }
48
49    /// Add a cluster to the graph
50    pub fn add_cluster(&mut self, cluster: GraphCluster) {
51        self.clusters.push(cluster);
52    }
53
54    /// Find a node by ID
55    pub fn find_node(&self, id: &str) -> Option<&GraphNode> {
56        self.nodes.iter().find(|n| n.id == id)
57    }
58
59    /// Find all edges connected to a node
60    pub fn edges_for_node(&self, node_id: &str) -> Vec<&GraphEdge> {
61        self.edges.iter().filter(|e| e.from == node_id || e.to == node_id).collect()
62    }
63}
64
65impl Default for GraphData {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71/// A node in the graph representing an endpoint, service, or workspace
72#[derive(Debug, Clone, Serialize, Deserialize)]
73#[serde(rename_all = "camelCase")]
74pub struct GraphNode {
75    /// Unique identifier for the node
76    pub id: String,
77
78    /// Human-readable label for the node
79    pub label: String,
80
81    /// Type of node (endpoint, service, workspace)
82    pub node_type: NodeType,
83
84    /// Protocol used by this node (if applicable)
85    pub protocol: Option<Protocol>,
86
87    /// Current state of the node (if state machine is active)
88    pub current_state: Option<String>,
89
90    /// Additional metadata about the node
91    #[serde(default)]
92    pub metadata: HashMap<String, serde_json::Value>,
93}
94
95/// Type of node in the graph
96#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
97#[serde(rename_all = "lowercase")]
98pub enum NodeType {
99    /// An individual endpoint (HTTP, gRPC, WebSocket, etc.)
100    Endpoint,
101
102    /// A service grouping multiple endpoints
103    Service,
104
105    /// A workspace grouping multiple services/endpoints
106    Workspace,
107}
108
109/// Protocol type for endpoints
110#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
111#[serde(rename_all = "lowercase")]
112pub enum Protocol {
113    /// HTTP/REST protocol
114    Http,
115
116    /// gRPC protocol
117    Grpc,
118
119    /// WebSocket protocol
120    Websocket,
121
122    /// GraphQL protocol
123    Graphql,
124
125    /// MQTT protocol
126    Mqtt,
127
128    /// SMTP protocol
129    Smtp,
130
131    /// Kafka protocol
132    Kafka,
133
134    /// AMQP protocol
135    Amqp,
136
137    /// FTP protocol
138    Ftp,
139}
140
141impl From<&str> for Protocol {
142    fn from(s: &str) -> Self {
143        match s.to_lowercase().as_str() {
144            "http" => Protocol::Http,
145            "grpc" => Protocol::Grpc,
146            "websocket" => Protocol::Websocket,
147            "graphql" => Protocol::Graphql,
148            "mqtt" => Protocol::Mqtt,
149            "smtp" => Protocol::Smtp,
150            "kafka" => Protocol::Kafka,
151            "amqp" => Protocol::Amqp,
152            "ftp" => Protocol::Ftp,
153            _ => Protocol::Http, // Default to HTTP
154        }
155    }
156}
157
158/// An edge in the graph representing a relationship between nodes
159#[derive(Debug, Clone, Serialize, Deserialize)]
160#[serde(rename_all = "camelCase")]
161pub struct GraphEdge {
162    /// Source node ID
163    pub from: String,
164
165    /// Target node ID
166    pub to: String,
167
168    /// Type of relationship
169    pub edge_type: EdgeType,
170
171    /// Optional label for the edge
172    pub label: Option<String>,
173
174    /// Additional metadata about the edge
175    #[serde(default)]
176    pub metadata: HashMap<String, serde_json::Value>,
177}
178
179/// Type of edge/relationship in the graph
180#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
181#[serde(rename_all = "lowercase")]
182pub enum EdgeType {
183    /// Dependency relationship (e.g., chain dependency)
184    Dependency,
185
186    /// State transition relationship
187    StateTransition,
188
189    /// Service call relationship (cross-service communication)
190    ServiceCall,
191
192    /// Data flow relationship
193    DataFlow,
194
195    /// Workspace/service grouping relationship
196    Contains,
197}
198
199/// A cluster for grouping related nodes (e.g., micro-mocks, workspaces)
200#[derive(Debug, Clone, Serialize, Deserialize)]
201#[serde(rename_all = "camelCase")]
202pub struct GraphCluster {
203    /// Unique identifier for the cluster
204    pub id: String,
205
206    /// Human-readable label for the cluster
207    pub label: String,
208
209    /// Type of cluster (workspace, service, etc.)
210    pub cluster_type: ClusterType,
211
212    /// IDs of nodes that belong to this cluster
213    pub node_ids: Vec<String>,
214
215    /// Additional metadata about the cluster
216    #[serde(default)]
217    pub metadata: HashMap<String, serde_json::Value>,
218}
219
220/// Type of cluster in the graph
221#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
222#[serde(rename_all = "lowercase")]
223pub enum ClusterType {
224    /// Workspace cluster
225    Workspace,
226
227    /// Service cluster (micro-mock)
228    Service,
229
230    /// Chain cluster (grouping chain-related endpoints)
231    Chain,
232}