🎨 Set up linting and formatting (#2120)

* ⬆️ Upgrade TS to 4.3.5

* 👕 Add ESLint configs

* 🎨 Add Prettier config

* 📦 Add deps and commands

*  Adjust global .editorconfig to new ruleset

* 🔥 Remove unneeded local .editorconfig

* 📦 Update deps in editor-ui

* 🔨 Limit Prettier to only TS files

*  Add recommended VSCode extensions

* 👕 Fix build

* 🔥 Remove Vue setting from global config

*  Disable prefer-default-export per feedback

* ✏️ Add forgotten divider

* 👕 Disable no-plusplus

* 👕 Disable class-methods-use-this

* ✏️ Alphabetize overrides

* 👕 Add one-var consecutive override

*  Revert one-var consecutive override

This reverts commit b9252cf935659ba6d76727ad484a1d3c00008fcc.

* 🎨 👕 Lint and format workflow package (#2121)

* 🎨 Format /workflow package

* 👕 Lint /workflow package

* 🎨 Re-format /workflow package

* 👕 Re-lint /workflow package

* ✏️ Fix typo

*  Consolidate if-checks

* 🔥 Remove prefer-default-export exceptions

* 🔥 Remove no-plusplus exceptions

* 🔥 Remove class-methods-use-this exceptions

* 🎨 👕 Lint and format node-dev package (#2122)

* 🎨 Format /node-dev package

*  Exclude templates from ESLint config

This keeps the templates consistent with the codebase while preventing lint exceptions from being made part of the templates.

* 👕 Lint /node-dev package

* 🔥 Remove prefer-default-export exceptions

* 🔥 Remove no-plusplus exceptions

* 🎨 👕 Lint and format core package (#2123)

* 🎨 Format /core package

* 👕 Lint /core package

* 🎨 Re-format /core package

* 👕 Re-lint /core package

* 🔥 Remove prefer-default-export exceptions

* 🔥 Remove no-plusplus exceptions

* 🔥 Remove class-methods-use-this exceptions

* 🎨 👕 Lint and format cli package (#2124)

* 🎨 Format /cli package

* 👕 Exclude migrations from linting

* 👕 Lint /cli package

* 🎨 Re-format /cli package

* 👕 Re-lint /cli package

* 👕 Fix build

* 🔥 Remove prefer-default-export exceptions

*  Update exceptions in ActiveExecutions

* 🔥 Remove no-plusplus exceptions

* 🔥 Remove class-methods-use-this exceptions

* 👕 fix lint issues

* 🔧 use package specific linter, remove tslint command

* 🔨 resolve build issue, sync dependencies

* 🔧 change lint command

Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
This commit is contained in:
Iván Ovejero
2021-08-29 20:58:11 +02:00
committed by GitHub
parent 223cd75685
commit 56c4c6991f
108 changed files with 11832 additions and 8416 deletions

View File

@@ -1,4 +1,15 @@
/* eslint-disable no-param-reassign */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-for-in-array */
/* eslint-disable no-prototype-builtins */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-continue */
/* eslint-disable no-restricted-syntax */
/* eslint-disable import/no-cycle */
// eslint-disable-next-line import/no-cycle
import {
Expression,
IConnections,
@@ -26,20 +37,27 @@ import {
WebhookSetupMethodNames,
WorkflowActivateMode,
WorkflowExecuteMode,
} from './';
} from '.';
import { IConnection, IDataObject, IObservableObject } from './Interfaces';
export class Workflow {
id: string | undefined;
name: string | undefined;
nodes: INodes = {};
connectionsBySourceNode: IConnections;
connectionsByDestinationNode: IConnections;
nodeTypes: INodeTypes;
expression: Expression;
active: boolean;
settings: IWorkflowSettings;
// To save workflow specific static data like for example
@@ -47,7 +65,16 @@ export class Workflow {
staticData: IDataObject;
// constructor(id: string | undefined, nodes: INode[], connections: IConnections, active: boolean, nodeTypes: INodeTypes, staticData?: IDataObject, settings?: IWorkflowSettings) {
constructor(parameters: {id?: string, name?: string, nodes: INode[], connections: IConnections, active: boolean, nodeTypes: INodeTypes, staticData?: IDataObject, settings?: IWorkflowSettings}) {
constructor(parameters: {
id?: string;
name?: string;
nodes: INode[];
connections: IConnections;
active: boolean;
nodeTypes: INodeTypes;
staticData?: IDataObject;
settings?: IWorkflowSettings;
}) {
this.id = parameters.id;
this.name = parameters.name;
this.nodeTypes = parameters.nodeTypes;
@@ -70,7 +97,12 @@ export class Workflow {
}
// Add default values
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.description.properties, node.parameters, true, false);
const nodeParameters = NodeHelpers.getNodeParameters(
nodeType.description.properties,
node.parameters,
true,
false,
);
node.parameters = nodeParameters !== null ? nodeParameters : {};
}
this.connectionsBySourceNode = parameters.connections;
@@ -80,15 +112,15 @@ export class Workflow {
this.active = parameters.active || false;
this.staticData = ObservableObject.create(parameters.staticData || {}, undefined, { ignoreEmptyOnFirstChild: true });
this.staticData = ObservableObject.create(parameters.staticData || {}, undefined, {
ignoreEmptyOnFirstChild: true,
});
this.settings = parameters.settings || {};
this.expression = new Expression(this);
}
/**
* The default connections are by source node. This function rewrites them by destination nodes
* to easily find parent nodes.
@@ -140,8 +172,6 @@ export class Workflow {
return returnConnection;
}
/**
* A workflow can only be activated if it has a node which has either triggers
* or webhooks defined.
@@ -162,6 +192,7 @@ export class Workflow {
continue;
}
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
if (ignoreNodeTypes !== undefined && ignoreNodeTypes.includes(node.type)) {
continue;
}
@@ -173,7 +204,11 @@ export class Workflow {
continue;
}
if (nodeType.poll !== undefined || nodeType.trigger !== undefined || nodeType.webhook !== undefined) {
if (
nodeType.poll !== undefined ||
nodeType.trigger !== undefined ||
nodeType.webhook !== undefined
) {
// Is a trigger node. So workflow can be activated.
return true;
}
@@ -182,8 +217,6 @@ export class Workflow {
return false;
}
/**
* Checks if everything in the workflow is complete
* and ready to be executed. If it returns null everything
@@ -216,7 +249,7 @@ export class Workflow {
typeUnknown: true,
};
} else {
nodeIssues = NodeHelpers.getNodeParametersIssues(nodeType.description.properties!, node);
nodeIssues = NodeHelpers.getNodeParametersIssues(nodeType.description.properties, node);
}
if (nodeIssues !== null) {
@@ -231,8 +264,6 @@ export class Workflow {
return workflowIssues;
}
/**
* Returns the static data of the workflow.
* It gets saved with the workflow and will be the same for
@@ -249,11 +280,15 @@ export class Workflow {
key = 'global';
} else if (type === 'node') {
if (node === undefined) {
throw new Error(`The request data of context type "node" the node parameter has to be set!`);
throw new Error(
`The request data of context type "node" the node parameter has to be set!`,
);
}
key = `node:${node.name}`;
} else {
throw new Error(`The context type "${type}" is not know. Only "global" and node" are supported!`);
throw new Error(
`The context type "${type}" is not know. Only "global" and node" are supported!`,
);
}
if (this.staticData[key] === undefined) {
@@ -265,8 +300,6 @@ export class Workflow {
return this.staticData[key] as IDataObject;
}
/**
* Returns all the trigger nodes in the workflow.
*
@@ -274,10 +307,9 @@ export class Workflow {
* @memberof Workflow
*/
getTriggerNodes(): INode[] {
return this.queryNodes((nodeType: INodeType) => !!nodeType.trigger );
return this.queryNodes((nodeType: INodeType) => !!nodeType.trigger);
}
/**
* Returns all the poll nodes in the workflow
*
@@ -285,10 +317,9 @@ export class Workflow {
* @memberof Workflow
*/
getPollNodes(): INode[] {
return this.queryNodes((nodeType: INodeType) => !!nodeType.poll );
return this.queryNodes((nodeType: INodeType) => !!nodeType.poll);
}
/**
* Returns all the nodes in the workflow for which the given
* checkFunction return true
@@ -321,8 +352,6 @@ export class Workflow {
return returnNodes;
}
/**
* Returns the node with the given name if it exists else null
*
@@ -338,7 +367,6 @@ export class Workflow {
return null;
}
/**
* Renames nodes in expressions
*
@@ -348,7 +376,11 @@ export class Workflow {
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
* @memberof Workflow
*/
renameNodeInExpressions(parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], currentName: string, newName: string): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
renameNodeInExpressions(
parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
currentName: string,
newName: string,
): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
if (typeof parameterValue !== 'object') {
// Reached the actual value
if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') {
@@ -362,7 +394,11 @@ export class Workflow {
// In case some special characters are used in name escape them
const currentNameEscaped = currentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
parameterValue = parameterValue.replace(new RegExp(`(\\$node(\.|\\["|\\[\'))${currentNameEscaped}((\.|"\\]|\'\\]))`, 'g'), `$1${newName}$3`);
parameterValue = parameterValue.replace(
// eslint-disable-next-line no-useless-escape
new RegExp(`(\\$node(\.|\\["|\\[\'))${currentNameEscaped}((\.|"\\]|\'\\]))`, 'g'),
`$1${newName}$3`,
);
}
}
@@ -370,7 +406,8 @@ export class Workflow {
}
if (Array.isArray(parameterValue)) {
const returnArray: any[] = []; // tslint:disable-line:no-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const returnArray: any[] = [];
for (const currentValue of parameterValue) {
returnArray.push(this.renameNodeInExpressions(currentValue, currentName, newName));
@@ -379,17 +416,21 @@ export class Workflow {
return returnArray;
}
const returnData: any = {}; // tslint:disable-line:no-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const returnData: any = {};
for (const parameterName of Object.keys(parameterValue || {})) {
returnData[parameterName] = this.renameNodeInExpressions(parameterValue![parameterName], currentName, newName);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
returnData[parameterName] = this.renameNodeInExpressions(
parameterValue![parameterName],
currentName,
newName,
);
}
return returnData;
}
/**
* Rename a node in the workflow
*
@@ -398,7 +439,6 @@ export class Workflow {
* @memberof Workflow
*/
renameNode(currentName: string, newName: string) {
// Rename the node itself
if (this.nodes[currentName] !== undefined) {
this.nodes[newName] = this.nodes[currentName];
@@ -409,7 +449,11 @@ export class Workflow {
// Update the expressions which reference the node
// with its old name
for (const node of Object.values(this.nodes)) {
node.parameters = this.renameNodeInExpressions(node.parameters, currentName, newName) as INodeParameters;
node.parameters = this.renameNodeInExpressions(
node.parameters,
currentName,
newName,
) as INodeParameters;
}
// Change all source connections
@@ -419,12 +463,21 @@ export class Workflow {
}
// Change all destination connections
let sourceNode: string, type: string, sourceIndex: string, connectionIndex: string, connectionData: IConnection;
let sourceNode: string;
let type: string;
let sourceIndex: string;
let connectionIndex: string;
let connectionData: IConnection;
for (sourceNode of Object.keys(this.connectionsBySourceNode)) {
for (type of Object.keys(this.connectionsBySourceNode[sourceNode])) {
for (sourceIndex of Object.keys(this.connectionsBySourceNode[sourceNode][type])) {
for (connectionIndex of Object.keys(this.connectionsBySourceNode[sourceNode][type][parseInt(sourceIndex, 10)])) {
connectionData = this.connectionsBySourceNode[sourceNode][type][parseInt(sourceIndex, 10)][parseInt(connectionIndex, 10)];
for (connectionIndex of Object.keys(
this.connectionsBySourceNode[sourceNode][type][parseInt(sourceIndex, 10)],
)) {
connectionData =
this.connectionsBySourceNode[sourceNode][type][parseInt(sourceIndex, 10)][
parseInt(connectionIndex, 10)
];
if (connectionData.node === currentName) {
connectionData.node = newName;
}
@@ -434,11 +487,11 @@ export class Workflow {
}
// Use the updated connections to create updated connections by destionation nodes
this.connectionsByDestinationNode = this.__getConnectionsByDestination(this.connectionsBySourceNode);
this.connectionsByDestinationNode = this.__getConnectionsByDestination(
this.connectionsBySourceNode,
);
}
/**
* Finds the highest parent nodes of the node with the given name
*
@@ -448,7 +501,12 @@ export class Workflow {
* @returns {string[]}
* @memberof Workflow
*/
getHighestNode(nodeName: string, type = 'main', nodeConnectionIndex?:number, checkedNodes?: string[]): string[] {
getHighestNode(
nodeName: string,
type = 'main',
nodeConnectionIndex?: number,
checkedNodes?: string[],
): string[] {
const currentHighest: string[] = [];
if (this.nodes[nodeName].disabled === false) {
// If the current node is not disabled itself is the highest
@@ -467,23 +525,28 @@ export class Workflow {
checkedNodes = checkedNodes || [];
if (checkedNodes!.includes(nodeName)) {
if (checkedNodes.includes(nodeName)) {
// Node got checked already before
return currentHighest;
}
checkedNodes!.push(nodeName);
checkedNodes.push(nodeName);
const returnNodes: string[] = [];
let addNodes: string[];
let connectionsByIndex: IConnection[];
for (let connectionIndex = 0; connectionIndex < this.connectionsByDestinationNode[nodeName][type].length; connectionIndex++) {
for (
let connectionIndex = 0;
connectionIndex < this.connectionsByDestinationNode[nodeName][type].length;
connectionIndex++
) {
if (nodeConnectionIndex !== undefined && nodeConnectionIndex !== connectionIndex) {
// If a connection-index is given ignore all other ones
continue;
}
connectionsByIndex = this.connectionsByDestinationNode[nodeName][type][connectionIndex];
// eslint-disable-next-line @typescript-eslint/no-loop-func
connectionsByIndex.forEach((connection) => {
if (checkedNodes!.includes(connection.node)) {
// Node got checked already before
@@ -512,8 +575,6 @@ export class Workflow {
return returnNodes;
}
/**
* Returns all the after the given one
*
@@ -527,8 +588,6 @@ export class Workflow {
return this.getConnectedNodes(this.connectionsBySourceNode, nodeName, type, depth);
}
/**
* Returns all the nodes before the given one
*
@@ -542,8 +601,6 @@ export class Workflow {
return this.getConnectedNodes(this.connectionsByDestinationNode, nodeName, type, depth);
}
/**
* Gets all the nodes which are connected nodes starting from
* the given one
@@ -556,7 +613,13 @@ export class Workflow {
* @returns {string[]}
* @memberof Workflow
*/
getConnectedNodes(connections: IConnections, nodeName: string, type = 'main', depth = -1, checkedNodes?: string[]): string[] {
getConnectedNodes(
connections: IConnections,
nodeName: string,
type = 'main',
depth = -1,
checkedNodes?: string[],
): string[] {
depth = depth === -1 ? -1 : depth;
const newDepth = depth === -1 ? depth : depth - 1;
if (depth === 0) {
@@ -576,12 +639,12 @@ export class Workflow {
checkedNodes = checkedNodes || [];
if (checkedNodes!.includes(nodeName)) {
if (checkedNodes.includes(nodeName)) {
// Node got checked already before
return [];
}
checkedNodes!.push(nodeName);
checkedNodes.push(nodeName);
const returnNodes: string[] = [];
let addNodes: string[];
@@ -597,7 +660,13 @@ export class Workflow {
returnNodes.unshift(connection.node);
addNodes = this.getConnectedNodes(connections, connection.node, type, newDepth, checkedNodes);
addNodes = this.getConnectedNodes(
connections,
connection.node,
type,
newDepth,
checkedNodes,
);
for (i = addNodes.length; i--; i > 0) {
// Because nodes can have multiple parents it is possible that
@@ -620,8 +689,6 @@ export class Workflow {
return returnNodes;
}
/**
* Returns via which output of the parent-node the node
* is connected to.
@@ -634,7 +701,13 @@ export class Workflow {
* @returns {(number | undefined)}
* @memberof Workflow
*/
getNodeConnectionOutputIndex(nodeName: string, parentNodeName: string, type = 'main', depth = -1, checkedNodes?: string[]): number | undefined {
getNodeConnectionOutputIndex(
nodeName: string,
parentNodeName: string,
type = 'main',
depth = -1,
checkedNodes?: string[],
): number | undefined {
const node = this.getNode(parentNodeName);
if (node === null) {
return undefined;
@@ -665,12 +738,12 @@ export class Workflow {
checkedNodes = checkedNodes || [];
if (checkedNodes!.includes(nodeName)) {
if (checkedNodes.includes(nodeName)) {
// Node got checked already before
return undefined;
}
checkedNodes!.push(nodeName);
checkedNodes.push(nodeName);
let outputIndex: number | undefined;
for (const connectionsByIndex of this.connectionsByDestinationNode[nodeName][type]) {
@@ -679,12 +752,18 @@ export class Workflow {
return connection.index;
}
if (checkedNodes!.includes(connection.node)) {
if (checkedNodes.includes(connection.node)) {
// Node got checked already before so continue with the next one
continue;
}
outputIndex = this.getNodeConnectionOutputIndex(connection.node, parentNodeName, type, newDepth, checkedNodes);
outputIndex = this.getNodeConnectionOutputIndex(
connection.node,
parentNodeName,
type,
newDepth,
checkedNodes,
);
if (outputIndex !== undefined) {
return outputIndex;
@@ -695,9 +774,6 @@ export class Workflow {
return undefined;
}
/**
* Returns from which of the given nodes the workflow should get started from
*
@@ -713,7 +789,6 @@ export class Workflow {
node = this.nodes[nodeName];
nodeType = this.nodeTypes.getByName(node.type) as INodeType;
if (nodeType.trigger !== undefined || nodeType.poll !== undefined) {
if (node.disabled === true) {
continue;
@@ -734,8 +809,6 @@ export class Workflow {
return undefined;
}
/**
* Returns the start node to start the worfklow from
*
@@ -744,7 +817,6 @@ export class Workflow {
* @memberof Workflow
*/
getStartNode(destinationNode?: string): INode | undefined {
if (destinationNode) {
// Find the highest parent nodes of the given one
const nodeNames = this.getHighestNode(destinationNode);
@@ -769,8 +841,6 @@ export class Workflow {
return this.__getStartNode(Object.keys(this.nodes));
}
/**
* Executes the Webhooks method of the node
*
@@ -781,11 +851,17 @@ export class Workflow {
* @returns {(Promise<boolean | undefined>)}
* @memberof Workflow
*/
async runWebhookMethod(method: WebhookSetupMethodNames, webhookData: IWebhookData, nodeExecuteFunctions: INodeExecuteFunctions, mode: WorkflowExecuteMode, activation: WorkflowActivateMode, isTest?: boolean): Promise<boolean | undefined> {
async runWebhookMethod(
method: WebhookSetupMethodNames,
webhookData: IWebhookData,
nodeExecuteFunctions: INodeExecuteFunctions,
mode: WorkflowExecuteMode,
activation: WorkflowActivateMode,
isTest?: boolean,
): Promise<boolean | undefined> {
const node = this.getNode(webhookData.node) as INode;
const nodeType = this.nodeTypes.getByName(node.type) as INodeType;
if (nodeType.webhookMethods === undefined) {
return;
}
@@ -798,11 +874,19 @@ export class Workflow {
return;
}
const thisArgs = nodeExecuteFunctions.getExecuteHookFunctions(this, node, webhookData.workflowExecuteAdditionalData, mode, activation, isTest, webhookData);
const thisArgs = nodeExecuteFunctions.getExecuteHookFunctions(
this,
node,
webhookData.workflowExecuteAdditionalData,
mode,
activation,
isTest,
webhookData,
);
// eslint-disable-next-line consistent-return
return nodeType.webhookMethods[webhookData.webhookDescription.name][method]!.call(thisArgs);
}
/**
* Runs the given trigger node so that it can trigger the workflow
* when the node has data.
@@ -814,7 +898,13 @@ export class Workflow {
* @returns {(Promise<ITriggerResponse | undefined>)}
* @memberof Workflow
*/
async runTrigger(node: INode, getTriggerFunctions: IGetExecuteTriggerFunctions, additionalData: IWorkflowExecuteAdditionalData, mode: WorkflowExecuteMode, activation: WorkflowActivateMode): Promise<ITriggerResponse | undefined> {
async runTrigger(
node: INode,
getTriggerFunctions: IGetExecuteTriggerFunctions,
additionalData: IWorkflowExecuteAdditionalData,
mode: WorkflowExecuteMode,
activation: WorkflowActivateMode,
): Promise<ITriggerResponse | undefined> {
const triggerFunctions = getTriggerFunctions(this, node, additionalData, mode, activation);
const nodeType = this.nodeTypes.getByName(node.type);
@@ -824,29 +914,30 @@ export class Workflow {
}
if (!nodeType.trigger) {
throw new Error(`The node type "${node.type}" of node "${node.name}" does not have a trigger function defined.`);
throw new Error(
`The node type "${node.type}" of node "${node.name}" does not have a trigger function defined.`,
);
}
if (mode === 'manual') {
// In manual mode we do not just start the trigger function we also
// want to be able to get informed as soon as the first data got emitted
const triggerResponse = await nodeType.trigger!.call(triggerFunctions);
const triggerResponse = await nodeType.trigger.call(triggerFunctions);
// Add the manual trigger response which resolves when the first time data got emitted
triggerResponse!.manualTriggerResponse = new Promise((resolve) => {
// eslint-disable-next-line @typescript-eslint/no-shadow
triggerFunctions.emit = ((resolve) => (data: INodeExecutionData[][]) => {
resolve(data);
})(resolve);
});
return triggerResponse;
} else {
// In all other modes simply start the trigger
return nodeType.trigger!.call(triggerFunctions);
}
// In all other modes simply start the trigger
return nodeType.trigger.call(triggerFunctions);
}
/**
* Runs the given trigger node so that it can trigger the workflow
* when the node has data.
@@ -856,7 +947,10 @@ export class Workflow {
* @returns
* @memberof Workflow
*/
async runPoll(node: INode, pollFunctions: IPollFunctions): Promise<INodeExecutionData[][] | null> {
async runPoll(
node: INode,
pollFunctions: IPollFunctions,
): Promise<INodeExecutionData[][] | null> {
const nodeType = this.nodeTypes.getByName(node.type);
if (nodeType === undefined) {
@@ -864,13 +958,14 @@ export class Workflow {
}
if (!nodeType.poll) {
throw new Error(`The node type "${node.type}" of node "${node.name}" does not have a poll function defined.`);
throw new Error(
`The node type "${node.type}" of node "${node.name}" does not have a poll function defined.`,
);
}
return nodeType.poll!.call(pollFunctions);
return nodeType.poll.call(pollFunctions);
}
/**
* Executes the webhook data to see what it should return and if the
* workflow should be started or not
@@ -882,7 +977,13 @@ export class Workflow {
* @returns {Promise<IWebhookResponseData>}
* @memberof Workflow
*/
async runWebhook(webhookData: IWebhookData, node: INode, additionalData: IWorkflowExecuteAdditionalData, nodeExecuteFunctions: INodeExecuteFunctions, mode: WorkflowExecuteMode): Promise<IWebhookResponseData> {
async runWebhook(
webhookData: IWebhookData,
node: INode,
additionalData: IWorkflowExecuteAdditionalData,
nodeExecuteFunctions: INodeExecuteFunctions,
mode: WorkflowExecuteMode,
): Promise<IWebhookResponseData> {
const nodeType = this.nodeTypes.getByName(node.type);
if (nodeType === undefined) {
throw new Error(`The type of the webhook node "${node.name}" is not known.`);
@@ -890,11 +991,16 @@ export class Workflow {
throw new Error(`The node "${node.name}" does not have any webhooks defined.`);
}
const thisArgs = nodeExecuteFunctions.getExecuteWebhookFunctions(this, node, additionalData, mode, webhookData);
const thisArgs = nodeExecuteFunctions.getExecuteWebhookFunctions(
this,
node,
additionalData,
mode,
webhookData,
);
return nodeType.webhook.call(thisArgs);
}
/**
* Executes the given node.
*
@@ -908,7 +1014,15 @@ export class Workflow {
* @returns {(Promise<INodeExecutionData[][] | null>)}
* @memberof Workflow
*/
async runNode(node: INode, inputData: ITaskDataConnections, runExecutionData: IRunExecutionData, runIndex: number, additionalData: IWorkflowExecuteAdditionalData, nodeExecuteFunctions: INodeExecuteFunctions, mode: WorkflowExecuteMode): Promise<INodeExecutionData[][] | null | undefined> {
async runNode(
node: INode,
inputData: ITaskDataConnections,
runExecutionData: IRunExecutionData,
runIndex: number,
additionalData: IWorkflowExecuteAdditionalData,
nodeExecuteFunctions: INodeExecuteFunctions,
mode: WorkflowExecuteMode,
): Promise<INodeExecutionData[][] | null | undefined> {
if (node.disabled === true) {
// If node is disabled simply pass the data through
// return NodeRunHelpers.
@@ -917,7 +1031,7 @@ export class Workflow {
if (inputData.main[0] === null) {
return undefined;
}
return [(inputData.main[0] as INodeExecutionData[])];
return [inputData.main[0]];
}
return undefined;
}
@@ -935,7 +1049,7 @@ export class Workflow {
if (inputData.hasOwnProperty('main') && inputData.main.length > 0) {
// We always use the data of main input and the first input for executeSingle
connectionInputData = (inputData.main[0] as INodeExecutionData[]);
connectionInputData = inputData.main[0] as INodeExecutionData[];
}
if (connectionInputData.length === 0) {
@@ -944,7 +1058,10 @@ export class Workflow {
}
}
if (runExecutionData.resultData.lastNodeExecuted === node.name && runExecutionData.resultData.error !== undefined) {
if (
runExecutionData.resultData.lastNodeExecuted === node.name &&
runExecutionData.resultData.error !== undefined
) {
// The node did already fail. So throw an error here that it displays and logs it correctly.
// Does get used by webhook and trigger nodes in case they throw an error that it is possible
// to log the error and display in Editor-UI.
@@ -959,7 +1076,8 @@ export class Workflow {
connectionInputData = connectionInputData.slice(0, 1);
const newInputData: ITaskDataConnections = {};
for (const inputName of Object.keys(inputData)) {
newInputData[inputName] = inputData[inputName].map(input => {
newInputData[inputName] = inputData[inputName].map((input) => {
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
return input && input.slice(0, 1);
});
}
@@ -970,9 +1088,19 @@ export class Workflow {
const returnPromises: Array<Promise<INodeExecutionData>> = [];
for (let itemIndex = 0; itemIndex < connectionInputData.length; itemIndex++) {
const thisArgs = nodeExecuteFunctions.getExecuteSingleFunctions(this, runExecutionData, runIndex, connectionInputData, inputData, node, itemIndex, additionalData, mode);
const thisArgs = nodeExecuteFunctions.getExecuteSingleFunctions(
this,
runExecutionData,
runIndex,
connectionInputData,
inputData,
node,
itemIndex,
additionalData,
mode,
);
returnPromises.push(nodeType.executeSingle!.call(thisArgs));
returnPromises.push(nodeType.executeSingle.call(thisArgs));
}
if (returnPromises.length === 0) {
@@ -990,21 +1118,41 @@ export class Workflow {
return [promiseResults];
}
} else if (nodeType.execute) {
const thisArgs = nodeExecuteFunctions.getExecuteFunctions(this, runExecutionData, runIndex, connectionInputData, inputData, node, additionalData, mode);
const thisArgs = nodeExecuteFunctions.getExecuteFunctions(
this,
runExecutionData,
runIndex,
connectionInputData,
inputData,
node,
additionalData,
mode,
);
return nodeType.execute.call(thisArgs);
} else if (nodeType.poll) {
if (mode === 'manual') {
// In manual mode run the poll function
const thisArgs = nodeExecuteFunctions.getExecutePollFunctions(this, node, additionalData, mode, 'manual');
const thisArgs = nodeExecuteFunctions.getExecutePollFunctions(
this,
node,
additionalData,
mode,
'manual',
);
return nodeType.poll.call(thisArgs);
} else {
// In any other mode pass data through as it already contains the result of the poll
return inputData.main as INodeExecutionData[][];
}
// In any other mode pass data through as it already contains the result of the poll
return inputData.main as INodeExecutionData[][];
} else if (nodeType.trigger) {
if (mode === 'manual') {
// In manual mode start the trigger
const triggerResponse = await this.runTrigger(node, nodeExecuteFunctions.getExecuteTriggerFunctions, additionalData, mode, 'manual');
const triggerResponse = await this.runTrigger(
node,
nodeExecuteFunctions.getExecuteTriggerFunctions,
additionalData,
mode,
'manual',
);
if (triggerResponse === undefined) {
return null;
@@ -1027,11 +1175,9 @@ export class Workflow {
}
return response;
} else {
// For trigger nodes in any mode except "manual" do we simply pass the data through
return inputData.main as INodeExecutionData[][];
}
// For trigger nodes in any mode except "manual" do we simply pass the data through
return inputData.main as INodeExecutionData[][];
} else if (nodeType.webhook) {
// For webhook nodes always simply pass the data through
return inputData.main as INodeExecutionData[][];