/** * Automation2 Flow Editor - Graph conversion utilities * Converts between API graph format and canvas internal format. */ import type { NodeType, Automation2Graph, Automation2GraphNode, Automation2Connection, GraphDefinedSchemaRef, } from '../../../../api/workflowApi'; import type { CanvasNode, CanvasConnection } from '../../editor/FlowCanvas'; export function fromApiGraph( graph: Automation2Graph, nodeTypes: NodeType[] ): { nodes: CanvasNode[]; connections: CanvasConnection[] } { const nodeMap = new Map(); nodeTypes.forEach((nt) => { nodeMap.set(nt.id, { inputs: nt.inputs ?? 1, outputs: nt.outputs ?? 1 }); }); const nodes: CanvasNode[] = (graph.nodes || []).map((n: Automation2GraphNode) => { const io = nodeMap.get(n.type) ?? { inputs: 1, outputs: 1 }; let outputs = io.outputs; if (n.type === 'flow.switch') { const cases = (n.parameters?.cases as unknown[]) ?? []; outputs = Math.max(1, cases.length); } const nt = nodeTypes.find((t) => t.id === n.type); return { id: n.id, type: n.type, x: (n as { x?: number }).x ?? 0, y: (n as { y?: number }).y ?? 0, title: (n as { title?: string }).title ?? (typeof n.type === 'string' ? n.type : ''), comment: (n as { comment?: string }).comment, inputs: io.inputs, outputs, parameters: n.parameters ?? {}, inputPorts: nt?.inputPorts ? Object.entries(nt.inputPorts).map(([, v]) => ({ name: '', schema: '', accepts: (v as { accepts?: string[] }).accepts })) : undefined, outputPorts: nt?.outputPorts ? Object.entries(nt.outputPorts).map(([, v]) => ({ name: '', schema: (v as { schema?: string | GraphDefinedSchemaRef }).schema ?? '', })) : undefined, }; }); const connId = (s: string, t: string, so: number, ti: number) => `c_${s}_${so}_${t}_${ti}`; const connections: CanvasConnection[] = (graph.connections || []).map((c: Automation2Connection) => { const srcNode = nodes.find((n) => n.id === c.source); const sourceOutput = c.sourceOutput ?? 0; const sourceHandle = srcNode ? srcNode.inputs + sourceOutput : 0; return { id: connId(c.source, c.target, sourceOutput, c.targetInput ?? 0), sourceId: c.source, sourceHandle, targetId: c.target, targetHandle: c.targetInput ?? 0, }; }); return { nodes, connections }; } export function toApiGraph( nodes: CanvasNode[], connections: CanvasConnection[] ): Automation2Graph { const nodeMap = new Map(nodes.map((n) => [n.id, n])); return { nodes: nodes.map((n) => ({ id: n.id, type: n.type, x: n.x, y: n.y, title: n.title, comment: n.comment, parameters: n.parameters ?? {}, inputPorts: n.inputPorts, outputPorts: n.outputPorts, })), connections: connections.map((c) => { const srcNode = nodeMap.get(c.sourceId); const sourceOutput = srcNode && c.sourceHandle >= srcNode.inputs ? c.sourceHandle - srcNode.inputs : 0; return { source: c.sourceId, target: c.targetId, sourceOutput, targetInput: c.targetHandle, }; }), }; }