From f5685b42a4185cc85696587e414f183e9aa1590d Mon Sep 17 00:00:00 2001 From: Oleg Ivaniv Date: Mon, 12 Feb 2024 14:50:27 +0100 Subject: [PATCH 1/2] fix: Fix resolving of expressions of deeply nested sub-nodes --- .../src/components/VariableSelector.vue | 5 +-- .../src/composables/useWorkflowHelpers.ts | 38 +------------------ packages/workflow/src/Workflow.ts | 35 ++++++++++++++++- packages/workflow/src/WorkflowDataProxy.ts | 8 +++- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/packages/editor-ui/src/components/VariableSelector.vue b/packages/editor-ui/src/components/VariableSelector.vue index 9862a42b86c0a..30b2f49d9239d 100644 --- a/packages/editor-ui/src/components/VariableSelector.vue +++ b/packages/editor-ui/src/components/VariableSelector.vue @@ -81,10 +81,7 @@ export default defineComponent({ if (!activeNode) { return null; } - return this.workflowHelpers.getParentMainInputNode( - this.workflowHelpers.getCurrentWorkflow(), - activeNode, - ); + return this.workflow.getParentMainInputNode(activeNode); }, extendAll(): boolean { if (this.variableFilter) { diff --git a/packages/editor-ui/src/composables/useWorkflowHelpers.ts b/packages/editor-ui/src/composables/useWorkflowHelpers.ts index 98d6cc3475482..a60f1261b1690 100644 --- a/packages/editor-ui/src/composables/useWorkflowHelpers.ts +++ b/packages/editor-ui/src/composables/useWorkflowHelpers.ts @@ -73,41 +73,6 @@ import { useI18n } from '@/composables/useI18n'; import type { Router } from 'vue-router'; import { useTelemetry } from '@/composables/useTelemetry'; -export function getParentMainInputNode(workflow: Workflow, node: INode): INode { - const nodeType = useNodeTypesStore().getNodeType(node.type); - if (nodeType) { - const outputs = NodeHelpers.getNodeOutputs(workflow, node, nodeType); - - if (!!outputs.find((output) => output !== NodeConnectionType.Main)) { - // Get the first node which is connected to a non-main output - const nonMainNodesConnected = outputs?.reduce((acc, outputName) => { - const parentNodes = workflow.getChildNodes(node.name, outputName); - if (parentNodes.length > 0) { - acc.push(...parentNodes); - } - return acc; - }, [] as string[]); - - if (nonMainNodesConnected.length) { - const returnNode = workflow.getNode(nonMainNodesConnected[0]); - if (returnNode === null) { - // This should theoretically never happen as the node is connected - // but who knows and it makes TS happy - throw new Error( - `The node "${nonMainNodesConnected[0]}" which is a connection of "${node.name}" could not be found!`, - ); - } - - // The chain of non-main nodes is potentially not finished yet so - // keep on going - return getParentMainInputNode(workflow, returnNode); - } - } - } - - return node; -} - export function resolveParameter( parameter: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], opts: { @@ -127,7 +92,7 @@ export function resolveParameter( const workflow = getCurrentWorkflow(); if (activeNode) { - contextNode = getParentMainInputNode(workflow, activeNode); + contextNode = workflow.getParentMainInputNode(activeNode); } const workflowRunData = useWorkflowsStore().getWorkflowRunData; @@ -1187,7 +1152,6 @@ export function useWorkflowHelpers(router: Router) { getCurrentWorkflow, getConnectedNodes, getNodes, - getParentMainInputNode, getWorkflow, getNodeTypes, connectionInputData, diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index 0411db82b782e..1e08f39e78259 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -44,7 +44,7 @@ import type { ConnectionTypes, CloseFunction, } from './Interfaces'; -import { Node } from './Interfaces'; +import { Node, NodeConnectionType } from './Interfaces'; import type { IDeferredPromise } from './DeferredPromise'; import * as NodeHelpers from './NodeHelpers'; @@ -845,6 +845,39 @@ export class Workflow { return returnConns; } + getParentMainInputNode(node: INode): INode { + if (node) { + const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion); + const outputs = NodeHelpers.getNodeOutputs(this, node, nodeType.description); + + if (!!outputs.find((output) => (output?.type ?? output) !== NodeConnectionType.Main)) { + // Get the first node which is connected to a non-main output + const nonMainNodesConnected = outputs?.reduce((acc, outputName) => { + const parentNodes = this.getChildNodes(node.name, outputName?.type ?? outputName); + if (parentNodes.length > 0) { + acc.push(...parentNodes); + } + return acc; + }, [] as string[]); + + if (nonMainNodesConnected.length) { + const returnNode = this.getNode(nonMainNodesConnected[0]); + if (returnNode === null) { + // This should theoretically never happen as the node is connected + // but who knows and it makes TS happy + throw new ApplicationError(`Node "${nonMainNodesConnected[0]}" not found`); + } + + // The chain of non-main nodes is potentially not finished yet so + // keep on going + return this.getParentMainInputNode(returnNode); + } + } + } + + return node; + } + /** * Returns via which output of the parent-node and index the current node * they are connected diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 4e8de2a5a6b0d..a6b19310e9fd7 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -993,7 +993,13 @@ export class WorkflowDataProxy { // Before resolving the pairedItem make sure that the requested node comes in the // graph before the current one - const parentNodes = that.workflow.getParentNodes(that.contextNodeName); + const activeNode = that.workflow.getNode(that.activeNodeName); + let contextNode = that.contextNodeName; + if (activeNode) { + const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode); + contextNode = parentMainInputNode.name ?? contextNode; + } + const parentNodes = that.workflow.getParentNodes(contextNode); if (!parentNodes.includes(nodeName)) { throw createExpressionError('Invalid expression', { messageTemplate: 'Invalid expression under ‘%%PARAMETER%%’', From 6b8dbc2e841e2b3d16a65c1c11c164807338f437 Mon Sep 17 00:00:00 2001 From: Oleg Ivaniv Date: Mon, 12 Feb 2024 14:55:50 +0100 Subject: [PATCH 2/2] TS linter fixes --- packages/workflow/src/Workflow.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index 1e08f39e78259..5a05195c8d704 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -43,6 +43,7 @@ import type { NodeParameterValueType, ConnectionTypes, CloseFunction, + INodeOutputConfiguration, } from './Interfaces'; import { Node, NodeConnectionType } from './Interfaces'; import type { IDeferredPromise } from './DeferredPromise'; @@ -850,10 +851,18 @@ export class Workflow { const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion); const outputs = NodeHelpers.getNodeOutputs(this, node, nodeType.description); - if (!!outputs.find((output) => (output?.type ?? output) !== NodeConnectionType.Main)) { + if ( + !!outputs.find( + (output) => + ((output as INodeOutputConfiguration)?.type ?? output) !== NodeConnectionType.Main, + ) + ) { // Get the first node which is connected to a non-main output const nonMainNodesConnected = outputs?.reduce((acc, outputName) => { - const parentNodes = this.getChildNodes(node.name, outputName?.type ?? outputName); + const parentNodes = this.getChildNodes( + node.name, + (outputName as INodeOutputConfiguration)?.type ?? outputName, + ); if (parentNodes.length > 0) { acc.push(...parentNodes); }