mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
refactor(editor): Remove part of getCurrentWorkflow usages (#16148)
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
"import": "./dist/esm/index.js",
|
||||
"require": "./dist/cjs/index.js"
|
||||
},
|
||||
"./common": {
|
||||
"types": "./dist/esm/common/index.d.ts",
|
||||
"import": "./dist/esm/common/index.js",
|
||||
"require": "./dist/cjs/common/index.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
12
packages/workflow/src/common/get-child-nodes.ts
Normal file
12
packages/workflow/src/common/get-child-nodes.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { getConnectedNodes } from './get-connected-nodes';
|
||||
import { NodeConnectionTypes } from '../interfaces';
|
||||
import type { IConnections, NodeConnectionType } from '../interfaces';
|
||||
|
||||
export function getChildNodes(
|
||||
connectionsBySourceNode: IConnections,
|
||||
nodeName: string,
|
||||
type: NodeConnectionType | 'ALL' | 'ALL_NON_MAIN' = NodeConnectionTypes.Main,
|
||||
depth = -1,
|
||||
): string[] {
|
||||
return getConnectedNodes(connectionsBySourceNode, nodeName, type, depth);
|
||||
}
|
||||
98
packages/workflow/src/common/get-connected-nodes.ts
Normal file
98
packages/workflow/src/common/get-connected-nodes.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { NodeConnectionTypes } from '../interfaces';
|
||||
import type { IConnections, NodeConnectionType } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Gets all the nodes which are connected nodes starting from
|
||||
* the given one
|
||||
*
|
||||
* @param {NodeConnectionType} [type='main']
|
||||
* @param {*} [depth=-1]
|
||||
*/
|
||||
export function getConnectedNodes(
|
||||
connections: IConnections,
|
||||
nodeName: string,
|
||||
connectionType: NodeConnectionType | 'ALL' | 'ALL_NON_MAIN' = NodeConnectionTypes.Main,
|
||||
depth = -1,
|
||||
checkedNodesIncoming?: string[],
|
||||
): string[] {
|
||||
const newDepth = depth === -1 ? depth : depth - 1;
|
||||
if (depth === 0) {
|
||||
// Reached max depth
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!connections.hasOwnProperty(nodeName)) {
|
||||
// Node does not have incoming connections
|
||||
return [];
|
||||
}
|
||||
|
||||
let types: NodeConnectionType[];
|
||||
if (connectionType === 'ALL') {
|
||||
types = Object.keys(connections[nodeName]) as NodeConnectionType[];
|
||||
} else if (connectionType === 'ALL_NON_MAIN') {
|
||||
types = Object.keys(connections[nodeName]).filter(
|
||||
(type) => type !== 'main',
|
||||
) as NodeConnectionType[];
|
||||
} else {
|
||||
types = [connectionType];
|
||||
}
|
||||
|
||||
let addNodes: string[];
|
||||
let nodeIndex: number;
|
||||
let i: number;
|
||||
let parentNodeName: string;
|
||||
const returnNodes: string[] = [];
|
||||
|
||||
types.forEach((type) => {
|
||||
if (!connections[nodeName].hasOwnProperty(type)) {
|
||||
// Node does not have incoming connections of given type
|
||||
return;
|
||||
}
|
||||
|
||||
const checkedNodes = checkedNodesIncoming ? [...checkedNodesIncoming] : [];
|
||||
|
||||
if (checkedNodes.includes(nodeName)) {
|
||||
// Node got checked already before
|
||||
return;
|
||||
}
|
||||
|
||||
checkedNodes.push(nodeName);
|
||||
|
||||
connections[nodeName][type].forEach((connectionsByIndex) => {
|
||||
connectionsByIndex?.forEach((connection) => {
|
||||
if (checkedNodes.includes(connection.node)) {
|
||||
// Node got checked already before
|
||||
return;
|
||||
}
|
||||
|
||||
returnNodes.unshift(connection.node);
|
||||
|
||||
addNodes = getConnectedNodes(
|
||||
connections,
|
||||
connection.node,
|
||||
connectionType,
|
||||
newDepth,
|
||||
checkedNodes,
|
||||
);
|
||||
|
||||
for (i = addNodes.length; i--; i > 0) {
|
||||
// Because nodes can have multiple parents it is possible that
|
||||
// parts of the tree is parent of both and to not add nodes
|
||||
// twice check first if they already got added before.
|
||||
parentNodeName = addNodes[i];
|
||||
nodeIndex = returnNodes.indexOf(parentNodeName);
|
||||
|
||||
if (nodeIndex !== -1) {
|
||||
// Node got found before so remove it from current location
|
||||
// that node-order stays correct
|
||||
returnNodes.splice(nodeIndex, 1);
|
||||
}
|
||||
|
||||
returnNodes.unshift(parentNodeName);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return returnNodes;
|
||||
}
|
||||
19
packages/workflow/src/common/get-node-by-name.ts
Normal file
19
packages/workflow/src/common/get-node-by-name.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { INode, INodes } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Returns the node with the given name if it exists else null
|
||||
*
|
||||
* @param {INodes} nodes Nodes to search in
|
||||
* @param {string} name Name of the node to return
|
||||
*/
|
||||
export function getNodeByName(nodes: INodes | INode[], name: string) {
|
||||
if (Array.isArray(nodes)) {
|
||||
return nodes.find((node) => node.name === name) || null;
|
||||
}
|
||||
|
||||
if (nodes.hasOwnProperty(name)) {
|
||||
return nodes[name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
18
packages/workflow/src/common/get-parent-nodes.ts
Normal file
18
packages/workflow/src/common/get-parent-nodes.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { getConnectedNodes } from './get-connected-nodes';
|
||||
import { NodeConnectionTypes } from '../interfaces';
|
||||
import type { IConnections, NodeConnectionType } from '../interfaces';
|
||||
|
||||
/**
|
||||
* Returns all the nodes before the given one
|
||||
*
|
||||
* @param {NodeConnectionType} [type='main']
|
||||
* @param {*} [depth=-1]
|
||||
*/
|
||||
export function getParentNodes(
|
||||
connectionsByDestinationNode: IConnections,
|
||||
nodeName: string,
|
||||
type: NodeConnectionType | 'ALL' | 'ALL_NON_MAIN' = NodeConnectionTypes.Main,
|
||||
depth = -1,
|
||||
): string[] {
|
||||
return getConnectedNodes(connectionsByDestinationNode, nodeName, type, depth);
|
||||
}
|
||||
5
packages/workflow/src/common/index.ts
Normal file
5
packages/workflow/src/common/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './get-child-nodes';
|
||||
export * from './get-connected-nodes';
|
||||
export * from './get-node-by-name';
|
||||
export * from './get-parent-nodes';
|
||||
export * from './map-connections-by-destination';
|
||||
@@ -0,0 +1,49 @@
|
||||
/* eslint-disable @typescript-eslint/no-for-in-array */
|
||||
|
||||
import type { IConnections, NodeConnectionType } from '../interfaces';
|
||||
|
||||
export function mapConnectionsByDestination(connections: IConnections) {
|
||||
const returnConnection: IConnections = {};
|
||||
|
||||
let connectionInfo;
|
||||
let maxIndex: number;
|
||||
for (const sourceNode in connections) {
|
||||
if (!connections.hasOwnProperty(sourceNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const type of Object.keys(connections[sourceNode]) as NodeConnectionType[]) {
|
||||
if (!connections[sourceNode].hasOwnProperty(type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const inputIndex in connections[sourceNode][type]) {
|
||||
if (!connections[sourceNode][type].hasOwnProperty(inputIndex)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (connectionInfo of connections[sourceNode][type][inputIndex] ?? []) {
|
||||
if (!returnConnection.hasOwnProperty(connectionInfo.node)) {
|
||||
returnConnection[connectionInfo.node] = {};
|
||||
}
|
||||
if (!returnConnection[connectionInfo.node].hasOwnProperty(connectionInfo.type)) {
|
||||
returnConnection[connectionInfo.node][connectionInfo.type] = [];
|
||||
}
|
||||
|
||||
maxIndex = returnConnection[connectionInfo.node][connectionInfo.type].length - 1;
|
||||
for (let j = maxIndex; j < connectionInfo.index; j++) {
|
||||
returnConnection[connectionInfo.node][connectionInfo.type].push([]);
|
||||
}
|
||||
|
||||
returnConnection[connectionInfo.node][connectionInfo.type][connectionInfo.index]?.push({
|
||||
node: sourceNode,
|
||||
type,
|
||||
index: parseInt(inputIndex, 10),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnConnection;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import * as TelemetryHelpers from './telemetry-helpers';
|
||||
|
||||
export * from './errors';
|
||||
export * from './constants';
|
||||
export * from './common';
|
||||
export * from './cron';
|
||||
export * from './deferred-promise';
|
||||
export * from './global-state';
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-for-in-array */
|
||||
import {
|
||||
getNodeByName,
|
||||
getConnectedNodes,
|
||||
getChildNodes,
|
||||
getParentNodes,
|
||||
mapConnectionsByDestination,
|
||||
} from './common';
|
||||
|
||||
import {
|
||||
MANUAL_CHAT_TRIGGER_LANGCHAIN_NODE_TYPE,
|
||||
NODES_WITH_RENAMABLE_CONTENT,
|
||||
@@ -123,9 +131,7 @@ export class Workflow {
|
||||
this.connectionsBySourceNode = parameters.connections;
|
||||
|
||||
// Save also the connections by the destination nodes
|
||||
this.connectionsByDestinationNode = Workflow.getConnectionsByDestination(
|
||||
parameters.connections,
|
||||
);
|
||||
this.connectionsByDestinationNode = mapConnectionsByDestination(parameters.connections);
|
||||
|
||||
this.active = parameters.active || false;
|
||||
|
||||
@@ -146,11 +152,6 @@ export class Workflow {
|
||||
this.staticData.__dataChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default connections are by source node. This function rewrites them by destination nodes
|
||||
* to easily find parent nodes.
|
||||
*
|
||||
*/
|
||||
static getConnectionsByDestination(connections: IConnections): IConnections {
|
||||
const returnConnection: IConnections = {};
|
||||
|
||||
@@ -288,11 +289,7 @@ export class Workflow {
|
||||
* @param {string} nodeName Name of the node to return
|
||||
*/
|
||||
getNode(nodeName: string): INode | null {
|
||||
if (this.nodes.hasOwnProperty(nodeName)) {
|
||||
return this.nodes[nodeName];
|
||||
}
|
||||
|
||||
return null;
|
||||
return getNodeByName(this.nodes, nodeName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,9 +474,7 @@ export class Workflow {
|
||||
}
|
||||
|
||||
// Use the updated connections to create updated connections by destination nodes
|
||||
this.connectionsByDestinationNode = Workflow.getConnectionsByDestination(
|
||||
this.connectionsBySourceNode,
|
||||
);
|
||||
this.connectionsByDestinationNode = mapConnectionsByDestination(this.connectionsBySourceNode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,7 +571,7 @@ export class Workflow {
|
||||
type: NodeConnectionType | 'ALL' | 'ALL_NON_MAIN' = NodeConnectionTypes.Main,
|
||||
depth = -1,
|
||||
): string[] {
|
||||
return this.getConnectedNodes(this.connectionsBySourceNode, nodeName, type, depth);
|
||||
return getChildNodes(this.connectionsBySourceNode, nodeName, type, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +585,7 @@ export class Workflow {
|
||||
type: NodeConnectionType | 'ALL' | 'ALL_NON_MAIN' = NodeConnectionTypes.Main,
|
||||
depth = -1,
|
||||
): string[] {
|
||||
return this.getConnectedNodes(this.connectionsByDestinationNode, nodeName, type, depth);
|
||||
return getParentNodes(this.connectionsByDestinationNode, nodeName, type, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -607,87 +602,7 @@ export class Workflow {
|
||||
depth = -1,
|
||||
checkedNodesIncoming?: string[],
|
||||
): string[] {
|
||||
depth = depth === -1 ? -1 : depth;
|
||||
const newDepth = depth === -1 ? depth : depth - 1;
|
||||
if (depth === 0) {
|
||||
// Reached max depth
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!connections.hasOwnProperty(nodeName)) {
|
||||
// Node does not have incoming connections
|
||||
return [];
|
||||
}
|
||||
|
||||
let types: NodeConnectionType[];
|
||||
if (connectionType === 'ALL') {
|
||||
types = Object.keys(connections[nodeName]) as NodeConnectionType[];
|
||||
} else if (connectionType === 'ALL_NON_MAIN') {
|
||||
types = Object.keys(connections[nodeName]).filter(
|
||||
(type) => type !== 'main',
|
||||
) as NodeConnectionType[];
|
||||
} else {
|
||||
types = [connectionType];
|
||||
}
|
||||
|
||||
let addNodes: string[];
|
||||
let nodeIndex: number;
|
||||
let i: number;
|
||||
let parentNodeName: string;
|
||||
const returnNodes: string[] = [];
|
||||
|
||||
types.forEach((type) => {
|
||||
if (!connections[nodeName].hasOwnProperty(type)) {
|
||||
// Node does not have incoming connections of given type
|
||||
return;
|
||||
}
|
||||
|
||||
const checkedNodes = checkedNodesIncoming ? [...checkedNodesIncoming] : [];
|
||||
|
||||
if (checkedNodes.includes(nodeName)) {
|
||||
// Node got checked already before
|
||||
return;
|
||||
}
|
||||
|
||||
checkedNodes.push(nodeName);
|
||||
|
||||
connections[nodeName][type].forEach((connectionsByIndex) => {
|
||||
connectionsByIndex?.forEach((connection) => {
|
||||
if (checkedNodes.includes(connection.node)) {
|
||||
// Node got checked already before
|
||||
return;
|
||||
}
|
||||
|
||||
returnNodes.unshift(connection.node);
|
||||
|
||||
addNodes = this.getConnectedNodes(
|
||||
connections,
|
||||
connection.node,
|
||||
connectionType,
|
||||
newDepth,
|
||||
checkedNodes,
|
||||
);
|
||||
|
||||
for (i = addNodes.length; i--; i > 0) {
|
||||
// Because nodes can have multiple parents it is possible that
|
||||
// parts of the tree is parent of both and to not add nodes
|
||||
// twice check first if they already got added before.
|
||||
parentNodeName = addNodes[i];
|
||||
nodeIndex = returnNodes.indexOf(parentNodeName);
|
||||
|
||||
if (nodeIndex !== -1) {
|
||||
// Node got found before so remove it from current location
|
||||
// that node-order stays correct
|
||||
returnNodes.splice(nodeIndex, 1);
|
||||
}
|
||||
|
||||
returnNodes.unshift(parentNodeName);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return returnNodes;
|
||||
return getConnectedNodes(connections, nodeName, connectionType, depth, checkedNodesIncoming);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
112
packages/workflow/test/common.test.ts
Normal file
112
packages/workflow/test/common.test.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import type { IConnections, IConnection } from '../src/interfaces';
|
||||
import { NodeConnectionTypes } from '../src/interfaces';
|
||||
import { mapConnectionsByDestination } from '../src/common';
|
||||
|
||||
describe('getConnectionsByDestination', () => {
|
||||
it('should return empty object when there are no connections', () => {
|
||||
const result = mapConnectionsByDestination({});
|
||||
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should return connections by destination node', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[
|
||||
{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 },
|
||||
{ node: 'Node3', type: NodeConnectionTypes.Main, index: 1 },
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
const result = mapConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }]],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[],
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle multiple connection types', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }]],
|
||||
[NodeConnectionTypes.AiAgent]: [
|
||||
[{ node: 'Node3', type: NodeConnectionTypes.AiAgent, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = mapConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }]],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.AiAgent]: [
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.AiAgent, index: 0 }],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle nodes with no connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [[]],
|
||||
},
|
||||
};
|
||||
|
||||
const result = mapConnectionsByDestination(connections);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
// @issue https://linear.app/n8n/issue/N8N-7880/cannot-load-some-templates
|
||||
it('should handle nodes with null connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
null as unknown as IConnection[],
|
||||
[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = mapConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 1 }]],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle nodes with multiple input connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }]],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.Main]: [[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }]],
|
||||
},
|
||||
};
|
||||
|
||||
const result = mapConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[
|
||||
{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 },
|
||||
{ node: 'Node3', type: NodeConnectionTypes.Main, index: 0 },
|
||||
],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2106,127 +2106,6 @@ describe('Workflow', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConnectionsByDestination', () => {
|
||||
it('should return empty object when there are no connections', () => {
|
||||
const result = Workflow.getConnectionsByDestination({});
|
||||
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should return connections by destination node', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[
|
||||
{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 },
|
||||
{ node: 'Node3', type: NodeConnectionTypes.Main, index: 1 },
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
const result = Workflow.getConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[],
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle multiple connection types', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
[NodeConnectionTypes.AiAgent]: [
|
||||
[{ node: 'Node3', type: NodeConnectionTypes.AiAgent, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = Workflow.getConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.AiAgent]: [
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.AiAgent, index: 0 }],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle nodes with no connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [[]],
|
||||
},
|
||||
};
|
||||
|
||||
const result = Workflow.getConnectionsByDestination(connections);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
// @issue https://linear.app/n8n/issue/N8N-7880/cannot-load-some-templates
|
||||
it('should handle nodes with null connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
null as unknown as IConnection[],
|
||||
[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = Workflow.getConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node1', type: NodeConnectionTypes.Main, index: 1 }],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle nodes with multiple input connections', () => {
|
||||
const connections: IConnections = {
|
||||
Node1: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
Node3: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[{ node: 'Node2', type: NodeConnectionTypes.Main, index: 0 }],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = Workflow.getConnectionsByDestination(connections);
|
||||
expect(result).toEqual({
|
||||
Node2: {
|
||||
[NodeConnectionTypes.Main]: [
|
||||
[
|
||||
{ node: 'Node1', type: NodeConnectionTypes.Main, index: 0 },
|
||||
{ node: 'Node3', type: NodeConnectionTypes.Main, index: 0 },
|
||||
],
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHighestNode', () => {
|
||||
const createNode = (name: string, disabled = false) =>
|
||||
({
|
||||
|
||||
Reference in New Issue
Block a user