Skip to content

Commit 80d1377

Browse files
committed
Implement Node Manager
1 parent 85f2b7a commit 80d1377

File tree

6 files changed

+77
-15
lines changed

6 files changed

+77
-15
lines changed

src/components/shared/ReactFlow/FlowCanvas/FlowCanvas.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,34 @@ const FlowCanvas = ({
144144

145145
const latestFlowPosRef = useRef<{ x: number; y: number } | null>(null);
146146

147+
/* Migrate Node Ids */
148+
const [migrationCompleted, setMigrationCompleted] = useState(false);
149+
150+
useEffect(() => {
151+
if (!initialCanvasLoaded.current || migrationCompleted) return;
152+
153+
const needsMigration = nodes.some(
154+
(node) =>
155+
!nodeManager.isManaged(node.id) &&
156+
(node.id.startsWith("task_") ||
157+
node.id.startsWith("input_") ||
158+
node.id.startsWith("output_")),
159+
);
160+
161+
if (needsMigration) {
162+
console.log("Migrating legacy node IDs to stable IDs...");
163+
const { updatedNodes, migrationMap } =
164+
nodeManager.migrateExistingNodes(nodes);
165+
166+
setNodes(updatedNodes);
167+
setMigrationCompleted(true);
168+
169+
console.log("Migration completed:", migrationMap);
170+
} else {
171+
setMigrationCompleted(true);
172+
}
173+
}, [nodes, nodeManager, migrationCompleted]);
174+
147175
const [showToolbar, setShowToolbar] = useState(false);
148176
const [replaceTarget, setReplaceTarget] = useState<Node | null>(null);
149177
const [shiftKeyPressed, setShiftKeyPressed] = useState(false);

src/components/shared/ReactFlow/FlowCanvas/utils/duplicateNodes.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export const duplicateNodes = (
6464
const graphSpec = componentSpec.implementation.graph;
6565

6666
const nodeIdMap: Record<string, string> = {};
67-
6867
const newTasks: Record<string, TaskSpec> = {};
6968
const newInputs: Record<string, InputSpec> = {};
7069
const newOutputs: Record<string, OutputSpec> = {};

src/utils/nodes/createInputNode.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@ import { type Node } from "@xyflow/react";
33
import type { IONodeData, NodeData } from "@/types/nodes";
44

55
import type { InputSpec } from "../componentSpec";
6-
import { inputIdToNodeId, inputNameToInputId } from "./conversions";
76
import { extractPositionFromAnnotations } from "./extractPositionFromAnnotations";
87

98
export const createInputNode = (input: InputSpec, nodeData: NodeData) => {
109
const { name, annotations } = input;
1110
const { nodeManager, readOnly } = nodeData;
1211

13-
const newNodeId = nodeManager?.getNodeId(name, "input");
14-
console.log("Creating input node:", { name, nodeId: newNodeId });
12+
const nodeId = nodeManager?.getNodeId(name, "input");
13+
console.log("Creating input node:", { name, nodeId });
1514

1615
const position = extractPositionFromAnnotations(annotations);
17-
const inputId = inputNameToInputId(name);
18-
const nodeId = inputIdToNodeId(inputId);
1916

2017
const inputNodeData: IONodeData = {
2118
spec: input,

src/utils/nodes/createOutputNode.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@ import { type Node } from "@xyflow/react";
33
import type { IONodeData, NodeData } from "@/types/nodes";
44

55
import type { OutputSpec } from "../componentSpec";
6-
import { outputIdToNodeId, outputNameToOutputId } from "./conversions";
76
import { extractPositionFromAnnotations } from "./extractPositionFromAnnotations";
87

98
export const createOutputNode = (output: OutputSpec, nodeData: NodeData) => {
109
const { name, annotations } = output;
1110
const { nodeManager, readOnly } = nodeData;
1211

13-
const newNodeId = nodeManager?.getNodeId(name, "output");
14-
console.log("Creating output node:", { name, nodeId: newNodeId });
12+
const nodeId = nodeManager?.getNodeId(name, "output");
13+
console.log("Creating output node:", { name, nodeId });
1514

1615
const position = extractPositionFromAnnotations(annotations);
17-
const outputId = outputNameToOutputId(name);
18-
const nodeId = outputIdToNodeId(outputId);
1916

2017
const outputNodeData: IONodeData = {
2118
spec: output,

src/utils/nodes/createTaskNode.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { type Node } from "@xyflow/react";
33
import type { NodeData, TaskNodeData } from "@/types/nodes";
44

55
import type { TaskSpec } from "../componentSpec";
6-
import { taskIdToNodeId } from "./conversions";
76
import { extractPositionFromAnnotations } from "./extractPositionFromAnnotations";
87
import { convertNodeCallbacksToTaskCallbacks } from "./taskCallbackUtils";
98

@@ -14,11 +13,10 @@ export const createTaskNode = (
1413
const [taskId, taskSpec] = task;
1514
const { nodeManager, callbacks, connectable, ...data } = nodeData;
1615

17-
const newNodeId = nodeManager?.getNodeId(taskId, "task");
18-
console.log("Creating task node:", { taskId, nodeId: newNodeId });
16+
const nodeId = nodeManager.getNodeId(taskId, "task");
17+
console.log("Creating task node:", { taskId, nodeId });
1918

2019
const position = extractPositionFromAnnotations(taskSpec.annotations);
21-
const nodeId = taskIdToNodeId(taskId);
2220

2321
const ids = { taskId, nodeId };
2422
const taskCallbacks = convertNodeCallbacksToTaskCallbacks(ids, callbacks);

src/utils/nodes/nodeIdUtils.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { NodeManager, NodeType } from "@/nodeManager";
2+
3+
// DEPRECATED: Legacy functions - use NodeManager instead
4+
export const taskIdToNodeId = (taskId: string): string => `task_${taskId}`; // Legacy
5+
export const inputNameToNodeId = (inputName: string): string =>
6+
`input_${inputName}`; // Legacy
7+
export const outputNameToNodeId = (outputName: string): string =>
8+
`output_${outputName}`; // Legacy
9+
10+
// RENAMED: For backwards compatibility and clarity
11+
export const inputNameToInputId = (inputName: string): string => inputName; // 1:1 mapping
12+
export const outputNameToOutputId = (outputName: string): string => outputName; // 1:1 mapping
13+
export const inputIdToInputName = (inputId: string): string => inputId; // 1:1 mapping
14+
export const outputIdToOutputName = (outputId: string): string => outputId; // 1:1 mapping
15+
16+
// LEGACY: Keep for backwards compatibility
17+
export const nodeIdToTaskId = (nodeId: string): string => {
18+
return nodeId.replace(/^task_/, "");
19+
};
20+
21+
export const nodeIdToInputName = (nodeId: string): string => {
22+
return nodeId.replace(/^input_/, "");
23+
};
24+
25+
export const nodeIdToOutputName = (nodeId: string): string => {
26+
return nodeId.replace(/^output_/, "");
27+
};
28+
29+
// NEW: NodeManager-aware functions
30+
export const getTaskIdFromNodeId = (
31+
nodeId: string,
32+
nodeManager: NodeManager,
33+
): string | undefined => {
34+
return nodeManager.getTaskId(nodeId);
35+
};
36+
37+
export const getStableNodeId = (
38+
taskId: string,
39+
nodeType: NodeType,
40+
nodeManager: NodeManager,
41+
): string => {
42+
return nodeManager.getNodeId(taskId, nodeType);
43+
};

0 commit comments

Comments
 (0)