Skip to main content

jellyflow_runtime/runtime/xyflow/changes/
model.rs

1use super::{EdgeChange, NodeChange, NodeGraphPatch};
2
3use jellyflow_core::core::{EdgeId, Graph, NodeId};
4use jellyflow_core::ops::GraphTransaction;
5
6/// XyFlow-style node/edge projection of a graph patch.
7///
8/// This adapter is intentionally lossy: it only contains node and edge changes. Use
9/// [`crate::runtime::commit::NodeGraphPatch`] when a consumer must observe full graph resources
10/// such as ports, groups, sticky notes, imports, or symbols.
11#[derive(Debug, Default, Clone)]
12pub struct NodeGraphChanges {
13    pub nodes: Vec<NodeChange>,
14    pub edges: Vec<EdgeChange>,
15}
16
17#[derive(Debug, thiserror::Error)]
18pub enum ChangesToTransactionError {
19    #[error("node not found: {0:?}")]
20    MissingNode(NodeId),
21    #[error("edge not found: {0:?}")]
22    MissingEdge(EdgeId),
23}
24
25impl NodeGraphChanges {
26    pub fn from_parts(nodes: Vec<NodeChange>, edges: Vec<EdgeChange>) -> Self {
27        Self { nodes, edges }
28    }
29
30    pub fn into_parts(self) -> (Vec<NodeChange>, Vec<EdgeChange>) {
31        (self.nodes, self.edges)
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.nodes.is_empty() && self.edges.is_empty()
36    }
37
38    pub fn nodes(&self) -> &[NodeChange] {
39        &self.nodes
40    }
41
42    pub fn edges(&self) -> &[EdgeChange] {
43        &self.edges
44    }
45
46    pub(in crate::runtime::xyflow) fn push_node(&mut self, change: NodeChange) {
47        self.nodes.push(change);
48    }
49
50    pub(in crate::runtime::xyflow) fn push_edge(&mut self, change: EdgeChange) {
51        self.edges.push(change);
52    }
53
54    pub fn from_patch(patch: &NodeGraphPatch) -> Self {
55        crate::runtime::xyflow::projection::XyFlowCommitProjection::from_patch(patch)
56            .into_node_edge_changes()
57    }
58
59    /// Derives change events from a reversible graph transaction.
60    ///
61    /// This is intended for XyFlow-style callbacks such as "on_nodes_change".
62    pub fn from_transaction(tx: &GraphTransaction) -> Self {
63        crate::runtime::xyflow::projection::XyFlowCommitProjection::from_transaction(tx)
64            .into_node_edge_changes()
65    }
66
67    /// Converts change events into a reversible transaction by looking up "from" values in the
68    /// current graph.
69    ///
70    /// This enables an XyFlow-like runtime to accept `(NodeChange, EdgeChange)` and still keep
71    /// `GraphHistory` undo/redo semantics.
72    pub fn to_transaction(
73        &self,
74        graph: &Graph,
75    ) -> Result<GraphTransaction, ChangesToTransactionError> {
76        crate::runtime::xyflow::transaction::changes_to_transaction(self, graph)
77    }
78}