mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 11:49:59 +00:00
✨ Updated node design and node versioning (#1961)
* ⚡ introduce versioned nodes * Export versioned nodes for separate process run * Add bse node for versioned nodes * fix node name for versioned nodes * extend node from nodeVersionedType * improve nodes base and flow to FE * revert lib es2019 to es2017 * include version in key to prevent duplicate key * handle type versions on FE * clean up * cleanup nodes base * add type versions in getNodeParameterOptions * cleanup * code review * code review + add default version to node type description * remove node default types from store * 💄 cleanups * Draft for migrated Mattermost node * First version of Mattermost node versioned according to node standards * Correcting deactivate operations name to match currently used one * ✨ Create utility types * ⚡ Simplify Mattermost types * ⚡ Rename exports for consistency * ⚡ Type channel properties * ⚡ Type message properties * ⚡ Type reaction properties * ⚡ Type user properties * ⚡ Add type import to router * 🐛 Add missing key * 🔨 Adjust typo in operation name * 🔨 Inline exports for channel properties * 🔨 Inline exports for message properties * 🔨 Inline exports for reaction properties * 🔨 Inline exports for user properties * 🔨 Inline exports for load options * 👕 Fix lint issue * 🔨 Inline export for description * 🔨 Rename descriptions for clarity * 🔨 Refactor imports/exports for methods * 🔨 Refactor latest version retrieval * 🔥 Remove unneeded else clause When the string literal union is exhausted, the resource key becomes never, so TS disallows wrong key usage. * ✨ Add overloads to getNodeParameter * ⚡ Improve overload * 🔥 Remove superfluous INodeVersions type * 🔨 Relocate pre-existing interface * 🔥 Remove JSDoc arg descriptions * ⚡ Minor reformatting in transport file * ⚡ Fix API call function type * Created first draft for Axios requests * Working version of mattermost node with Axios * Work in progress for replacing request library * Improvements to request translations * Fixed sending files via multipart / form-data * Fixing translation from request to axios and loading node parameter options * Improved typing for new http helper * Added ignore any for specific lines for linting * Fixed follow redirects changes on http request node and manual execution of previously existing workflow with older node versions * Adding default headers according to body on httpRequest helper * Spec error handling and fixed workflows with older node versions * Showcase how to export errors in a standard format * Merging master * Refactored mattermost node to keep files in a uniform structure. Also fix bugs with merges * Reverting changes to http request node * Changed nullish comparison and removed repeated code from nodes * Renamed queryString back to qs and simplified node output * Simplified some comparisons * Changed header names to be uc first * Added default user agent to requests and patch http method support * Fixed indentation, remove unnecessary file and console log * Fixed mattermost node name * Fixed lint issues * Further fix linting issues * Further fix lint issues * Fixed http request helper's return type Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import * as express from 'express';
|
||||
import * as FormData from 'form-data';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { Workflow } from './Workflow';
|
||||
import { WorkflowHooks } from './WorkflowHooks';
|
||||
import { WorkflowOperationError } from './WorkflowErrors';
|
||||
@@ -191,6 +193,11 @@ export interface IDataObject {
|
||||
[key: string]: GenericValue | IDataObject | GenericValue[] | IDataObject[];
|
||||
}
|
||||
|
||||
export interface INodeTypeNameVersion {
|
||||
name: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface IGetExecutePollFunctions {
|
||||
(
|
||||
workflow: Workflow,
|
||||
@@ -274,6 +281,43 @@ export interface IExecuteContextData {
|
||||
[key: string]: IContextObject;
|
||||
}
|
||||
|
||||
export interface IHttpRequestOptions {
|
||||
url: string;
|
||||
headers?: IDataObject;
|
||||
method?: 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT';
|
||||
body?: FormData | GenericValue | GenericValue[] | Buffer | URLSearchParams;
|
||||
qs?: IDataObject;
|
||||
arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma';
|
||||
auth?: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
disableFollowRedirect?: boolean;
|
||||
encoding?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream';
|
||||
skipSslCertificateValidation?: boolean;
|
||||
returnFullResponse?: boolean;
|
||||
proxy?: {
|
||||
host: string;
|
||||
port: number;
|
||||
auth?: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
protocol?: string;
|
||||
};
|
||||
timeout?: number;
|
||||
json?: boolean;
|
||||
}
|
||||
|
||||
export type IN8nHttpResponse = IDataObject | Buffer | GenericValue | GenericValue[];
|
||||
|
||||
export interface IN8nHttpFullResponse {
|
||||
body: IN8nHttpResponse;
|
||||
headers: IDataObject;
|
||||
statusCode: number;
|
||||
statusMessage: string;
|
||||
}
|
||||
|
||||
export interface IExecuteFunctions {
|
||||
continueOnFail(): boolean;
|
||||
evaluateExpression(
|
||||
@@ -292,6 +336,11 @@ export interface IExecuteFunctions {
|
||||
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData[];
|
||||
getMode(): WorkflowExecuteMode;
|
||||
getNode(): INode;
|
||||
getNodeParameter<T extends { resource: string }>(
|
||||
parameterName: 'resource',
|
||||
itemIndex?: number,
|
||||
): T['resource'];
|
||||
// getNodeParameter(parameterName: 'operation', itemIndex?: number): string;
|
||||
getNodeParameter(
|
||||
parameterName: string,
|
||||
itemIndex: number,
|
||||
@@ -309,7 +358,10 @@ export interface IExecuteFunctions {
|
||||
putExecutionToWait(waitTill: Date): Promise<void>;
|
||||
sendMessageToUI(message: any): void; // tslint:disable-line:no-any
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -334,7 +386,10 @@ export interface IExecuteSingleFunctions {
|
||||
getWorkflowDataProxy(): IWorkflowDataProxyData;
|
||||
getWorkflowStaticData(type: string): IDataObject;
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -369,7 +424,10 @@ export interface ILoadOptionsFunctions {
|
||||
getTimezone(): string;
|
||||
getRestApiUrl(): string;
|
||||
helpers: {
|
||||
[key: string]: ((...args: any[]) => any) | undefined;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: ((...args: any[]) => any) | undefined; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -389,7 +447,10 @@ export interface IHookFunctions {
|
||||
getWorkflow(): IWorkflowMetadata;
|
||||
getWorkflowStaticData(type: string): IDataObject;
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -408,7 +469,10 @@ export interface IPollFunctions {
|
||||
getWorkflow(): IWorkflowMetadata;
|
||||
getWorkflowStaticData(type: string): IDataObject;
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -427,7 +491,10 @@ export interface ITriggerFunctions {
|
||||
getWorkflow(): IWorkflowMetadata;
|
||||
getWorkflowStaticData(type: string): IDataObject;
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -455,7 +522,10 @@ export interface IWebhookFunctions {
|
||||
outputIndex?: number,
|
||||
): Promise<INodeExecutionData[][]>;
|
||||
helpers: {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
httpRequest(
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IN8nHttpResponse | IN8nHttpFullResponse>;
|
||||
[key: string]: (...args: any[]) => any; // tslint:disable-line:no-any
|
||||
};
|
||||
}
|
||||
|
||||
@@ -496,12 +566,10 @@ export interface IBinaryKeyData {
|
||||
}
|
||||
|
||||
export interface INodeExecutionData {
|
||||
[key: string]: IDataObject | IBinaryKeyData | undefined;
|
||||
// TODO: Rename this one as json does not really fit as it is not json (which is a string) it is actually a JS object
|
||||
[key: string]: IDataObject | IBinaryKeyData | NodeApiError | NodeOperationError | undefined;
|
||||
json: IDataObject;
|
||||
// json: object;
|
||||
// json?: object;
|
||||
binary?: IBinaryKeyData;
|
||||
error?: NodeApiError | NodeOperationError;
|
||||
}
|
||||
|
||||
export interface INodeExecuteFunctions {
|
||||
@@ -557,10 +625,10 @@ export interface INodePropertyTypeOptions {
|
||||
|
||||
export interface IDisplayOptions {
|
||||
hide?: {
|
||||
[key: string]: NodeParameterValue[];
|
||||
[key: string]: NodeParameterValue[] | undefined;
|
||||
};
|
||||
show?: {
|
||||
[key: string]: NodeParameterValue[];
|
||||
[key: string]: NodeParameterValue[] | undefined;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -634,6 +702,14 @@ export interface INodeType {
|
||||
};
|
||||
}
|
||||
|
||||
export interface INodeVersionedType {
|
||||
nodeVersions: {
|
||||
[key: number]: INodeType;
|
||||
};
|
||||
currentVersion: number;
|
||||
description: INodeTypeBaseDescription;
|
||||
getNodeType: (version?: number) => INodeType;
|
||||
}
|
||||
export interface NodeCredentialTestResult {
|
||||
status: 'OK' | 'Error';
|
||||
message: string;
|
||||
@@ -684,15 +760,21 @@ export interface IWorfklowIssues {
|
||||
[key: string]: INodeIssues;
|
||||
}
|
||||
|
||||
export interface INodeTypeDescription {
|
||||
export interface INodeTypeBaseDescription {
|
||||
displayName: string;
|
||||
name: string;
|
||||
icon?: string;
|
||||
group: string[];
|
||||
version: number;
|
||||
description: string;
|
||||
defaults: INodeParameters;
|
||||
documentationUrl?: string;
|
||||
subtitle?: string;
|
||||
defaultVersion?: number;
|
||||
codex?: CodexData;
|
||||
}
|
||||
|
||||
export interface INodeTypeDescription extends INodeTypeBaseDescription {
|
||||
version: number;
|
||||
defaults: INodeParameters;
|
||||
inputs: string[];
|
||||
inputNames?: string[];
|
||||
outputs: string[];
|
||||
@@ -701,14 +783,12 @@ export interface INodeTypeDescription {
|
||||
credentials?: INodeCredentialDescription[];
|
||||
maxNodes?: number; // How many nodes of that type can be created in a workflow
|
||||
polling?: boolean;
|
||||
subtitle?: string;
|
||||
hooks?: {
|
||||
[key: string]: INodeHookDescription[] | undefined;
|
||||
activate?: INodeHookDescription[];
|
||||
deactivate?: INodeHookDescription[];
|
||||
};
|
||||
webhooks?: IWebhookDescription[];
|
||||
codex?: CodexData;
|
||||
}
|
||||
|
||||
export interface INodeHookDescription {
|
||||
@@ -777,13 +857,14 @@ export type WebhookResponseMode = 'onReceived' | 'lastNode';
|
||||
export interface INodeTypes {
|
||||
nodeTypes: INodeTypeData;
|
||||
init(nodeTypes?: INodeTypeData): Promise<void>;
|
||||
getAll(): INodeType[];
|
||||
getByName(nodeType: string): INodeType | undefined;
|
||||
getAll(): Array<INodeType | INodeVersionedType>;
|
||||
getByName(nodeType: string): INodeType | INodeVersionedType | undefined;
|
||||
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined;
|
||||
}
|
||||
|
||||
export interface INodeTypeData {
|
||||
[key: string]: {
|
||||
type: INodeType;
|
||||
type: INodeType | INodeVersionedType;
|
||||
sourcePath: string;
|
||||
};
|
||||
}
|
||||
@@ -949,3 +1030,19 @@ export type CodexData = {
|
||||
export type JsonValue = string | number | boolean | null | JsonObject | JsonValue[];
|
||||
|
||||
export type JsonObject = { [key: string]: JsonValue };
|
||||
|
||||
export type AllEntities<M> = M extends { [key: string]: string } ? Entity<M, keyof M> : never;
|
||||
|
||||
export type Entity<M, K> = K extends keyof M ? { resource: K; operation: M[K] } : never;
|
||||
|
||||
export type PropertiesOf<M extends { resource: string; operation: string }> = Array<
|
||||
Omit<INodeProperties, 'displayOptions'> & {
|
||||
displayOptions?: {
|
||||
[key in 'show' | 'hide']?: {
|
||||
resource?: Array<M['resource']>;
|
||||
operation?: Array<M['operation']>;
|
||||
[otherKey: string]: NodeParameterValue[] | undefined;
|
||||
};
|
||||
};
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
@@ -23,6 +26,7 @@ import {
|
||||
INodeProperties,
|
||||
INodePropertyCollection,
|
||||
INodeType,
|
||||
INodeVersionedType,
|
||||
IParameterDependencies,
|
||||
IRunExecutionData,
|
||||
IWebhookData,
|
||||
@@ -41,7 +45,7 @@ import { Workflow } from './Workflow';
|
||||
* @param {INodeType} nodeType
|
||||
* @returns
|
||||
*/
|
||||
export function getSpecialNodeParameters(nodeType: INodeType) {
|
||||
export function getSpecialNodeParameters(nodeType: INodeType): INodeProperties[] {
|
||||
if (nodeType.description.polling === true) {
|
||||
return [
|
||||
{
|
||||
@@ -296,7 +300,7 @@ export function displayParameter(
|
||||
|
||||
if (
|
||||
values.length === 0 ||
|
||||
!parameter.displayOptions.show[propertyName].some((v) => values.includes(v))
|
||||
!parameter.displayOptions.show[propertyName]!.some((v) => values.includes(v))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -323,7 +327,7 @@ export function displayParameter(
|
||||
|
||||
if (
|
||||
values.length !== 0 &&
|
||||
parameter.displayOptions.hide[propertyName].some((v) => values.includes(v))
|
||||
parameter.displayOptions.hide[propertyName]!.some((v) => values.includes(v))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -844,7 +848,7 @@ export function getNodeWebhooks(
|
||||
return [];
|
||||
}
|
||||
|
||||
const nodeType = workflow.nodeTypes.getByName(node.type) as INodeType;
|
||||
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType;
|
||||
|
||||
if (nodeType.description.webhooks === undefined) {
|
||||
// Node does not have any webhooks so return
|
||||
@@ -940,7 +944,7 @@ export function getNodeWebhooksBasic(workflow: Workflow, node: INode): IWebhookD
|
||||
return [];
|
||||
}
|
||||
|
||||
const nodeType = workflow.nodeTypes.getByName(node.type) as INodeType;
|
||||
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType;
|
||||
|
||||
if (nodeType.description.webhooks === undefined) {
|
||||
// Node does not have any webhooks so return
|
||||
@@ -1385,3 +1389,27 @@ export function mergeNodeProperties(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getVersionedTypeNode(
|
||||
object: INodeVersionedType | INodeType,
|
||||
version?: number,
|
||||
): INodeType {
|
||||
if (isNodeTypeVersioned(object)) {
|
||||
return (object as INodeVersionedType).getNodeType(version);
|
||||
}
|
||||
return object as INodeType;
|
||||
}
|
||||
|
||||
export function getVersionedTypeNodeAll(object: INodeVersionedType | INodeType): INodeType[] {
|
||||
if (isNodeTypeVersioned(object)) {
|
||||
return Object.values((object as INodeVersionedType).nodeVersions).map((element) => {
|
||||
element.description.name = object.description.name;
|
||||
return element;
|
||||
});
|
||||
}
|
||||
return [object as INodeType];
|
||||
}
|
||||
|
||||
export function isNodeTypeVersioned(object: INodeVersionedType | INodeType): boolean {
|
||||
return !!('getNodeType' in object);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
@@ -85,7 +88,8 @@ export class Workflow {
|
||||
let nodeType: INodeType | undefined;
|
||||
for (const node of parameters.nodes) {
|
||||
this.nodes[node.name] = node;
|
||||
nodeType = this.nodeTypes.getByName(node.type);
|
||||
|
||||
nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType === undefined) {
|
||||
// Go on to next node when its type is not known.
|
||||
@@ -197,7 +201,7 @@ export class Workflow {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeType = this.nodeTypes.getByName(node.type);
|
||||
nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType === undefined) {
|
||||
// Type is not known so check is not possible
|
||||
@@ -241,7 +245,7 @@ export class Workflow {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeType = this.nodeTypes.getByName(node.type);
|
||||
nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType === undefined) {
|
||||
// Node type is not known
|
||||
@@ -342,7 +346,7 @@ export class Workflow {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeType = this.nodeTypes.getByName(node.type);
|
||||
nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType !== undefined && checkFunction(nodeType)) {
|
||||
returnNodes.push(node);
|
||||
@@ -712,7 +716,7 @@ export class Workflow {
|
||||
if (node === null) {
|
||||
return undefined;
|
||||
}
|
||||
const nodeType = this.nodeTypes.getByName(node.type) as INodeType;
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType;
|
||||
if (nodeType.description.outputs.length === 1) {
|
||||
// If the parent node has only one output, it can only be connected
|
||||
// to that one. So no further checking is required.
|
||||
@@ -787,7 +791,8 @@ export class Workflow {
|
||||
let nodeType: INodeType;
|
||||
for (const nodeName of nodeNames) {
|
||||
node = this.nodes[nodeName];
|
||||
nodeType = this.nodeTypes.getByName(node.type) as INodeType;
|
||||
|
||||
nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType;
|
||||
|
||||
if (nodeType.trigger !== undefined || nodeType.poll !== undefined) {
|
||||
if (node.disabled === true) {
|
||||
@@ -860,7 +865,7 @@ export class Workflow {
|
||||
isTest?: boolean,
|
||||
): Promise<boolean | undefined> {
|
||||
const node = this.getNode(webhookData.node) as INode;
|
||||
const nodeType = this.nodeTypes.getByName(node.type) as INodeType;
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType;
|
||||
|
||||
if (nodeType.webhookMethods === undefined) {
|
||||
return;
|
||||
@@ -907,7 +912,7 @@ export class Workflow {
|
||||
): Promise<ITriggerResponse | undefined> {
|
||||
const triggerFunctions = getTriggerFunctions(this, node, additionalData, mode, activation);
|
||||
|
||||
const nodeType = this.nodeTypes.getByName(node.type);
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType === undefined) {
|
||||
throw new Error(`The node type "${node.type}" of node "${node.name}" is not known.`);
|
||||
@@ -947,11 +952,12 @@ export class Workflow {
|
||||
* @returns
|
||||
* @memberof Workflow
|
||||
*/
|
||||
|
||||
async runPoll(
|
||||
node: INode,
|
||||
pollFunctions: IPollFunctions,
|
||||
): Promise<INodeExecutionData[][] | null> {
|
||||
const nodeType = this.nodeTypes.getByName(node.type);
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
|
||||
if (nodeType === undefined) {
|
||||
throw new Error(`The node type "${node.type}" of node "${node.name}" is not known.`);
|
||||
@@ -984,7 +990,7 @@ export class Workflow {
|
||||
nodeExecuteFunctions: INodeExecuteFunctions,
|
||||
mode: WorkflowExecuteMode,
|
||||
): Promise<IWebhookResponseData> {
|
||||
const nodeType = this.nodeTypes.getByName(node.type);
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
if (nodeType === undefined) {
|
||||
throw new Error(`The type of the webhook node "${node.name}" is not known.`);
|
||||
} else if (nodeType.webhook === undefined) {
|
||||
@@ -1036,7 +1042,7 @@ export class Workflow {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const nodeType = this.nodeTypes.getByName(node.type);
|
||||
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
if (nodeType === undefined) {
|
||||
throw new Error(`Node type "${node.type}" is not known so can not run it!`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user