refactor(core): Lintfix core and workflow packages (#17096)

This commit is contained in:
Iván Ovejero
2025-07-08 13:04:50 +02:00
committed by GitHub
parent 1a4e4c5e72
commit d6b646d8cf
27 changed files with 47 additions and 86 deletions

View File

@@ -11,13 +11,6 @@ import tseslint from 'typescript-eslint';
import eslintConfigPrettier from 'eslint-config-prettier/flat';
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
// Slowest rules are disabled locally (for lint, not lintfix) to improve performance in development
// They are enabled in CI to ensure code quality
const runAllRules =
process.env.CI === 'true' ||
process.env.INCLUDE_SLOW_RULES === 'true' ||
process.argv.includes('--fix');
export const baseConfig = tseslint.config(
globalIgnores([
'node_modules/**',
@@ -110,7 +103,7 @@ export const baseConfig = tseslint.config(
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
/** https://typescript-eslint.io/rules/await-thenable/ */
'@typescript-eslint/await-thenable': runAllRules ? 'error' : 'off',
'@typescript-eslint/await-thenable': 'error',
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md
@@ -230,16 +223,12 @@ export const baseConfig = tseslint.config(
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md
*/
'@typescript-eslint/no-misused-promises': runAllRules
? ['error', { checksVoidReturn: false }]
: 'off',
'@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }],
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md
*/
'@typescript-eslint/no-floating-promises': runAllRules
? ['error', { ignoreVoid: true }]
: 'off',
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md
@@ -259,7 +248,7 @@ export const baseConfig = tseslint.config(
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md
*/
'@typescript-eslint/no-unnecessary-qualifier': runAllRules ? 'error' : 'off',
'@typescript-eslint/no-unnecessary-qualifier': 'error',
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-expressions.md
@@ -279,7 +268,7 @@ export const baseConfig = tseslint.config(
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md
*/
'@typescript-eslint/promise-function-async': runAllRules ? 'error' : 'off',
'@typescript-eslint/promise-function-async': 'error',
/**
* https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/triple-slash-reference.md
@@ -303,7 +292,7 @@ export const baseConfig = tseslint.config(
/**
* https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-cycle.md
*/
'import-x/no-cycle': runAllRules ? ['error', { ignoreExternal: false, maxDepth: 3 }] : 'off',
'import-x/no-cycle': ['error', { ignoreExternal: false, maxDepth: 3 }],
/**
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md

View File

@@ -34,7 +34,7 @@ describe('NodeExecutionContext', () => {
timezone: 'UTC',
expression,
});
let additionalData = mock<IWorkflowExecuteAdditionalData>({
const additionalData = mock<IWorkflowExecuteAdditionalData>({
credentialsHelper: mock(),
});

View File

@@ -14,8 +14,8 @@ import type {
INodeTypes,
ICredentialDataDecryptedObject,
NodeConnectionType,
IRunData,
} from 'n8n-workflow';
import type { IRunData } from 'n8n-workflow';
import { ApplicationError, NodeConnectionTypes } from 'n8n-workflow';
import { describeCommonTests } from './shared-tests';

View File

@@ -12,8 +12,8 @@ import type {
INodeTypes,
IExecuteFunctions,
IRunData,
ITaskData,
} from 'n8n-workflow';
import type { ITaskData } from 'n8n-workflow';
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
import { ExecuteContext } from '../../execute-context';

View File

@@ -187,7 +187,7 @@ export async function copyBinaryFile(
* Takes a buffer and converts it into the format n8n uses. It encodes the binary data as
* base64 and adds metadata.
*/
// eslint-disable-next-line complexity
export async function prepareBinaryData(
binaryData: Buffer | Readable,
executionId: string,

View File

@@ -5,7 +5,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-shadow */
import { Logger } from '@n8n/backend-common';
import type {
ClientOAuth2Options,
@@ -227,11 +227,10 @@ const getBeforeRedirectFn =
axiosConfig: AxiosRequestConfig,
proxyConfig: IHttpRequestOptions['proxy'] | string | undefined,
) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(redirectedRequest: Record<string, any>) => {
const redirectAgentOptions = {
...agentOptions,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
servername: redirectedRequest.hostname,
};
const redirectAgent = getAgentWithProxy({
@@ -248,7 +247,6 @@ const getBeforeRedirectFn =
}
if (axiosConfig.headers?.Authorization) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
redirectedRequest.headers.Authorization = axiosConfig.headers.Authorization;
}
if (axiosConfig.auth) {
@@ -327,11 +325,8 @@ export async function invokeAxios(
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const pushFormDataValue = (form: FormData, key: string, value: any) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
if (value?.hasOwnProperty('value') && value.hasOwnProperty('options')) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
form.append(key, value.value, value.options);
} else {
form.append(key, value);
@@ -361,7 +356,6 @@ async function generateContentLengthHeader(config: AxiosRequestConfig) {
}
try {
const length = await new Promise<number>((res, rej) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
config.data.getLength((error: Error | null, dataLength: number) => {
if (error) rej(error);
else res(dataLength);
@@ -372,7 +366,6 @@ async function generateContentLengthHeader(config: AxiosRequestConfig) {
'content-length': length,
};
} catch (error) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Container.get(Logger).error('Unable to calculate form data length', { error });
}
}
@@ -416,7 +409,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
if (typeof requestObject.body === 'string') {
axiosConfig.data = requestObject.body;
} else {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const allData = Object.assign(requestObject.body || {}, requestObject.form || {}) as Record<
string,
string
@@ -441,9 +433,9 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
// replace the existing header with a new one that
// contains the boundary property.
delete axiosConfig.headers?.[contentTypeHeaderKeyName!];
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const headers = axiosConfig.data.getHeaders();
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers);
await generateContentLengthHeader(axiosConfig);
} else {
@@ -482,16 +474,16 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
axiosConfig.data = createFormDataObject(requestObject.formData as Record<string, unknown>);
}
// Mix in headers as FormData creates the boundary.
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
const headers = axiosConfig.data.getHeaders();
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers);
await generateContentLengthHeader(axiosConfig);
} else if (requestObject.body !== undefined) {
// If we have body and possibly form
if (requestObject.form !== undefined && requestObject.body) {
// merge both objects when exist.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
requestObject.body = Object.assign(requestObject.body, requestObject.form);
}
axiosConfig.data = requestObject.body as FormData | GenericValue | GenericValue[];
@@ -559,7 +551,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
if (requestObject.auth !== undefined) {
// Check support for sendImmediately
if (requestObject.auth.bearer !== undefined) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
Authorization: `Bearer ${requestObject.auth.bearer}`,
});
@@ -567,9 +558,8 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
const authObj = requestObject.auth;
// Request accepts both user/username and pass/password
axiosConfig.auth = {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
username: (authObj.user || authObj.username) as string,
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
password: (authObj.password || authObj.pass) as string,
};
}
@@ -586,7 +576,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
.map((headerKey) => headerKey.toLowerCase())
.includes('accept');
if (!acceptHeaderExists) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
Accept: 'application/json',
});
@@ -594,7 +583,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
}
if (requestObject.json === false || requestObject.json === undefined) {
// Prevent json parsing
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
axiosConfig.transformResponse = (res) => res;
}
@@ -647,7 +636,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
// as the service returns XML unless requested otherwise.
const allHeaders = axiosConfig.headers ? Object.keys(axiosConfig.headers) : [];
if (!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'accept')) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { accept: '*/*' });
}
if (
@@ -661,7 +649,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
// If we don't specify this here, axios will add
// application/json; charset=utf-8
// and this breaks a lot of stuff
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
'content-type': 'application/json',
});
@@ -771,7 +759,6 @@ export async function proxyRequestToAxios(
}
}
// eslint-disable-next-line complexity
export function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequestConfig {
// Destructure properties with the same name first.
const { headers, method, timeout, auth, proxy, url } = n8nRequest;

View File

@@ -40,7 +40,7 @@ const validateResourceMapperValue = (
for (let i = 0; i < paramValueNames.length; i++) {
const key = paramValueNames[i];
const resolvedValue = paramValues[key];
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const schemaEntry = schema.find((s) => s.id === key);
if (

View File

@@ -7,8 +7,8 @@
// 1 means the output has run data
// PD denotes that the node has pinned data
import type { IPinData } from 'n8n-workflow';
import { NodeConnectionTypes, type IRunData } from 'n8n-workflow';
import type { IPinData, IRunData } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { createNodeData, toITaskData } from './helpers';
import { DirectedGraph } from '../directed-graph';

View File

@@ -15,8 +15,10 @@ import type {
ISourceData,
IWaitingForExecution,
IWaitingForExecutionSource,
IPinData,
IRunData,
} from 'n8n-workflow';
import { NodeConnectionTypes, type IPinData, type IRunData } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { createNodeData, toITaskData } from './helpers';
import { DirectedGraph } from '../directed-graph';

View File

@@ -124,12 +124,12 @@ export class DirectedGraph {
const newConnections: GraphConnection[] = [];
for (const incomingConnection of incomingConnections) {
if (options.skipConnectionFn && options.skipConnectionFn(incomingConnection)) {
if (options.skipConnectionFn?.(incomingConnection)) {
continue;
}
for (const outgoingConnection of outgoingConnections) {
if (options.skipConnectionFn && options.skipConnectionFn(outgoingConnection)) {
if (options.skipConnectionFn?.(outgoingConnection)) {
continue;
}

View File

@@ -123,7 +123,6 @@ export function getSourceDataGroups(
currentInputIndex++;
const connectionWithDataIndex = sortedConnectionsWithData.findIndex(
// eslint-disable-next-line @typescript-eslint/no-loop-func
(c) => c.inputIndex === currentInputIndex,
);
@@ -137,7 +136,6 @@ export function getSourceDataGroups(
}
const connectionWithoutDataIndex = sortedConnectionsWithoutData.findIndex(
// eslint-disable-next-line @typescript-eslint/no-loop-func
(c) => c.inputIndex === currentInputIndex,
);

View File

@@ -1178,7 +1178,6 @@ export class WorkflowExecute {
const newInputData: ITaskDataConnections = {};
for (const connectionType of Object.keys(inputData)) {
newInputData[connectionType] = inputData[connectionType].map((input) => {
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
return input && input.slice(0, 1);
});
}
@@ -1558,7 +1557,7 @@ export class WorkflowExecute {
if (waitBetweenTries !== 0) {
// TODO: Improve that in the future and check if other nodes can
// be executed in the meantime
// eslint-disable-next-line @typescript-eslint/no-shadow
await new Promise((resolve) => {
setTimeout(() => {
resolve(undefined);
@@ -1767,14 +1766,11 @@ export class WorkflowExecute {
lineResult.json.$error !== undefined &&
lineResult.json.$json !== undefined
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError;
lineResult.json = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
error: (lineResult.json.$error as NodeApiError | NodeOperationError).message,
};
} else if (lineResult.error !== undefined) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
lineResult.json = { error: lineResult.error.message };
}
}
@@ -1986,7 +1982,7 @@ export class WorkflowExecute {
const parentNodes = workflow.getParentNodes(nodeName);
// Check if input nodes (of same run) got already executed
// eslint-disable-next-line @typescript-eslint/no-loop-func
const parentIsWaiting = parentNodes.some((value) => waitingNodes.includes(value));
if (parentIsWaiting) {
// Execute node later as one of its dependencies is still outstanding
@@ -2127,12 +2123,11 @@ export class WorkflowExecute {
this.moveNodeMetadata();
await hooks.runHook('workflowExecuteAfter', [fullRunData, newStaticData]).catch(
// eslint-disable-next-line @typescript-eslint/no-shadow
(error) => {
await hooks
.runHook('workflowExecuteAfter', [fullRunData, newStaticData])
.catch((error) => {
console.error('There was a problem running hook "workflowExecuteAfter"', error);
},
);
});
if (closeFunction) {
try {

View File

@@ -9,7 +9,7 @@ export const loadClassInIsolation = <T>(filePath: string, className: string) =>
// Note: Skip the isolation because it breaks nock mocks in tests
if (inTest) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return new (require(filePath)[className])() as T;
} else {
const script = new Script(`new (require('${filePath}').${className})()`);

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity */
const check = (
val: unknown,
path = 'value',

View File

@@ -12,10 +12,8 @@ function augment<T>(value: T): T {
if (value instanceof Date) return new Date(value.valueOf()) as T;
if (value instanceof Uint8Array) return value.slice() as T;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (Array.isArray(value)) return augmentArray(value) as T;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return augmentObject(value) as T;
}

View File

@@ -94,7 +94,7 @@ export abstract class NodeError extends ExecutionBaseError {
if (typeof value === 'number') return value.toString();
if (Array.isArray(value)) {
const resolvedErrors: string[] = value
// eslint-disable-next-line @typescript-eslint/no-shadow
.map((jsonError) => {
if (typeof jsonError === 'string') return jsonError;
if (typeof jsonError === 'number') return jsonError.toString();

View File

@@ -1,5 +1,5 @@
import { ExecutionBaseError } from './abstract/execution-base.error';
import type { IDataObject } from '../interfaces';
import { ExecutionBaseError } from './abstract/execution-base.error';
export interface ExpressionErrorOptions {
cause?: Error;

View File

@@ -1,5 +1,5 @@
import { ExecutionBaseError } from './abstract/execution-base.error';
import type { INode } from '../interfaces';
import { ExecutionBaseError } from './abstract/execution-base.error';
/**
* Class for instantiating an operational error, e.g. a timeout error.

View File

@@ -14,7 +14,6 @@ export const PrototypeSanitizer: ASTAfterHook = (ast, dataNode) => {
if (!node.computed) {
// This is static, so we're safe to error here
if (node.property.type !== 'Identifier') {
// eslint-disable-next-line n8n-local-rules/no-plain-errors
throw new ExpressionError(
`Unknown property type ${node.property.type} while sanitising expression`,
);

View File

@@ -5,6 +5,7 @@ import { ExpressionExtensionError } from './errors/expression-extension.error';
import { ExpressionError } from './errors/expression.error';
import { evaluateExpression, setErrorHandler } from './expression-evaluator-proxy';
import { sanitizer, sanitizerName } from './expression-sandboxing';
import { isExpression } from './expressions/expression-helpers';
import { extend, extendOptional } from './extensions';
import { extendSyntax } from './extensions/expression-extension';
import { extendedFunctions } from './extensions/extended-functions';
@@ -25,7 +26,6 @@ import type {
} from './interfaces';
import type { Workflow } from './workflow';
import { WorkflowDataProxy } from './workflow-data-proxy';
import { isExpression } from './expressions/expression-helpers';
const IS_FRONTEND_IN_DEV_MODE =
typeof process === 'object' &&

View File

@@ -136,7 +136,6 @@ export const extendTransform = (expression: string): { code: string } | undefine
// This is to match behavior in our original expression evaluator (tmpl)
const globalIdentifier = types.builders.identifier(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
typeof window !== 'object' ? 'global' : 'window',
);
// We want to define all of our commonly used identifiers and member

View File

@@ -893,7 +893,7 @@ type BaseExecutionFunctions = FunctionsBaseWithRequiredKeys<'getMode'> & {
getInputSourceData(inputIndex?: number, connectionType?: NodeConnectionType): ISourceData;
getExecutionCancelSignal(): AbortSignal | undefined;
onExecutionCancellation(handler: () => unknown): void;
logAiEvent(eventName: AiEvent, msg?: string | undefined): void;
logAiEvent(eventName: AiEvent, msg?: string): void;
};
// TODO: Create later own type only for Config-Nodes
@@ -1002,7 +1002,7 @@ export type ISupplyDataFunctions = ExecuteFunctions.GetNodeParameterFn &
getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData;
getExecutionCancelSignal(): AbortSignal | undefined;
onExecutionCancellation(handler: () => unknown): void;
logAiEvent(eventName: AiEvent, msg?: string | undefined): void;
logAiEvent(eventName: AiEvent, msg?: string): void;
cloneWith(replacements: {
runIndex: number;
inputData: INodeExecutionData[][];
@@ -1551,7 +1551,7 @@ export interface INodePropertyValueExtractorFunction {
(
this: IExecuteSingleFunctions,
value: string | NodeParameterValue,
): Promise<string | NodeParameterValue> | (string | NodeParameterValue);
): Promise<string | NodeParameterValue> | string;
}
export type INodePropertyValueExtractor = INodePropertyValueExtractorRegex;

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable prefer-spread */
@@ -840,7 +840,6 @@ export function getNodeParameters(
itemName
] as INodeParameters[]) {
nodePropertyOptions = nodeProperties.options!.find(
// eslint-disable-next-line @typescript-eslint/no-shadow
(nodePropertyOptions) => nodePropertyOptions.name === itemName,
) as INodePropertyCollection;
@@ -875,7 +874,7 @@ export function getNodeParameters(
tempNodeParameters = {};
// Get the options of the current item
// eslint-disable-next-line @typescript-eslint/no-shadow
const nodePropertyOptions = nodeProperties.options!.find(
(data) => data.name === itemName,
);

View File

@@ -60,7 +60,6 @@ const withIndefiniteArticle = (noun: string): string => {
return `${article} ${noun}`;
};
// eslint-disable-next-line complexity
function parseFilterConditionValues(
condition: FilterConditionValue,
options: FilterOptionsValue,

View File

@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-shadow */
import type { IDataObject, IObservableObject } from './interfaces';

View File

@@ -1030,7 +1030,7 @@ export class WorkflowDataProxy {
const placeholdersDataInputData =
inputData?.[NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
if (Boolean(!placeholdersDataInputData)) {
if (!placeholdersDataInputData) {
throw new ExpressionError('No execution data available', {
runIndex,
itemIndex,

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-for-in-array */
@@ -534,7 +533,7 @@ export class Workflow {
}
connectionsByIndex =
this.connectionsByDestinationNode[nodeName][NodeConnectionTypes.Main][connectionIndex];
// eslint-disable-next-line @typescript-eslint/no-loop-func
connectionsByIndex?.forEach((connection) => {
if (checkedNodes.includes(connection.node)) {
// Node got checked already before
@@ -730,7 +729,6 @@ export class Workflow {
const toAdd = [...queue];
queue = [];
// eslint-disable-next-line @typescript-eslint/no-loop-func
toAdd.forEach((curr) => {
if (visited[curr.name]) {
visited[curr.name].indicies = dedupe(visited[curr.name].indicies.concat(curr.indicies));
@@ -770,7 +768,7 @@ export class Workflow {
const outputs = NodeHelpers.getNodeOutputs(this, node, nodeType.description);
if (
!!outputs.find(
outputs.find(
(output) =>
((output as INodeOutputConfiguration)?.type ?? output) !== NodeConnectionTypes.Main,
)