mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
Add Webhook response node (#2254)
* ✨ Add Webhook-Response-Node * ⚡ Replace callback function with promise * ✨ Add support for Bull and binary-data * ✨ Add string response option * ⚡ Remove some comments * ✨ Make more generically possible & fix issue multi call in queue mode * ⚡ Fix startup and eslint issues * ⚡ Improvements to webhook response node and functionality * ⚡ Replace data with more generic type * ⚡ Make statusMessage optional * ⚡ Change parameter order * ⚡ Move Response Code underneath options * ⚡ Hide Response Code on Webhook node if mode responseNode got selected * ⚡ Minor improvements * ⚡ Add missing file and fix lint issue * ⚡ Fix some node linting issues * ⚡ Apply feedback * ⚡ Minor improvements
This commit is contained in:
14
packages/workflow/src/DeferredPromise.ts
Normal file
14
packages/workflow/src/DeferredPromise.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// From: https://gist.github.com/compulim/8b49b0a744a3eeb2205e2b9506201e50
|
||||
export interface IDeferredPromise<T> {
|
||||
promise: () => Promise<T>;
|
||||
reject: (error: Error) => void;
|
||||
resolve: (result: T) => void;
|
||||
}
|
||||
|
||||
export async function createDeferredPromise<T>(): Promise<IDeferredPromise<T>> {
|
||||
return new Promise<IDeferredPromise<T>>((resolveCreate) => {
|
||||
const promise = new Promise<T>((resolve, reject) => {
|
||||
resolveCreate({ promise: async () => promise, resolve, reject });
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
import * as express from 'express';
|
||||
import * as FormData from 'form-data';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { IDeferredPromise } from './DeferredPromise';
|
||||
import { Workflow } from './Workflow';
|
||||
import { WorkflowHooks } from './WorkflowHooks';
|
||||
import { WorkflowOperationError } from './WorkflowErrors';
|
||||
@@ -208,6 +209,9 @@ export interface IDataObject {
|
||||
[key: string]: GenericValue | IDataObject | GenericValue[] | IDataObject[];
|
||||
}
|
||||
|
||||
// export type IExecuteResponsePromiseData = IDataObject;
|
||||
export type IExecuteResponsePromiseData = IDataObject | IN8nHttpFullResponse;
|
||||
|
||||
export interface INodeTypeNameVersion {
|
||||
name: string;
|
||||
version: number;
|
||||
@@ -324,13 +328,13 @@ export interface IHttpRequestOptions {
|
||||
json?: boolean;
|
||||
}
|
||||
|
||||
export type IN8nHttpResponse = IDataObject | Buffer | GenericValue | GenericValue[];
|
||||
export type IN8nHttpResponse = IDataObject | Buffer | GenericValue | GenericValue[] | null;
|
||||
|
||||
export interface IN8nHttpFullResponse {
|
||||
body: IN8nHttpResponse;
|
||||
headers: IDataObject;
|
||||
statusCode: number;
|
||||
statusMessage: string;
|
||||
statusMessage?: string;
|
||||
}
|
||||
|
||||
export interface IExecuteFunctions {
|
||||
@@ -371,7 +375,8 @@ export interface IExecuteFunctions {
|
||||
outputIndex?: number,
|
||||
): Promise<INodeExecutionData[][]>;
|
||||
putExecutionToWait(waitTill: Date): Promise<void>;
|
||||
sendMessageToUI(message: any): void;
|
||||
sendMessageToUI(message: any): void; // tslint:disable-line:no-any
|
||||
sendResponse(response: IExecuteResponsePromiseData): void; // tslint:disable-line:no-any
|
||||
helpers: {
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
@@ -492,7 +497,10 @@ export interface IPollFunctions {
|
||||
}
|
||||
|
||||
export interface ITriggerFunctions {
|
||||
emit(data: INodeExecutionData[][]): void;
|
||||
emit(
|
||||
data: INodeExecutionData[][],
|
||||
responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>,
|
||||
): void;
|
||||
getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined>;
|
||||
getMode(): WorkflowExecuteMode;
|
||||
getActivationMode(): WorkflowActivateMode;
|
||||
@@ -975,6 +983,7 @@ export interface IWorkflowExecuteHooks {
|
||||
nodeExecuteBefore?: Array<(nodeName: string) => Promise<void>>;
|
||||
workflowExecuteAfter?: Array<(data: IRun, newStaticData: IDataObject) => Promise<void>>;
|
||||
workflowExecuteBefore?: Array<(workflow: Workflow, data: IRunExecutionData) => Promise<void>>;
|
||||
sendResponse?: Array<(response: IExecuteResponsePromiseData) => Promise<void>>;
|
||||
}
|
||||
|
||||
export interface IWorkflowExecuteAdditionalData {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
import {
|
||||
Expression,
|
||||
IConnections,
|
||||
IDeferredPromise,
|
||||
IExecuteResponsePromiseData,
|
||||
IGetExecuteTriggerFunctions,
|
||||
INode,
|
||||
INodeExecuteFunctions,
|
||||
@@ -946,10 +948,23 @@ export class Workflow {
|
||||
|
||||
// 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);
|
||||
triggerFunctions.emit = (
|
||||
(resolveEmit) =>
|
||||
(
|
||||
data: INodeExecutionData[][],
|
||||
responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>,
|
||||
) => {
|
||||
additionalData.hooks!.hookFunctions.sendResponse = [
|
||||
async (response: IExecuteResponsePromiseData): Promise<void> => {
|
||||
if (responsePromise) {
|
||||
responsePromise.resolve(response);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
resolveEmit(data);
|
||||
}
|
||||
)(resolve);
|
||||
});
|
||||
|
||||
return triggerResponse;
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as LoggerProxy from './LoggerProxy';
|
||||
import * as NodeHelpers from './NodeHelpers';
|
||||
import * as ObservableObject from './ObservableObject';
|
||||
|
||||
export * from './DeferredPromise';
|
||||
export * from './Interfaces';
|
||||
export * from './Expression';
|
||||
export * from './NodeErrors';
|
||||
|
||||
Reference in New Issue
Block a user