mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Lintfix core and workflow packages (#17096)
This commit is contained in:
@@ -11,13 +11,6 @@ import tseslint from 'typescript-eslint';
|
|||||||
import eslintConfigPrettier from 'eslint-config-prettier/flat';
|
import eslintConfigPrettier from 'eslint-config-prettier/flat';
|
||||||
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
|
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(
|
export const baseConfig = tseslint.config(
|
||||||
globalIgnores([
|
globalIgnores([
|
||||||
'node_modules/**',
|
'node_modules/**',
|
||||||
@@ -110,7 +103,7 @@ export const baseConfig = tseslint.config(
|
|||||||
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||||
|
|
||||||
/** https://typescript-eslint.io/rules/await-thenable/ */
|
/** 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
|
* 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
|
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md
|
||||||
*/
|
*/
|
||||||
'@typescript-eslint/no-misused-promises': runAllRules
|
'@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }],
|
||||||
? ['error', { checksVoidReturn: false }]
|
|
||||||
: 'off',
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md
|
* 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
|
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
|
||||||
? ['error', { ignoreVoid: true }]
|
|
||||||
: 'off',
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ describe('NodeExecutionContext', () => {
|
|||||||
timezone: 'UTC',
|
timezone: 'UTC',
|
||||||
expression,
|
expression,
|
||||||
});
|
});
|
||||||
let additionalData = mock<IWorkflowExecuteAdditionalData>({
|
const additionalData = mock<IWorkflowExecuteAdditionalData>({
|
||||||
credentialsHelper: mock(),
|
credentialsHelper: mock(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import type {
|
|||||||
INodeTypes,
|
INodeTypes,
|
||||||
ICredentialDataDecryptedObject,
|
ICredentialDataDecryptedObject,
|
||||||
NodeConnectionType,
|
NodeConnectionType,
|
||||||
|
IRunData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import type { IRunData } from 'n8n-workflow';
|
|
||||||
import { ApplicationError, NodeConnectionTypes } from 'n8n-workflow';
|
import { ApplicationError, NodeConnectionTypes } from 'n8n-workflow';
|
||||||
|
|
||||||
import { describeCommonTests } from './shared-tests';
|
import { describeCommonTests } from './shared-tests';
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import type {
|
|||||||
INodeTypes,
|
INodeTypes,
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
IRunData,
|
IRunData,
|
||||||
|
ITaskData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import type { ITaskData } from 'n8n-workflow';
|
|
||||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { ExecuteContext } from '../../execute-context';
|
import { ExecuteContext } from '../../execute-context';
|
||||||
|
|||||||
@@ -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
|
* Takes a buffer and converts it into the format n8n uses. It encodes the binary data as
|
||||||
* base64 and adds metadata.
|
* base64 and adds metadata.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
export async function prepareBinaryData(
|
export async function prepareBinaryData(
|
||||||
binaryData: Buffer | Readable,
|
binaryData: Buffer | Readable,
|
||||||
executionId: string,
|
executionId: string,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-shadow */
|
|
||||||
import { Logger } from '@n8n/backend-common';
|
import { Logger } from '@n8n/backend-common';
|
||||||
import type {
|
import type {
|
||||||
ClientOAuth2Options,
|
ClientOAuth2Options,
|
||||||
@@ -227,11 +227,10 @@ const getBeforeRedirectFn =
|
|||||||
axiosConfig: AxiosRequestConfig,
|
axiosConfig: AxiosRequestConfig,
|
||||||
proxyConfig: IHttpRequestOptions['proxy'] | string | undefined,
|
proxyConfig: IHttpRequestOptions['proxy'] | string | undefined,
|
||||||
) =>
|
) =>
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
(redirectedRequest: Record<string, any>) => {
|
(redirectedRequest: Record<string, any>) => {
|
||||||
const redirectAgentOptions = {
|
const redirectAgentOptions = {
|
||||||
...agentOptions,
|
...agentOptions,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
||||||
servername: redirectedRequest.hostname,
|
servername: redirectedRequest.hostname,
|
||||||
};
|
};
|
||||||
const redirectAgent = getAgentWithProxy({
|
const redirectAgent = getAgentWithProxy({
|
||||||
@@ -248,7 +247,6 @@ const getBeforeRedirectFn =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (axiosConfig.headers?.Authorization) {
|
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;
|
redirectedRequest.headers.Authorization = axiosConfig.headers.Authorization;
|
||||||
}
|
}
|
||||||
if (axiosConfig.auth) {
|
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) => {
|
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')) {
|
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);
|
form.append(key, value.value, value.options);
|
||||||
} else {
|
} else {
|
||||||
form.append(key, value);
|
form.append(key, value);
|
||||||
@@ -361,7 +356,6 @@ async function generateContentLengthHeader(config: AxiosRequestConfig) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const length = await new Promise<number>((res, rej) => {
|
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) => {
|
config.data.getLength((error: Error | null, dataLength: number) => {
|
||||||
if (error) rej(error);
|
if (error) rej(error);
|
||||||
else res(dataLength);
|
else res(dataLength);
|
||||||
@@ -372,7 +366,6 @@ async function generateContentLengthHeader(config: AxiosRequestConfig) {
|
|||||||
'content-length': length,
|
'content-length': length,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
||||||
Container.get(Logger).error('Unable to calculate form data length', { error });
|
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') {
|
if (typeof requestObject.body === 'string') {
|
||||||
axiosConfig.data = requestObject.body;
|
axiosConfig.data = requestObject.body;
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
const allData = Object.assign(requestObject.body || {}, requestObject.form || {}) as Record<
|
const allData = Object.assign(requestObject.body || {}, requestObject.form || {}) as Record<
|
||||||
string,
|
string,
|
||||||
string
|
string
|
||||||
@@ -441,9 +433,9 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
// replace the existing header with a new one that
|
// replace the existing header with a new one that
|
||||||
// contains the boundary property.
|
// contains the boundary property.
|
||||||
delete axiosConfig.headers?.[contentTypeHeaderKeyName!];
|
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();
|
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);
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers);
|
||||||
await generateContentLengthHeader(axiosConfig);
|
await generateContentLengthHeader(axiosConfig);
|
||||||
} else {
|
} else {
|
||||||
@@ -482,16 +474,16 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
axiosConfig.data = createFormDataObject(requestObject.formData as Record<string, unknown>);
|
axiosConfig.data = createFormDataObject(requestObject.formData as Record<string, unknown>);
|
||||||
}
|
}
|
||||||
// Mix in headers as FormData creates the boundary.
|
// 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();
|
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);
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, headers);
|
||||||
await generateContentLengthHeader(axiosConfig);
|
await generateContentLengthHeader(axiosConfig);
|
||||||
} else if (requestObject.body !== undefined) {
|
} else if (requestObject.body !== undefined) {
|
||||||
// If we have body and possibly form
|
// If we have body and possibly form
|
||||||
if (requestObject.form !== undefined && requestObject.body) {
|
if (requestObject.form !== undefined && requestObject.body) {
|
||||||
// merge both objects when exist.
|
// merge both objects when exist.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
||||||
requestObject.body = Object.assign(requestObject.body, requestObject.form);
|
requestObject.body = Object.assign(requestObject.body, requestObject.form);
|
||||||
}
|
}
|
||||||
axiosConfig.data = requestObject.body as FormData | GenericValue | GenericValue[];
|
axiosConfig.data = requestObject.body as FormData | GenericValue | GenericValue[];
|
||||||
@@ -559,7 +551,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
if (requestObject.auth !== undefined) {
|
if (requestObject.auth !== undefined) {
|
||||||
// Check support for sendImmediately
|
// Check support for sendImmediately
|
||||||
if (requestObject.auth.bearer !== undefined) {
|
if (requestObject.auth.bearer !== undefined) {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
||||||
Authorization: `Bearer ${requestObject.auth.bearer}`,
|
Authorization: `Bearer ${requestObject.auth.bearer}`,
|
||||||
});
|
});
|
||||||
@@ -567,9 +558,8 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
const authObj = requestObject.auth;
|
const authObj = requestObject.auth;
|
||||||
// Request accepts both user/username and pass/password
|
// Request accepts both user/username and pass/password
|
||||||
axiosConfig.auth = {
|
axiosConfig.auth = {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
username: (authObj.user || authObj.username) as string,
|
username: (authObj.user || authObj.username) as string,
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
password: (authObj.password || authObj.pass) as string,
|
password: (authObj.password || authObj.pass) as string,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -586,7 +576,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
.map((headerKey) => headerKey.toLowerCase())
|
.map((headerKey) => headerKey.toLowerCase())
|
||||||
.includes('accept');
|
.includes('accept');
|
||||||
if (!acceptHeaderExists) {
|
if (!acceptHeaderExists) {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
});
|
});
|
||||||
@@ -594,7 +583,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
}
|
}
|
||||||
if (requestObject.json === false || requestObject.json === undefined) {
|
if (requestObject.json === false || requestObject.json === undefined) {
|
||||||
// Prevent json parsing
|
// Prevent json parsing
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
||||||
axiosConfig.transformResponse = (res) => res;
|
axiosConfig.transformResponse = (res) => res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,7 +636,6 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
// as the service returns XML unless requested otherwise.
|
// as the service returns XML unless requested otherwise.
|
||||||
const allHeaders = axiosConfig.headers ? Object.keys(axiosConfig.headers) : [];
|
const allHeaders = axiosConfig.headers ? Object.keys(axiosConfig.headers) : [];
|
||||||
if (!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'accept')) {
|
if (!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'accept')) {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { accept: '*/*' });
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, { accept: '*/*' });
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -661,7 +649,7 @@ export async function parseRequestObject(requestObject: IRequestOptions) {
|
|||||||
// If we don't specify this here, axios will add
|
// If we don't specify this here, axios will add
|
||||||
// application/json; charset=utf-8
|
// application/json; charset=utf-8
|
||||||
// and this breaks a lot of stuff
|
// and this breaks a lot of stuff
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
||||||
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
axiosConfig.headers = Object.assign(axiosConfig.headers || {}, {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
});
|
});
|
||||||
@@ -771,7 +759,6 @@ export async function proxyRequestToAxios(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
export function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequestConfig {
|
export function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequestConfig {
|
||||||
// Destructure properties with the same name first.
|
// Destructure properties with the same name first.
|
||||||
const { headers, method, timeout, auth, proxy, url } = n8nRequest;
|
const { headers, method, timeout, auth, proxy, url } = n8nRequest;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const validateResourceMapperValue = (
|
|||||||
for (let i = 0; i < paramValueNames.length; i++) {
|
for (let i = 0; i < paramValueNames.length; i++) {
|
||||||
const key = paramValueNames[i];
|
const key = paramValueNames[i];
|
||||||
const resolvedValue = paramValues[key];
|
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);
|
const schemaEntry = schema.find((s) => s.id === key);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
// 1 means the output has run data
|
// 1 means the output has run data
|
||||||
// PD denotes that the node has pinned data
|
// PD denotes that the node has pinned data
|
||||||
|
|
||||||
import type { IPinData } from 'n8n-workflow';
|
import type { IPinData, IRunData } from 'n8n-workflow';
|
||||||
import { NodeConnectionTypes, type IRunData } from 'n8n-workflow';
|
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||||
|
|
||||||
import { createNodeData, toITaskData } from './helpers';
|
import { createNodeData, toITaskData } from './helpers';
|
||||||
import { DirectedGraph } from '../directed-graph';
|
import { DirectedGraph } from '../directed-graph';
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import type {
|
|||||||
ISourceData,
|
ISourceData,
|
||||||
IWaitingForExecution,
|
IWaitingForExecution,
|
||||||
IWaitingForExecutionSource,
|
IWaitingForExecutionSource,
|
||||||
|
IPinData,
|
||||||
|
IRunData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeConnectionTypes, type IPinData, type IRunData } from 'n8n-workflow';
|
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||||
|
|
||||||
import { createNodeData, toITaskData } from './helpers';
|
import { createNodeData, toITaskData } from './helpers';
|
||||||
import { DirectedGraph } from '../directed-graph';
|
import { DirectedGraph } from '../directed-graph';
|
||||||
|
|||||||
@@ -124,12 +124,12 @@ export class DirectedGraph {
|
|||||||
const newConnections: GraphConnection[] = [];
|
const newConnections: GraphConnection[] = [];
|
||||||
|
|
||||||
for (const incomingConnection of incomingConnections) {
|
for (const incomingConnection of incomingConnections) {
|
||||||
if (options.skipConnectionFn && options.skipConnectionFn(incomingConnection)) {
|
if (options.skipConnectionFn?.(incomingConnection)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const outgoingConnection of outgoingConnections) {
|
for (const outgoingConnection of outgoingConnections) {
|
||||||
if (options.skipConnectionFn && options.skipConnectionFn(outgoingConnection)) {
|
if (options.skipConnectionFn?.(outgoingConnection)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,6 @@ export function getSourceDataGroups(
|
|||||||
currentInputIndex++;
|
currentInputIndex++;
|
||||||
|
|
||||||
const connectionWithDataIndex = sortedConnectionsWithData.findIndex(
|
const connectionWithDataIndex = sortedConnectionsWithData.findIndex(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
||||||
(c) => c.inputIndex === currentInputIndex,
|
(c) => c.inputIndex === currentInputIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -137,7 +136,6 @@ export function getSourceDataGroups(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const connectionWithoutDataIndex = sortedConnectionsWithoutData.findIndex(
|
const connectionWithoutDataIndex = sortedConnectionsWithoutData.findIndex(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
||||||
(c) => c.inputIndex === currentInputIndex,
|
(c) => c.inputIndex === currentInputIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1178,7 +1178,6 @@ export class WorkflowExecute {
|
|||||||
const newInputData: ITaskDataConnections = {};
|
const newInputData: ITaskDataConnections = {};
|
||||||
for (const connectionType of Object.keys(inputData)) {
|
for (const connectionType of Object.keys(inputData)) {
|
||||||
newInputData[connectionType] = inputData[connectionType].map((input) => {
|
newInputData[connectionType] = inputData[connectionType].map((input) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
|
||||||
return input && input.slice(0, 1);
|
return input && input.slice(0, 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1558,7 +1557,7 @@ export class WorkflowExecute {
|
|||||||
if (waitBetweenTries !== 0) {
|
if (waitBetweenTries !== 0) {
|
||||||
// TODO: Improve that in the future and check if other nodes can
|
// TODO: Improve that in the future and check if other nodes can
|
||||||
// be executed in the meantime
|
// be executed in the meantime
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
@@ -1767,14 +1766,11 @@ export class WorkflowExecute {
|
|||||||
lineResult.json.$error !== undefined &&
|
lineResult.json.$error !== undefined &&
|
||||||
lineResult.json.$json !== undefined
|
lineResult.json.$json !== undefined
|
||||||
) {
|
) {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError;
|
lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError;
|
||||||
lineResult.json = {
|
lineResult.json = {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
error: (lineResult.json.$error as NodeApiError | NodeOperationError).message,
|
error: (lineResult.json.$error as NodeApiError | NodeOperationError).message,
|
||||||
};
|
};
|
||||||
} else if (lineResult.error !== undefined) {
|
} else if (lineResult.error !== undefined) {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
lineResult.json = { error: lineResult.error.message };
|
lineResult.json = { error: lineResult.error.message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1986,7 +1982,7 @@ export class WorkflowExecute {
|
|||||||
const parentNodes = workflow.getParentNodes(nodeName);
|
const parentNodes = workflow.getParentNodes(nodeName);
|
||||||
|
|
||||||
// Check if input nodes (of same run) got already executed
|
// 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));
|
const parentIsWaiting = parentNodes.some((value) => waitingNodes.includes(value));
|
||||||
if (parentIsWaiting) {
|
if (parentIsWaiting) {
|
||||||
// Execute node later as one of its dependencies is still outstanding
|
// Execute node later as one of its dependencies is still outstanding
|
||||||
@@ -2127,12 +2123,11 @@ export class WorkflowExecute {
|
|||||||
|
|
||||||
this.moveNodeMetadata();
|
this.moveNodeMetadata();
|
||||||
|
|
||||||
await hooks.runHook('workflowExecuteAfter', [fullRunData, newStaticData]).catch(
|
await hooks
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
.runHook('workflowExecuteAfter', [fullRunData, newStaticData])
|
||||||
(error) => {
|
.catch((error) => {
|
||||||
console.error('There was a problem running hook "workflowExecuteAfter"', error);
|
console.error('There was a problem running hook "workflowExecuteAfter"', error);
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (closeFunction) {
|
if (closeFunction) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const loadClassInIsolation = <T>(filePath: string, className: string) =>
|
|||||||
|
|
||||||
// Note: Skip the isolation because it breaks nock mocks in tests
|
// Note: Skip the isolation because it breaks nock mocks in tests
|
||||||
if (inTest) {
|
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;
|
return new (require(filePath)[className])() as T;
|
||||||
} else {
|
} else {
|
||||||
const script = new Script(`new (require('${filePath}').${className})()`);
|
const script = new Script(`new (require('${filePath}').${className})()`);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable complexity */
|
|
||||||
const check = (
|
const check = (
|
||||||
val: unknown,
|
val: unknown,
|
||||||
path = 'value',
|
path = 'value',
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ function augment<T>(value: T): T {
|
|||||||
if (value instanceof Date) return new Date(value.valueOf()) as T;
|
if (value instanceof Date) return new Date(value.valueOf()) as T;
|
||||||
if (value instanceof Uint8Array) return value.slice() 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;
|
if (Array.isArray(value)) return augmentArray(value) as T;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
||||||
return augmentObject(value) as T;
|
return augmentObject(value) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export abstract class NodeError extends ExecutionBaseError {
|
|||||||
if (typeof value === 'number') return value.toString();
|
if (typeof value === 'number') return value.toString();
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const resolvedErrors: string[] = value
|
const resolvedErrors: string[] = value
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
||||||
.map((jsonError) => {
|
.map((jsonError) => {
|
||||||
if (typeof jsonError === 'string') return jsonError;
|
if (typeof jsonError === 'string') return jsonError;
|
||||||
if (typeof jsonError === 'number') return jsonError.toString();
|
if (typeof jsonError === 'number') return jsonError.toString();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ExecutionBaseError } from './abstract/execution-base.error';
|
|
||||||
import type { IDataObject } from '../interfaces';
|
import type { IDataObject } from '../interfaces';
|
||||||
|
import { ExecutionBaseError } from './abstract/execution-base.error';
|
||||||
|
|
||||||
export interface ExpressionErrorOptions {
|
export interface ExpressionErrorOptions {
|
||||||
cause?: Error;
|
cause?: Error;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ExecutionBaseError } from './abstract/execution-base.error';
|
|
||||||
import type { INode } from '../interfaces';
|
import type { INode } from '../interfaces';
|
||||||
|
import { ExecutionBaseError } from './abstract/execution-base.error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for instantiating an operational error, e.g. a timeout error.
|
* Class for instantiating an operational error, e.g. a timeout error.
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export const PrototypeSanitizer: ASTAfterHook = (ast, dataNode) => {
|
|||||||
if (!node.computed) {
|
if (!node.computed) {
|
||||||
// This is static, so we're safe to error here
|
// This is static, so we're safe to error here
|
||||||
if (node.property.type !== 'Identifier') {
|
if (node.property.type !== 'Identifier') {
|
||||||
// eslint-disable-next-line n8n-local-rules/no-plain-errors
|
|
||||||
throw new ExpressionError(
|
throw new ExpressionError(
|
||||||
`Unknown property type ${node.property.type} while sanitising expression`,
|
`Unknown property type ${node.property.type} while sanitising expression`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ExpressionExtensionError } from './errors/expression-extension.error';
|
|||||||
import { ExpressionError } from './errors/expression.error';
|
import { ExpressionError } from './errors/expression.error';
|
||||||
import { evaluateExpression, setErrorHandler } from './expression-evaluator-proxy';
|
import { evaluateExpression, setErrorHandler } from './expression-evaluator-proxy';
|
||||||
import { sanitizer, sanitizerName } from './expression-sandboxing';
|
import { sanitizer, sanitizerName } from './expression-sandboxing';
|
||||||
|
import { isExpression } from './expressions/expression-helpers';
|
||||||
import { extend, extendOptional } from './extensions';
|
import { extend, extendOptional } from './extensions';
|
||||||
import { extendSyntax } from './extensions/expression-extension';
|
import { extendSyntax } from './extensions/expression-extension';
|
||||||
import { extendedFunctions } from './extensions/extended-functions';
|
import { extendedFunctions } from './extensions/extended-functions';
|
||||||
@@ -25,7 +26,6 @@ import type {
|
|||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
import type { Workflow } from './workflow';
|
import type { Workflow } from './workflow';
|
||||||
import { WorkflowDataProxy } from './workflow-data-proxy';
|
import { WorkflowDataProxy } from './workflow-data-proxy';
|
||||||
import { isExpression } from './expressions/expression-helpers';
|
|
||||||
|
|
||||||
const IS_FRONTEND_IN_DEV_MODE =
|
const IS_FRONTEND_IN_DEV_MODE =
|
||||||
typeof process === 'object' &&
|
typeof process === 'object' &&
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ export const extendTransform = (expression: string): { code: string } | undefine
|
|||||||
|
|
||||||
// This is to match behavior in our original expression evaluator (tmpl)
|
// This is to match behavior in our original expression evaluator (tmpl)
|
||||||
const globalIdentifier = types.builders.identifier(
|
const globalIdentifier = types.builders.identifier(
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
typeof window !== 'object' ? 'global' : 'window',
|
typeof window !== 'object' ? 'global' : 'window',
|
||||||
);
|
);
|
||||||
// We want to define all of our commonly used identifiers and member
|
// We want to define all of our commonly used identifiers and member
|
||||||
|
|||||||
@@ -893,7 +893,7 @@ type BaseExecutionFunctions = FunctionsBaseWithRequiredKeys<'getMode'> & {
|
|||||||
getInputSourceData(inputIndex?: number, connectionType?: NodeConnectionType): ISourceData;
|
getInputSourceData(inputIndex?: number, connectionType?: NodeConnectionType): ISourceData;
|
||||||
getExecutionCancelSignal(): AbortSignal | undefined;
|
getExecutionCancelSignal(): AbortSignal | undefined;
|
||||||
onExecutionCancellation(handler: () => unknown): void;
|
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
|
// TODO: Create later own type only for Config-Nodes
|
||||||
@@ -1002,7 +1002,7 @@ export type ISupplyDataFunctions = ExecuteFunctions.GetNodeParameterFn &
|
|||||||
getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData;
|
getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData;
|
||||||
getExecutionCancelSignal(): AbortSignal | undefined;
|
getExecutionCancelSignal(): AbortSignal | undefined;
|
||||||
onExecutionCancellation(handler: () => unknown): void;
|
onExecutionCancellation(handler: () => unknown): void;
|
||||||
logAiEvent(eventName: AiEvent, msg?: string | undefined): void;
|
logAiEvent(eventName: AiEvent, msg?: string): void;
|
||||||
cloneWith(replacements: {
|
cloneWith(replacements: {
|
||||||
runIndex: number;
|
runIndex: number;
|
||||||
inputData: INodeExecutionData[][];
|
inputData: INodeExecutionData[][];
|
||||||
@@ -1551,7 +1551,7 @@ export interface INodePropertyValueExtractorFunction {
|
|||||||
(
|
(
|
||||||
this: IExecuteSingleFunctions,
|
this: IExecuteSingleFunctions,
|
||||||
value: string | NodeParameterValue,
|
value: string | NodeParameterValue,
|
||||||
): Promise<string | NodeParameterValue> | (string | NodeParameterValue);
|
): Promise<string | NodeParameterValue> | string;
|
||||||
}
|
}
|
||||||
export type INodePropertyValueExtractor = INodePropertyValueExtractorRegex;
|
export type INodePropertyValueExtractor = INodePropertyValueExtractorRegex;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* 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/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||||
/* eslint-disable prefer-spread */
|
/* eslint-disable prefer-spread */
|
||||||
@@ -840,7 +840,6 @@ export function getNodeParameters(
|
|||||||
itemName
|
itemName
|
||||||
] as INodeParameters[]) {
|
] as INodeParameters[]) {
|
||||||
nodePropertyOptions = nodeProperties.options!.find(
|
nodePropertyOptions = nodeProperties.options!.find(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
||||||
(nodePropertyOptions) => nodePropertyOptions.name === itemName,
|
(nodePropertyOptions) => nodePropertyOptions.name === itemName,
|
||||||
) as INodePropertyCollection;
|
) as INodePropertyCollection;
|
||||||
|
|
||||||
@@ -875,7 +874,7 @@ export function getNodeParameters(
|
|||||||
tempNodeParameters = {};
|
tempNodeParameters = {};
|
||||||
|
|
||||||
// Get the options of the current item
|
// Get the options of the current item
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
||||||
const nodePropertyOptions = nodeProperties.options!.find(
|
const nodePropertyOptions = nodeProperties.options!.find(
|
||||||
(data) => data.name === itemName,
|
(data) => data.name === itemName,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const withIndefiniteArticle = (noun: string): string => {
|
|||||||
return `${article} ${noun}`;
|
return `${article} ${noun}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
function parseFilterConditionValues(
|
function parseFilterConditionValues(
|
||||||
condition: FilterConditionValue,
|
condition: FilterConditionValue,
|
||||||
options: FilterOptionsValue,
|
options: FilterOptionsValue,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-shadow */
|
|
||||||
|
|
||||||
import type { IDataObject, IObservableObject } from './interfaces';
|
import type { IDataObject, IObservableObject } from './interfaces';
|
||||||
|
|
||||||
|
|||||||
@@ -1030,7 +1030,7 @@ export class WorkflowDataProxy {
|
|||||||
const placeholdersDataInputData =
|
const placeholdersDataInputData =
|
||||||
inputData?.[NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
|
inputData?.[NodeConnectionTypes.AiTool]?.[0]?.[itemIndex].json;
|
||||||
|
|
||||||
if (Boolean(!placeholdersDataInputData)) {
|
if (!placeholdersDataInputData) {
|
||||||
throw new ExpressionError('No execution data available', {
|
throw new ExpressionError('No execution data available', {
|
||||||
runIndex,
|
runIndex,
|
||||||
itemIndex,
|
itemIndex,
|
||||||
|
|||||||
@@ -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-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
/* eslint-disable @typescript-eslint/no-for-in-array */
|
/* eslint-disable @typescript-eslint/no-for-in-array */
|
||||||
@@ -534,7 +533,7 @@ export class Workflow {
|
|||||||
}
|
}
|
||||||
connectionsByIndex =
|
connectionsByIndex =
|
||||||
this.connectionsByDestinationNode[nodeName][NodeConnectionTypes.Main][connectionIndex];
|
this.connectionsByDestinationNode[nodeName][NodeConnectionTypes.Main][connectionIndex];
|
||||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
||||||
connectionsByIndex?.forEach((connection) => {
|
connectionsByIndex?.forEach((connection) => {
|
||||||
if (checkedNodes.includes(connection.node)) {
|
if (checkedNodes.includes(connection.node)) {
|
||||||
// Node got checked already before
|
// Node got checked already before
|
||||||
@@ -730,7 +729,6 @@ export class Workflow {
|
|||||||
const toAdd = [...queue];
|
const toAdd = [...queue];
|
||||||
queue = [];
|
queue = [];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
||||||
toAdd.forEach((curr) => {
|
toAdd.forEach((curr) => {
|
||||||
if (visited[curr.name]) {
|
if (visited[curr.name]) {
|
||||||
visited[curr.name].indicies = dedupe(visited[curr.name].indicies.concat(curr.indicies));
|
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);
|
const outputs = NodeHelpers.getNodeOutputs(this, node, nodeType.description);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!!outputs.find(
|
outputs.find(
|
||||||
(output) =>
|
(output) =>
|
||||||
((output as INodeOutputConfiguration)?.type ?? output) !== NodeConnectionTypes.Main,
|
((output as INodeOutputConfiguration)?.type ?? output) !== NodeConnectionTypes.Main,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user