Flow Studio
Tracked Actions
Six canvas graph mutations are tracked by the history middleware and are undoable with Ctrl+Z. Each tracked action wraps its state update inside historyAction() — which takes a pre-mutation snapshot before the store is modified.
Tracked Action List
| Action | Snapshot Captures | Undo Restores |
|---|---|---|
addNode | nodes before add | Node is removed |
removeNode | nodes + edges before remove | Node + connected edges restored |
moveNode | node position before move | Node returns to previous position |
renameNode (via updateNode) | node label before rename | Label reverts |
addEdge | edges before add | Edge is removed |
removeEdge | edges before remove | Edge is restored |
Composite Operations
Some user actions result in multiple store mutations — these are grouped into a single history entry:
// removeNode: removes the node AND all its connected edges atomically
// This is a single history entry — one Ctrl+Z restores both the node and its edges
removeNode: (id) => {
get().historyAction(() => {
set(state => ({
nodes: state.nodes.filter(n => n.id !== id),
edges: state.edges.filter(e => e.source !== id && e.target !== id)
}));
// nodes AND edges updated in one set() call → one history entry
});
}
What a Snapshot Contains
// History snapshots capture only nodes and edges — not viewport or selection
type HistorySnapshot = {
nodes: WorkflowNode[]; // Deep copy (JSON.parse(JSON.stringify(...)))
edges: WorkflowEdge[]; // Deep copy
};
// Viewport and selectedNodes are NOT captured:
// - Viewport changes are not undoable
// - Selection is a transient UI state — restoring it after undo would be confusing
updateNode is not globally tracked. Only the rename operation (updating node label) pushes to history. Config field changes (actorId, timeoutDuration, etc.) are auto-saved directly and do not enter the undo stack — they go through the persistence middleware, not historyAction.