From bc6ec87a1a52d57bb2f1c59a3f216f01823efee9 Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Thu, 15 Jan 2026 17:33:10 +0000 Subject: [PATCH 1/3] A fix, maybe --- .../FlowBlueprintEditorView.tsx | 88 ++++++++++++------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/src/components/flow-blueprints/FlowBlueprintEditorView.tsx b/src/components/flow-blueprints/FlowBlueprintEditorView.tsx index 689db409..8e564c64 100644 --- a/src/components/flow-blueprints/FlowBlueprintEditorView.tsx +++ b/src/components/flow-blueprints/FlowBlueprintEditorView.tsx @@ -301,7 +301,7 @@ const nodeTypes = { interface: InterfaceNode, }; -interface FlowBlueprints { +interface FlowBlueprint { blueprint?: Record; flow?: Record; } @@ -311,7 +311,7 @@ const generateNodesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Node[] = const nodes: Node[] = []; // Add blueprint processors - Object.keys(flowBlueprints.blueprint || {}).forEach((processorName) => { + Object.keys(flowBlueprint.blueprint || {}).forEach((processorName) => { // Strip template suffix to get base processor name for service map lookup const baseProcessorName = processorName.replace(/:\{[^}]+\}$/, ""); @@ -343,7 +343,7 @@ const generateNodesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Node[] = }); // Add flow processors - Object.keys(flowBlueprints.flow || {}).forEach((processorName) => { + Object.keys(flowBlueprint.flow || {}).forEach((processorName) => { // Strip template suffix to get base processor name for service map lookup const baseProcessorName = processorName.replace(/:\{[^}]+\}$/, ""); @@ -375,7 +375,7 @@ const generateNodesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Node[] = }); // Add interface nodes - Object.entries(flowBlueprints.interfaces || {}).forEach( + Object.entries(flowBlueprint.interfaces || {}).forEach( ([interfaceName, interfaceQueues]) => { // Look up interface definition in service map const interfaceDefinition = serviceMap.interfaces?.[interfaceName]; @@ -469,24 +469,24 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = }> >(); - // Collect all processors and their connections from service map + flow blueprint queues + // Collect all processors and their connections from service map + flow class queues const allProcessors = [ - ...Object.keys(flowBlueprints.blueprint || {}).map((name) => ({ + ...Object.keys(flowBlueprint.blueprint || {}).map((name) => ({ name, type: "blueprint", baseProcessorName: name.replace(/:\{[^}]+\}$/, ""), - flowBlueprintsConnections: flowBlueprint.blueprint[name], + flowBlueprintConnections: flowBlueprint.blueprint[name], })), - ...Object.keys(flowBlueprints.flow || {}).map((name) => ({ + ...Object.keys(flowBlueprint.flow || {}).map((name) => ({ name, type: "flow", baseProcessorName: name.replace(/:\{[^}]+\}$/, ""), - flowBlueprintsConnections: flowBlueprint.flow[name], + flowBlueprintConnections: flowBlueprint.flow[name], })), ]; allProcessors.forEach( - ({ name, type, baseProcessorName, flowBlueprintsConnections }) => { + ({ name, type, baseProcessorName, flowBlueprintConnections }) => { const processorInfo = serviceMap.processors[baseProcessorName]; if (!processorInfo?.connections) return; @@ -505,21 +505,21 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = // For providers: look for request and response if (connection.role === "provides") { queues = { - request: flowBlueprintsConnections.request, - response: flowBlueprintsConnections.response, + request: flowBlueprintConnections.request, + response: flowBlueprintConnections.response, }; } else if (connection.role === "consumes") { queues = { - request: flowBlueprintsConnections[`${connection.name}-request`], - response: flowBlueprintsConnections[`${connection.name}-response`], + request: flowBlueprintConnections[`${connection.name}-request`], + response: flowBlueprintConnections[`${connection.name}-response`], }; } } else if (connectionKind === "flow") { // For flow: single queue value at connection.name - queues = { value: flowBlueprintsConnections[connection.name] }; + queues = { value: flowBlueprintConnections[connection.name] }; } else if (connectionKind === "passive") { // For passive: both consumer and provider use single queue value - queues = { value: flowBlueprintsConnections[connection.name] }; + queues = { value: flowBlueprintConnections[connection.name] }; } // Only add if we found valid queues @@ -609,7 +609,7 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = // Connect interfaces to their implementing processors - Object.entries(flowBlueprints.interfaces || {}).forEach( + Object.entries(flowBlueprint.interfaces || {}).forEach( ([interfaceName, interfaceQueues]) => { const interfaceDefinition = serviceMap.interfaces?.[interfaceName]; const interfaceKind = interfaceDefinition?.kind; @@ -620,7 +620,7 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = // Find processors that match this interface's queue pattern allProcessors.forEach( - ({ name, type, baseProcessorName, flowBlueprintsConnections }) => { + ({ name, type, baseProcessorName, flowBlueprintConnections }) => { const processorId = `${type}-${name}`; const processorInfo = serviceMap.processors[baseProcessorName]; if (!processorInfo?.connections) return; @@ -639,8 +639,8 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = // Check if this processor provides this service if ( - flowBlueprintsConnections.request === interfaceRequest && - flowBlueprintsConnections.response === interfaceResponse + flowBlueprintConnections.request === interfaceRequest && + flowBlueprintConnections.response === interfaceResponse ) { // Find the service connection that provides matchingConnection = processorInfo.connections.find( @@ -657,7 +657,7 @@ const generateEdgesFromFlowBlueprints = (flowBlueprint: FlowBlueprint): Edge[] = // Check only provider connections for matching queue processorInfo.connections.forEach((connection) => { if (connection.role === "provides") { - const connectionQueue = flowBlueprintsConnections[connection.name]; + const connectionQueue = flowBlueprintConnections[connection.name]; if (connectionQueue === interfaceQueue) { matchingConnection = connection; isMatch = true; @@ -703,20 +703,48 @@ export const FlowBlueprintEditorView: React.FC = ( onBack, }) => { const { flowBlueprints } = useFlowBlueprints(); - const flowBlueprint = flowBlueprints.find((fc) => fc.id === flowBlueprintId); + + // Transform flow Blueprint data if it's in [key, value] format (same as FlowBlueprintTable) + const transformedFlowBlueprints = useMemo(() => { + if (!flowBlueprints || !Array.isArray(flowBlueprints)) return []; + + // Check if first item is an array [key, value] pair + if ( + flowBlueprints.length > 0 && + Array.isArray(flowBlueprints[0]) && + flowBlueprints[0].length === 2 + ) { + return flowBlueprints.map(([id, flowBlueprintData]) => ({ + id, + ...(flowBlueprintData as Record), + })); + } + + // Already transformed + return flowBlueprints; + }, [flowBlueprints]); + + const flowBlueprint = transformedFlowBlueprints.find((fc) => fc.id === flowBlueprintId); + + // Keep the last valid flowBlueprint to prevent unmounting during refetch + const lastValidFlowBlueprint = React.useRef(flowBlueprint); + if (flowBlueprint) { + lastValidFlowBlueprint.current = flowBlueprint; + } + const stableFlowBlueprint = flowBlueprint || lastValidFlowBlueprint.current; // Generate nodes and edges from flow blueprint data using useMemo - must be before early return const initialNodes = useMemo(() => { - if (!flowBlueprint) return []; - const nodes = generateNodesFromFlowBlueprints(flowBlueprint); + if (!stableFlowBlueprint) return []; + const nodes = generateNodesFromFlowBlueprints(stableFlowBlueprint); return nodes; - }, [flowBlueprint]); + }, [stableFlowBlueprint]); const generatedEdges = useMemo(() => { - if (!flowBlueprint) return []; - const edges = generateEdgesFromFlowBlueprints(flowBlueprint); + if (!stableFlowBlueprint) return []; + const edges = generateEdgesFromFlowBlueprints(stableFlowBlueprint); return edges; - }, [flowBlueprint]); + }, [stableFlowBlueprint]); const layoutedNodes = useMemo(() => { const layouted = applyDagreLayout(initialNodes, generatedEdges); @@ -740,7 +768,7 @@ export const FlowBlueprintEditorView: React.FC = ( [setEdges], ); - if (!flowBlueprints) { + if (!stableFlowBlueprint) { return ( @@ -790,7 +818,7 @@ export const FlowBlueprintEditorView: React.FC = ( - {flowBlueprints.name} + {stableFlowBlueprint?.name} From 8327ed2831803a138b399da0f3f9d14dc5a098a3 Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Thu, 15 Jan 2026 19:21:48 +0000 Subject: [PATCH 2/3] Revert some "fixes" which aren't needed --- .../FlowBlueprintEditorView.tsx | 46 ++++--------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/src/components/flow-blueprints/FlowBlueprintEditorView.tsx b/src/components/flow-blueprints/FlowBlueprintEditorView.tsx index 8e564c64..0afed6ce 100644 --- a/src/components/flow-blueprints/FlowBlueprintEditorView.tsx +++ b/src/components/flow-blueprints/FlowBlueprintEditorView.tsx @@ -703,48 +703,20 @@ export const FlowBlueprintEditorView: React.FC = ( onBack, }) => { const { flowBlueprints } = useFlowBlueprints(); - - // Transform flow Blueprint data if it's in [key, value] format (same as FlowBlueprintTable) - const transformedFlowBlueprints = useMemo(() => { - if (!flowBlueprints || !Array.isArray(flowBlueprints)) return []; - - // Check if first item is an array [key, value] pair - if ( - flowBlueprints.length > 0 && - Array.isArray(flowBlueprints[0]) && - flowBlueprints[0].length === 2 - ) { - return flowBlueprints.map(([id, flowBlueprintData]) => ({ - id, - ...(flowBlueprintData as Record), - })); - } - - // Already transformed - return flowBlueprints; - }, [flowBlueprints]); - - const flowBlueprint = transformedFlowBlueprints.find((fc) => fc.id === flowBlueprintId); - - // Keep the last valid flowBlueprint to prevent unmounting during refetch - const lastValidFlowBlueprint = React.useRef(flowBlueprint); - if (flowBlueprint) { - lastValidFlowBlueprint.current = flowBlueprint; - } - const stableFlowBlueprint = flowBlueprint || lastValidFlowBlueprint.current; + const flowBlueprint = flowBlueprints.find((fc) => fc.id === flowBlueprintId); // Generate nodes and edges from flow blueprint data using useMemo - must be before early return const initialNodes = useMemo(() => { - if (!stableFlowBlueprint) return []; - const nodes = generateNodesFromFlowBlueprints(stableFlowBlueprint); + if (!flowBlueprint) return []; + const nodes = generateNodesFromFlowBlueprints(flowBlueprint); return nodes; - }, [stableFlowBlueprint]); + }, [flowBlueprint]); const generatedEdges = useMemo(() => { - if (!stableFlowBlueprint) return []; - const edges = generateEdgesFromFlowBlueprints(stableFlowBlueprint); + if (!flowBlueprint) return []; + const edges = generateEdgesFromFlowBlueprints(flowBlueprint); return edges; - }, [stableFlowBlueprint]); + }, [flowBlueprint]); const layoutedNodes = useMemo(() => { const layouted = applyDagreLayout(initialNodes, generatedEdges); @@ -768,7 +740,7 @@ export const FlowBlueprintEditorView: React.FC = ( [setEdges], ); - if (!stableFlowBlueprint) { + if (!flowBlueprint) { return ( @@ -818,7 +790,7 @@ export const FlowBlueprintEditorView: React.FC = ( - {stableFlowBlueprint?.name} + {flowBlueprint?.name} From 17257c9372ba7012722a07bbd228cb5e259f63ac Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Thu, 15 Jan 2026 19:22:17 +0000 Subject: [PATCH 3/3] Pull in newer trustgraph/react-state --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 036c4d21..9dfb05f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@tanstack/react-table": "^8.21.3", "@trustgraph/client": "^1.2.1", "@trustgraph/react-provider": "^1.2.0", - "@trustgraph/react-state": "^1.2.0", + "@trustgraph/react-state": "^1.2.1", "@types/dagre": "^0.7.53", "compute-cosine-similarity": "^1.1.0", "dagre": "^0.8.5", @@ -2589,9 +2589,9 @@ } }, "node_modules/@trustgraph/react-state": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@trustgraph/react-state/-/react-state-1.2.0.tgz", - "integrity": "sha512-KQv9S+bCE1SIhdEW7fksgJbcquPGsAFXl7ZekklSMNM1ivjzNKnMm5fThp0wnMFH13SexVLfbpAJ+vjFS0+Vnw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@trustgraph/react-state/-/react-state-1.2.1.tgz", + "integrity": "sha512-O2+v6hTI34LJftqQm9waPFeRQ2yfX0iUOtuxm3YAD++Vtxa+1FDayauuUK9v31oa1zUS9ibFYJPQZK1h3ylvWA==", "license": "MIT", "dependencies": { "@trustgraph/client": "^1.2.0", diff --git a/package.json b/package.json index 39dcbfba..3c1efdf2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@tanstack/react-table": "^8.21.3", "@trustgraph/client": "^1.2.1", "@trustgraph/react-provider": "^1.2.0", - "@trustgraph/react-state": "^1.2.0", + "@trustgraph/react-state": "^1.2.1", "@types/dagre": "^0.7.53", "compute-cosine-similarity": "^1.1.0", "dagre": "^0.8.5",