File size: 1,876 Bytes
05c5ed5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { Edge } from "@xyflow/react";
import { UINode } from "./workflow.interface";
import equal from "lib/equal";
import { exclude } from "lib/utils";

function normalizeNode(node: UINode) {
  return {
    id: node.id,
    data: exclude(node.data, ["id", "runtime", "description", "name"]),
    name: node.data.name || "",
    description: node.data.description || "",
    position: { ...node.position },
  };
}
function normalizeEdge(edge: Edge) {
  return {
    id: edge.id,
    source: edge.source,
    target: edge.target,
    targetHandle: edge.targetHandle ?? "",
    sourceHandle: edge.sourceHandle ?? "",
  };
}

export function extractWorkflowDiff(
  oldData: { nodes: UINode[]; edges: Edge[] },
  newData: { nodes: UINode[]; edges: Edge[] },
) {
  const deleteNodes: UINode[] = [];
  const deleteEdges: Edge[] = [];
  const updateNodes: UINode[] = [];
  const updateEdges: Edge[] = [];

  const oldNodes = oldData.nodes;
  const newNodes = new Map<string, UINode>(
    newData.nodes.map((node) => [node.id, node]),
  );

  oldNodes.forEach((node) => {
    const newNode = newNodes.get(node.id);
    if (!newNode) {
      deleteNodes.push(node);
    } else if (!equal(normalizeNode(node), normalizeNode(newNode))) {
      updateNodes.push(newNode);
    }
    newNodes.delete(node.id);
  });

  updateNodes.push(...newNodes.values());

  const oldEdges = oldData.edges;
  const newEdges = new Map<string, Edge>(
    newData.edges.map((edge) => [edge.id, edge]),
  );

  oldEdges.forEach((edge) => {
    const newEdge = newEdges.get(edge.id);
    if (!newEdge) {
      deleteEdges.push(edge);
    } else if (!equal(normalizeEdge(edge), normalizeEdge(newEdge))) {
      updateEdges.push(newEdge);
    }
    newEdges.delete(edge.id);
  });

  updateEdges.push(...newEdges.values());
  return {
    deleteNodes,
    deleteEdges,
    updateNodes,
    updateEdges,
  };
}