refactor: Consolidate redundant code in workflow execution-functions (no-changelog) (#4884)

* refactor: Consolidate redundant code in workflow interfaces (no-changelog)

* consolidate all execution-functions interfaces code

* move rawBody definition back

* address PR comments
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2022-12-23 18:27:07 +01:00
committed by GitHub
parent 2b1eb94906
commit 5cf70e1007
8 changed files with 342 additions and 1221 deletions

View File

@@ -4,6 +4,9 @@ import type * as express from 'express';
import type * as FormData from 'form-data';
import type { IncomingHttpHeaders } from 'http';
import type { URLSearchParams } from 'url';
import type { OptionsWithUri, OptionsWithUrl } from 'request';
import type { RequestPromiseOptions, RequestPromiseAPI } from 'request-promise-native';
import type { IDeferredPromise } from './DeferredPromise';
import type { Workflow } from './Workflow';
import type { WorkflowHooks } from './WorkflowHooks';
@@ -609,87 +612,6 @@ namespace ExecuteFunctions {
};
}
export type IExecuteFunctions = ExecuteFunctions.GetNodeParameterFn & {
continueOnFail(): boolean;
evaluateExpression(expression: string, itemIndex: number): NodeParameterValueType;
executeWorkflow(
workflowInfo: IExecuteWorkflowInfo,
inputData?: INodeExecutionData[],
): Promise<any>;
getContext(type: string): IContextObject;
getCredentials(type: string, itemIndex?: number): Promise<ICredentialDataDecryptedObject>;
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData[];
getInputSourceData(inputIndex?: number, inputName?: string): ISourceData;
getMode(): WorkflowExecuteMode;
getNode(): INode;
getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData;
getWorkflowStaticData(type: string): IDataObject;
getRestApiUrl(): string;
getTimezone(): string;
getExecuteData(): IExecuteData;
getWorkflow(): IWorkflowMetadata;
prepareOutputData(
outputData: INodeExecutionData[],
outputIndex?: number,
): Promise<INodeExecutionData[][]>;
putExecutionToWait(waitTill: Date): Promise<void>;
sendMessageToUI(message: any): void;
sendResponse(response: IExecuteResponsePromiseData): void;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
};
export interface IExecuteSingleFunctions {
continueOnFail(): boolean;
evaluateExpression(expression: string, itemIndex: number | undefined): NodeParameterValueType;
getContext(type: string): IContextObject;
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;
getInputSourceData(inputIndex?: number, inputName?: string): ISourceData;
getItemIndex(): number;
getMode(): WorkflowExecuteMode;
getNode(): INode;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
getRestApiUrl(): string;
getTimezone(): string;
getExecuteData(): IExecuteData;
getWorkflow(): IWorkflowMetadata;
getWorkflowDataProxy(): IWorkflowDataProxyData;
getWorkflowStaticData(type: string): IDataObject;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
}
export interface IExecutePaginationFunctions extends IExecuteSingleFunctions {
makeRoutingRequest(
this: IAllExecuteFunctions,
requestOptions: DeclarativeRestApiSettings.ResultOptions,
): Promise<INodeExecutionData[]>;
}
export interface IExecuteWorkflowInfo {
code?: IWorkflowBase;
id?: string;
@@ -702,13 +624,126 @@ export type ICredentialTestFunction = (
export interface ICredentialTestFunctions {
helpers: {
[key: string]: (...args: any[]) => any;
request: RequestPromiseAPI;
};
}
export interface ILoadOptionsFunctions {
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
export interface JsonHelperFunctions {
returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[];
}
export interface BinaryHelperFunctions {
prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise<IBinaryData>;
setBinaryDataBuffer(data: IBinaryData, binaryData: Buffer): Promise<IBinaryData>;
copyBinaryFile(filePath: string, fileName: string, mimeType?: string): Promise<IBinaryData>;
}
export interface RequestHelperFunctions {
request(uriOrObject: string | IDataObject | any, options?: IDataObject): Promise<any>;
requestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: OptionsWithUri | RequestPromiseOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any>;
httpRequest(requestOptions: IHttpRequestOptions): Promise<any>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any>;
requestOAuth1(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: OptionsWithUrl | RequestPromiseOptions,
): Promise<any>;
requestOAuth2(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: OptionsWithUri | RequestPromiseOptions,
oAuth2Options?: IOAuth2Options,
): Promise<any>;
}
export interface FunctionsBase {
getCredentials(type: string, itemIndex?: number): Promise<ICredentialDataDecryptedObject>;
getNode(): INode;
getWorkflow(): IWorkflowMetadata;
getWorkflowStaticData(type: string): IDataObject;
getTimezone(): string;
getRestApiUrl(): string;
getMode?: () => WorkflowExecuteMode;
getActivationMode?: () => WorkflowActivateMode;
}
type FunctionsBaseWithRequiredKeys<Keys extends keyof FunctionsBase> = FunctionsBase & {
[K in Keys]: NonNullable<FunctionsBase[K]>;
};
type BaseExecutionFunctions = FunctionsBaseWithRequiredKeys<'getMode'> & {
continueOnFail(): boolean;
evaluateExpression(expression: string, itemIndex: number): NodeParameterValueType;
getContext(type: string): IContextObject;
getExecuteData(): IExecuteData;
getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData;
getInputSourceData(inputIndex?: number, inputName?: string): ISourceData;
};
export type IExecuteFunctions = ExecuteFunctions.GetNodeParameterFn &
BaseExecutionFunctions & {
executeWorkflow(
workflowInfo: IExecuteWorkflowInfo,
inputData?: INodeExecutionData[],
): Promise<any>;
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData[];
prepareOutputData(
outputData: INodeExecutionData[],
outputIndex?: number,
): Promise<INodeExecutionData[][]>;
putExecutionToWait(waitTill: Date): Promise<void>;
sendMessageToUI(message: any): void;
sendResponse(response: IExecuteResponsePromiseData): void;
helpers: RequestHelperFunctions &
BinaryHelperFunctions &
JsonHelperFunctions & {
normalizeItems(items: INodeExecutionData | INodeExecutionData[]): INodeExecutionData[];
constructExecutionMetaData(
inputData: INodeExecutionData[],
options: { itemData: IPairedItemData | IPairedItemData[] },
): NodeExecutionWithMetadata[];
getBinaryDataBuffer(itemIndex: number, propertyName: string): Promise<Buffer>;
};
};
export interface IExecuteSingleFunctions extends BaseExecutionFunctions {
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;
getItemIndex(): number;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
helpers: RequestHelperFunctions &
BinaryHelperFunctions & {
getBinaryDataBuffer(propertyName: string, inputIndex?: number): Promise<Buffer>;
};
}
export interface IExecutePaginationFunctions extends IExecuteSingleFunctions {
makeRoutingRequest(
this: IAllExecuteFunctions,
requestOptions: DeclarativeRestApiSettings.ResultOptions,
): Promise<INodeExecutionData[]>;
}
export interface ILoadOptionsFunctions extends FunctionsBase {
getNodeParameter(
parameterName: string,
fallbackValue?: any,
@@ -719,134 +754,57 @@ export interface ILoadOptionsFunctions {
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object | undefined;
getCurrentNodeParameters(): INodeParameters | undefined;
getTimezone(): string;
getRestApiUrl(): string;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
// TODO: Remove from here. Add it only now to LoadOptions as many nodes do import
// from n8n-workflow instead of n8n-core
requestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: any,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<any>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: ((...args: any[]) => any) | undefined;
};
helpers: RequestHelperFunctions;
}
export interface IHookFunctions {
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
getMode(): WorkflowExecuteMode;
getActivationMode(): WorkflowActivateMode;
getNode(): INode;
getNodeWebhookUrl: (name: string) => string | undefined;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
getTimezone(): string;
getWebhookDescription(name: string): IWebhookDescription | undefined;
getWebhookName(): string;
getWorkflow(): IWorkflowMetadata;
getWorkflowStaticData(type: string): IDataObject;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
}
export interface IPollFunctions {
export interface IPollFunctions
extends FunctionsBaseWithRequiredKeys<'getMode' | 'getActivationMode'> {
__emit(
data: INodeExecutionData[][],
responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>,
donePromise?: IDeferredPromise<IRun>,
): void;
__emitError(error: Error, responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>): void;
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
getMode(): WorkflowExecuteMode;
getActivationMode(): WorkflowActivateMode;
getNode(): INode;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
getRestApiUrl(): string;
getTimezone(): string;
getWorkflow(): IWorkflowMetadata;
getWorkflowStaticData(type: string): IDataObject;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
helpers: RequestHelperFunctions & BinaryHelperFunctions & JsonHelperFunctions;
}
export interface ITriggerFunctions {
export interface ITriggerFunctions
extends FunctionsBaseWithRequiredKeys<'getMode' | 'getActivationMode'> {
emit(
data: INodeExecutionData[][],
responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>,
donePromise?: IDeferredPromise<IRun>,
): void;
emitError(error: Error, responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>): void;
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
getMode(): WorkflowExecuteMode;
getActivationMode(): WorkflowActivateMode;
getNode(): INode;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
getRestApiUrl(): string;
getTimezone(): string;
getWorkflow(): IWorkflowMetadata;
getWorkflowStaticData(type: string): IDataObject;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
helpers: RequestHelperFunctions & BinaryHelperFunctions & JsonHelperFunctions;
}
export interface IWebhookFunctions {
export interface IHookFunctions
extends FunctionsBaseWithRequiredKeys<'getMode' | 'getActivationMode'> {
getWebhookName(): string;
getWebhookDescription(name: string): IWebhookDescription | undefined;
getNodeWebhookUrl: (name: string) => string | undefined;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
options?: IGetNodeParameterOptions,
): NodeParameterValueType | object;
helpers: RequestHelperFunctions;
}
export interface IWebhookFunctions extends FunctionsBaseWithRequiredKeys<'getMode'> {
getBodyData(): IDataObject;
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
getHeaderData(): IncomingHttpHeaders;
getMode(): WorkflowExecuteMode;
getNode(): INode;
getNodeParameter(
parameterName: string,
fallbackValue?: any,
@@ -857,26 +815,12 @@ export interface IWebhookFunctions {
getQueryData(): object;
getRequestObject(): express.Request;
getResponseObject(): express.Response;
getTimezone(): string;
getWebhookName(): string;
getWorkflowStaticData(type: string): IDataObject;
getWorkflow(): IWorkflowMetadata;
prepareOutputData(
outputData: INodeExecutionData[],
outputIndex?: number,
): Promise<INodeExecutionData[][]>;
helpers: {
httpRequest(
requestOptions: IHttpRequestOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
httpRequestWithAuthentication(
this: IAllExecuteFunctions,
credentialsType: string,
requestOptions: IHttpRequestOptions,
additionalCredentialOptions?: IAdditionalCredentialOptions,
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
[key: string]: (...args: any[]) => any;
};
helpers: RequestHelperFunctions & BinaryHelperFunctions & JsonHelperFunctions;
}
export interface INodeCredentialsDetails {

View File

@@ -391,7 +391,7 @@ export class RoutingNode {
return returnData;
}
if (action.type === 'binaryData') {
responseData.body = Buffer.from(responseData.body as string);
const body = (responseData.body = Buffer.from(responseData.body as string));
let { destinationProperty } = action.properties;
destinationProperty = this.getParameterValue(
@@ -403,7 +403,7 @@ export class RoutingNode {
false,
) as string;
const binaryData = await executeSingleFunctions.helpers.prepareBinaryData(responseData.body);
const binaryData = await executeSingleFunctions.helpers.prepareBinaryData(body);
return inputData.map((item) => {
if (typeof item.json === 'string') {