Skip to main content

jellyflow_core/ops/transaction/
op.rs

1use serde::{Deserialize, Serialize};
2
3use crate::core::{
4    Binding, BindingEndpoint, BindingId, CanvasPoint, CanvasRect, CanvasSize, Edge, EdgeId,
5    EdgeKind, EdgeReconnectable, EdgeViewDescriptor, GraphId, GraphImport, Group, GroupId, Node,
6    NodeExtent, NodeId, NodeKindKey, NodeOrigin, Port, PortId, StickyNote, StickyNoteId, Symbol,
7    SymbolId,
8};
9use crate::types::TypeDesc;
10
11use super::endpoints::EdgeEndpoints;
12
13/// A reversible edit operation.
14///
15/// Destructive variants carry the removed data so the operation can be inverted for undo/redo.
16/// Higher-level tools should batch multiple ops into a single transaction.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(tag = "op", rename_all = "snake_case")]
19pub enum GraphOp {
20    /// Adds a node.
21    AddNode { id: NodeId, node: Node },
22    /// Removes a node.
23    ///
24    /// This operation is expected to remove associated ports and edges as well.
25    RemoveNode {
26        id: NodeId,
27        node: Node,
28        #[serde(default, skip_serializing_if = "Vec::is_empty")]
29        ports: Vec<(PortId, Port)>,
30        #[serde(default, skip_serializing_if = "Vec::is_empty")]
31        edges: Vec<(EdgeId, Edge)>,
32        #[serde(default, skip_serializing_if = "Vec::is_empty")]
33        bindings: Vec<(BindingId, Binding)>,
34    },
35    /// Sets a node position.
36    SetNodePos {
37        id: NodeId,
38        from: CanvasPoint,
39        to: CanvasPoint,
40    },
41    /// Sets a node origin override.
42    SetNodeOrigin {
43        id: NodeId,
44        from: Option<NodeOrigin>,
45        to: Option<NodeOrigin>,
46    },
47    /// Sets a node kind identifier.
48    SetNodeKind {
49        id: NodeId,
50        from: NodeKindKey,
51        to: NodeKindKey,
52    },
53    /// Sets a node kind version (for per-kind migrations).
54    SetNodeKindVersion { id: NodeId, from: u32, to: u32 },
55    /// Sets a node selectable override.
56    SetNodeSelectable {
57        id: NodeId,
58        from: Option<bool>,
59        to: Option<bool>,
60    },
61    /// Sets a node focusable override.
62    SetNodeFocusable {
63        id: NodeId,
64        from: Option<bool>,
65        to: Option<bool>,
66    },
67    /// Sets a node draggable override.
68    SetNodeDraggable {
69        id: NodeId,
70        from: Option<bool>,
71        to: Option<bool>,
72    },
73    /// Sets a node connectable override.
74    SetNodeConnectable {
75        id: NodeId,
76        from: Option<bool>,
77        to: Option<bool>,
78    },
79    /// Sets a node deletable override.
80    SetNodeDeletable {
81        id: NodeId,
82        from: Option<bool>,
83        to: Option<bool>,
84    },
85    /// Sets a node parent container (group frame).
86    SetNodeParent {
87        id: NodeId,
88        from: Option<GroupId>,
89        to: Option<GroupId>,
90    },
91    /// Sets a node extent override.
92    SetNodeExtent {
93        id: NodeId,
94        from: Option<NodeExtent>,
95        to: Option<NodeExtent>,
96    },
97    /// Sets a node expand-parent override.
98    SetNodeExpandParent {
99        id: NodeId,
100        from: Option<bool>,
101        to: Option<bool>,
102    },
103    /// Sets a node explicit size.
104    SetNodeSize {
105        id: NodeId,
106        from: Option<CanvasSize>,
107        to: Option<CanvasSize>,
108    },
109    /// Sets a node hidden state.
110    SetNodeHidden { id: NodeId, from: bool, to: bool },
111    /// Sets a node collapsed state.
112    SetNodeCollapsed { id: NodeId, from: bool, to: bool },
113    /// Sets a node's port ordering.
114    SetNodePorts {
115        id: NodeId,
116        from: Vec<PortId>,
117        to: Vec<PortId>,
118    },
119    /// Sets a node's domain-owned data payload.
120    ///
121    /// This is the primary edit op for node parameters and is intentionally untyped at the model
122    /// layer: typing and validation live in profiles/rules.
123    SetNodeData {
124        id: NodeId,
125        from: serde_json::Value,
126        to: serde_json::Value,
127    },
128
129    /// Adds a port.
130    AddPort { id: PortId, port: Port },
131    /// Removes a port.
132    ///
133    /// This operation is expected to remove associated edges as well.
134    RemovePort {
135        id: PortId,
136        port: Port,
137        #[serde(default, skip_serializing_if = "Vec::is_empty")]
138        edges: Vec<(EdgeId, Edge)>,
139        #[serde(default, skip_serializing_if = "Vec::is_empty")]
140        bindings: Vec<(BindingId, Binding)>,
141    },
142    /// Sets a port connectable override.
143    SetPortConnectable {
144        id: PortId,
145        from: Option<bool>,
146        to: Option<bool>,
147    },
148    /// Sets a port start-connectable override.
149    SetPortConnectableStart {
150        id: PortId,
151        from: Option<bool>,
152        to: Option<bool>,
153    },
154    /// Sets a port end-connectable override.
155    SetPortConnectableEnd {
156        id: PortId,
157        from: Option<bool>,
158        to: Option<bool>,
159    },
160    /// Sets a port type descriptor.
161    SetPortType {
162        id: PortId,
163        from: Option<TypeDesc>,
164        to: Option<TypeDesc>,
165    },
166    /// Sets a port domain-owned data payload.
167    SetPortData {
168        id: PortId,
169        from: serde_json::Value,
170        to: serde_json::Value,
171    },
172
173    /// Adds an edge.
174    AddEdge { id: EdgeId, edge: Edge },
175    /// Removes an edge.
176    RemoveEdge {
177        id: EdgeId,
178        edge: Edge,
179        #[serde(default, skip_serializing_if = "Vec::is_empty")]
180        bindings: Vec<(BindingId, Binding)>,
181    },
182    /// Sets an edge kind.
183    SetEdgeKind {
184        id: EdgeId,
185        from: EdgeKind,
186        to: EdgeKind,
187    },
188    /// Sets an edge selectable override.
189    SetEdgeSelectable {
190        id: EdgeId,
191        from: Option<bool>,
192        to: Option<bool>,
193    },
194    /// Sets an edge focusable override.
195    SetEdgeFocusable {
196        id: EdgeId,
197        from: Option<bool>,
198        to: Option<bool>,
199    },
200    /// Sets an edge hidden flag.
201    SetEdgeHidden { id: EdgeId, from: bool, to: bool },
202    /// Sets an edge hit-test interaction width override.
203    SetEdgeInteractionWidth {
204        id: EdgeId,
205        from: Option<f32>,
206        to: Option<f32>,
207    },
208    /// Sets an edge deletable override.
209    SetEdgeDeletable {
210        id: EdgeId,
211        from: Option<bool>,
212        to: Option<bool>,
213    },
214    /// Sets an edge reconnectable override.
215    SetEdgeReconnectable {
216        id: EdgeId,
217        from: Option<EdgeReconnectable>,
218        to: Option<EdgeReconnectable>,
219    },
220    /// Sets an edge's domain-owned data payload.
221    SetEdgeData {
222        id: EdgeId,
223        from: serde_json::Value,
224        to: serde_json::Value,
225    },
226    /// Sets an edge's renderer-neutral view descriptor.
227    SetEdgeView {
228        id: EdgeId,
229        from: EdgeViewDescriptor,
230        to: EdgeViewDescriptor,
231    },
232    /// Sets an edge's endpoints (preserving edge identity for reconnection workflows).
233    SetEdgeEndpoints {
234        id: EdgeId,
235        from: EdgeEndpoints,
236        to: EdgeEndpoints,
237    },
238
239    /// Adds a graph import reference.
240    AddImport { id: GraphId, import: GraphImport },
241    /// Removes a graph import reference.
242    RemoveImport { id: GraphId, import: GraphImport },
243    /// Sets an import alias.
244    SetImportAlias {
245        id: GraphId,
246        from: Option<String>,
247        to: Option<String>,
248    },
249
250    /// Adds a symbol.
251    AddSymbol { id: SymbolId, symbol: Symbol },
252    /// Removes a symbol.
253    RemoveSymbol { id: SymbolId, symbol: Symbol },
254    /// Sets a symbol name.
255    SetSymbolName {
256        id: SymbolId,
257        from: String,
258        to: String,
259    },
260    /// Sets a symbol type descriptor.
261    SetSymbolType {
262        id: SymbolId,
263        from: Option<TypeDesc>,
264        to: Option<TypeDesc>,
265    },
266    /// Sets a symbol default value.
267    SetSymbolDefaultValue {
268        id: SymbolId,
269        from: Option<serde_json::Value>,
270        to: Option<serde_json::Value>,
271    },
272    /// Updates a symbol metadata payload (domain-owned).
273    SetSymbolMeta {
274        id: SymbolId,
275        from: serde_json::Value,
276        to: serde_json::Value,
277    },
278
279    /// Adds a group.
280    AddGroup { id: GroupId, group: Group },
281    /// Removes a group.
282    ///
283    /// This operation is expected to detach nodes that were parented to the group.
284    RemoveGroup {
285        id: GroupId,
286        group: Group,
287        #[serde(default, skip_serializing_if = "Vec::is_empty")]
288        detached: Vec<(NodeId, Option<GroupId>)>,
289        #[serde(default, skip_serializing_if = "Vec::is_empty")]
290        bindings: Vec<(BindingId, Binding)>,
291    },
292    /// Sets a group's bounds.
293    SetGroupRect {
294        id: GroupId,
295        from: CanvasRect,
296        to: CanvasRect,
297    },
298    /// Sets a group's title.
299    SetGroupTitle {
300        id: GroupId,
301        from: String,
302        to: String,
303    },
304    /// Sets a group color override.
305    SetGroupColor {
306        id: GroupId,
307        from: Option<String>,
308        to: Option<String>,
309    },
310
311    /// Adds a sticky note.
312    AddStickyNote { id: StickyNoteId, note: StickyNote },
313    /// Removes a sticky note.
314    RemoveStickyNote {
315        id: StickyNoteId,
316        note: StickyNote,
317        #[serde(default, skip_serializing_if = "Vec::is_empty")]
318        bindings: Vec<(BindingId, Binding)>,
319    },
320    /// Sets a sticky note text body.
321    SetStickyNoteText {
322        id: StickyNoteId,
323        from: String,
324        to: String,
325    },
326    /// Sets a sticky note bounds.
327    SetStickyNoteRect {
328        id: StickyNoteId,
329        from: CanvasRect,
330        to: CanvasRect,
331    },
332    /// Sets a sticky note color override.
333    SetStickyNoteColor {
334        id: StickyNoteId,
335        from: Option<String>,
336        to: Option<String>,
337    },
338
339    /// Adds a knowledge-canvas binding.
340    AddBinding { id: BindingId, binding: Binding },
341    /// Removes a knowledge-canvas binding.
342    RemoveBinding { id: BindingId, binding: Binding },
343    /// Sets a binding subject endpoint.
344    SetBindingSubject {
345        id: BindingId,
346        from: BindingEndpoint,
347        to: BindingEndpoint,
348    },
349    /// Sets a binding target endpoint.
350    SetBindingTarget {
351        id: BindingId,
352        from: BindingEndpoint,
353        to: BindingEndpoint,
354    },
355    /// Sets a binding relationship label.
356    SetBindingKind {
357        id: BindingId,
358        from: Option<String>,
359        to: Option<String>,
360    },
361    /// Updates a binding metadata payload (domain-owned).
362    SetBindingMeta {
363        id: BindingId,
364        from: serde_json::Value,
365        to: serde_json::Value,
366    },
367}