mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(core): Remove NodeExecutionOutput. Add execution hints directly to the context (#13111)
This commit is contained in:
parent
5dddf772cf
commit
dbb9475b7b
|
@ -36,7 +36,6 @@ import {
|
|||
ApplicationError,
|
||||
createDeferredPromise,
|
||||
NodeConnectionType,
|
||||
NodeExecutionOutput,
|
||||
NodeHelpers,
|
||||
Workflow,
|
||||
} from 'n8n-workflow';
|
||||
|
@ -246,18 +245,6 @@ describe('WorkflowExecute', () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('WorkflowExecute, NodeExecutionOutput type test', () => {
|
||||
//TODO Add more tests here when execution hints are added to some node types
|
||||
const nodeExecutionOutput = new NodeExecutionOutput(
|
||||
[[{ json: { data: 123 } }]],
|
||||
[{ message: 'TEXT HINT' }],
|
||||
);
|
||||
|
||||
expect(nodeExecutionOutput).toBeInstanceOf(NodeExecutionOutput);
|
||||
expect(nodeExecutionOutput[0][0].json.data).toEqual(123);
|
||||
expect(nodeExecutionOutput.getHints()[0].message).toEqual('TEXT HINT');
|
||||
});
|
||||
|
||||
describe('runPartialWorkflow2', () => {
|
||||
// Dirty ►
|
||||
// ┌───────┐1 ┌─────┐1 ┌─────┐
|
||||
|
|
|
@ -11,6 +11,7 @@ import type {
|
|||
IRunExecutionData,
|
||||
ITaskDataConnections,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
NodeExecutionHint,
|
||||
Result,
|
||||
Workflow,
|
||||
WorkflowExecuteMode,
|
||||
|
@ -51,6 +52,8 @@ export class ExecuteContext extends BaseExecuteContext implements IExecuteFuncti
|
|||
|
||||
readonly getNodeParameter: IExecuteFunctions['getNodeParameter'];
|
||||
|
||||
readonly hints: NodeExecutionHint[] = [];
|
||||
|
||||
constructor(
|
||||
workflow: Workflow,
|
||||
node: INode,
|
||||
|
@ -210,4 +213,8 @@ export class ExecuteContext extends BaseExecuteContext implements IExecuteFuncti
|
|||
getParentCallbackManager(): CallbackManager | undefined {
|
||||
return this.additionalData.parentCallbackManager;
|
||||
}
|
||||
|
||||
addExecutionHints(...hints: NodeExecutionHint[]) {
|
||||
this.hints.push(...hints);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ import {
|
|||
NodeHelpers,
|
||||
NodeConnectionType,
|
||||
ApplicationError,
|
||||
NodeExecutionOutput,
|
||||
sleep,
|
||||
ExecutionCancelledError,
|
||||
Node,
|
||||
|
@ -1101,7 +1100,7 @@ export class WorkflowExecute {
|
|||
});
|
||||
}
|
||||
|
||||
return { data };
|
||||
return { data, hints: context.hints };
|
||||
} else if (nodeType.poll) {
|
||||
if (mode === 'manual') {
|
||||
// In manual mode run the poll function
|
||||
|
@ -1507,10 +1506,8 @@ export class WorkflowExecute {
|
|||
tryIndex++;
|
||||
}
|
||||
|
||||
if (nodeSuccessData instanceof NodeExecutionOutput) {
|
||||
const hints = (nodeSuccessData as NodeExecutionOutput).getHints();
|
||||
|
||||
executionHints.push(...hints);
|
||||
if (runNodeData.hints?.length) {
|
||||
executionHints.push(...runNodeData.hints);
|
||||
}
|
||||
|
||||
if (nodeSuccessData && executionData.node.onError === 'continueErrorOutput') {
|
||||
|
|
|
@ -165,7 +165,8 @@ export class Code implements INodeType {
|
|||
standardizeOutput(item.json);
|
||||
}
|
||||
|
||||
return addPostExecutionWarning(items, inputDataItems?.length);
|
||||
addPostExecutionWarning(this, items, inputDataItems?.length);
|
||||
return [items];
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -201,6 +202,7 @@ export class Code implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
return addPostExecutionWarning(returnData, inputDataItems?.length);
|
||||
addPostExecutionWarning(this, returnData, inputDataItems?.length);
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,46 @@
|
|||
import type { INodeExecutionData } from 'n8n-workflow';
|
||||
import { NodeExecutionOutput } from 'n8n-workflow';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
|
||||
import { addPostExecutionWarning } from '../utils';
|
||||
|
||||
describe('addPostExecutionWarning', () => {
|
||||
const context = mock<IExecuteFunctions>();
|
||||
const inputItemsLength = 2;
|
||||
|
||||
it('should return a NodeExecutionOutput warning when returnData length differs from inputItemsLength', () => {
|
||||
beforeEach(() => jest.resetAllMocks());
|
||||
|
||||
it('should add execution hints when returnData length differs from inputItemsLength', () => {
|
||||
const returnData: INodeExecutionData[] = [{ json: {}, pairedItem: 0 }];
|
||||
|
||||
const result = addPostExecutionWarning(returnData, inputItemsLength);
|
||||
addPostExecutionWarning(context, returnData, inputItemsLength);
|
||||
|
||||
expect(result).toBeInstanceOf(NodeExecutionOutput);
|
||||
expect((result as NodeExecutionOutput)?.getHints()).toEqual([
|
||||
{
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
},
|
||||
]);
|
||||
expect(context.addExecutionHints).toHaveBeenCalledWith({
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a NodeExecutionOutput warning when any item has undefined pairedItem', () => {
|
||||
it('should add execution hints when any item has undefined pairedItem', () => {
|
||||
const returnData: INodeExecutionData[] = [{ json: {}, pairedItem: 0 }, { json: {} }];
|
||||
|
||||
const result = addPostExecutionWarning(returnData, inputItemsLength);
|
||||
addPostExecutionWarning(context, returnData, inputItemsLength);
|
||||
|
||||
expect(result).toBeInstanceOf(NodeExecutionOutput);
|
||||
expect((result as NodeExecutionOutput)?.getHints()).toEqual([
|
||||
{
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
},
|
||||
]);
|
||||
expect(context.addExecutionHints).toHaveBeenCalledWith({
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return returnData array when all items match inputItemsLength and have defined pairedItem', () => {
|
||||
it('should not add execution hints when all items match inputItemsLength and have defined pairedItem', () => {
|
||||
const returnData: INodeExecutionData[] = [
|
||||
{ json: {}, pairedItem: 0 },
|
||||
{ json: {}, pairedItem: 1 },
|
||||
];
|
||||
|
||||
const result = addPostExecutionWarning(returnData, inputItemsLength);
|
||||
addPostExecutionWarning(context, returnData, inputItemsLength);
|
||||
|
||||
expect(result).toEqual([returnData]);
|
||||
expect(context.addExecutionHints).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type { INodeExecutionData, IDataObject } from 'n8n-workflow';
|
||||
import { NodeExecutionOutput } from 'n8n-workflow';
|
||||
import type { INodeExecutionData, IDataObject, IExecuteFunctions } from 'n8n-workflow';
|
||||
|
||||
export function isObject(maybe: unknown): maybe is { [key: string]: unknown } {
|
||||
return (
|
||||
|
@ -39,24 +38,18 @@ export function standardizeOutput(output: IDataObject) {
|
|||
}
|
||||
|
||||
export const addPostExecutionWarning = (
|
||||
context: IExecuteFunctions,
|
||||
returnData: INodeExecutionData[],
|
||||
inputItemsLength: number,
|
||||
) => {
|
||||
): void => {
|
||||
if (
|
||||
returnData.length !== inputItemsLength ||
|
||||
returnData.some((item) => item.pairedItem === undefined)
|
||||
) {
|
||||
return new NodeExecutionOutput(
|
||||
[returnData],
|
||||
[
|
||||
{
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
},
|
||||
],
|
||||
);
|
||||
context.addExecutionHints({
|
||||
message:
|
||||
'To make sure expressions after this node work, return the input items that produced each output item. <a target="_blank" href="https://docs.n8n.io/data/data-mapping/data-item-linking/item-linking-code-node/">More info</a>',
|
||||
location: 'outputPane',
|
||||
});
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
};
|
||||
|
|
|
@ -10,12 +10,7 @@ import type {
|
|||
JsonObject,
|
||||
NodeExecutionHint,
|
||||
} from 'n8n-workflow';
|
||||
import {
|
||||
NodeConnectionType,
|
||||
NodeApiError,
|
||||
NodeOperationError,
|
||||
NodeExecutionOutput,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionType, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { calendarFields, calendarOperations } from './CalendarDescription';
|
||||
|
@ -811,7 +806,7 @@ export class GoogleCalendar implements INodeType {
|
|||
}
|
||||
|
||||
if (hints.length) {
|
||||
return new NodeExecutionOutput([nodeExecutionData], hints);
|
||||
this.addExecutionHints(...hints);
|
||||
}
|
||||
|
||||
return [nodeExecutionData];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { MockProxy } from 'jest-mock-extended';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { INode, IExecuteFunctions, IDataObject, NodeExecutionOutput } from 'n8n-workflow';
|
||||
import type { INode, IExecuteFunctions, IDataObject } from 'n8n-workflow';
|
||||
|
||||
import * as genericFunctions from '../../GenericFunctions';
|
||||
import { GoogleCalendar } from '../../GoogleCalendar.node';
|
||||
|
@ -207,15 +207,13 @@ describe('Google Calendar Node', () => {
|
|||
},
|
||||
];
|
||||
|
||||
const result = await googleCalendar.execute.call(mockExecuteFunctions);
|
||||
await googleCalendar.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect((result as NodeExecutionOutput).getHints()).toEqual([
|
||||
{
|
||||
message:
|
||||
"Some events repeat far into the future. To return less of them, add a 'Before' date or change the 'Recurring Event Handling' option.",
|
||||
location: 'outputPane',
|
||||
},
|
||||
]);
|
||||
expect(mockExecuteFunctions.addExecutionHints).toHaveBeenCalledWith({
|
||||
message:
|
||||
"Some events repeat far into the future. To return less of them, add a 'Before' date or change the 'Recurring Event Handling' option.",
|
||||
location: 'outputPane',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,7 +16,6 @@ import type {
|
|||
import {
|
||||
BINARY_ENCODING,
|
||||
NodeApiError,
|
||||
NodeExecutionOutput,
|
||||
NodeConnectionType,
|
||||
NodeOperationError,
|
||||
jsonParse,
|
||||
|
@ -1002,16 +1001,11 @@ export class HttpRequestV3 implements INodeType {
|
|||
returnItems[0].json.data &&
|
||||
Array.isArray(returnItems[0].json.data)
|
||||
) {
|
||||
return new NodeExecutionOutput(
|
||||
[returnItems],
|
||||
[
|
||||
{
|
||||
message:
|
||||
'To split the contents of ‘data’ into separate items for easier processing, add a ‘Split Out’ node after this one',
|
||||
location: 'outputPane',
|
||||
},
|
||||
],
|
||||
);
|
||||
this.addExecutionHints({
|
||||
message:
|
||||
'To split the contents of ‘data’ into separate items for easier processing, add a ‘Split Out’ node after this one',
|
||||
location: 'outputPane',
|
||||
});
|
||||
}
|
||||
|
||||
return [returnItems];
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import merge from 'lodash/merge';
|
||||
import {
|
||||
NodeExecutionOutput,
|
||||
type IExecuteFunctions,
|
||||
type INodeExecutionData,
|
||||
type INodeProperties,
|
||||
type IPairedItemData,
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
INodeExecutionData,
|
||||
INodeProperties,
|
||||
IPairedItemData,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { updateDisplayOptions } from '@utils/utilities';
|
||||
|
@ -82,15 +81,10 @@ export async function execute(
|
|||
} else {
|
||||
numEntries = Math.min(...inputsData.map((input) => input.length), preferred.length);
|
||||
if (numEntries === 0) {
|
||||
return new NodeExecutionOutput(
|
||||
[returnData],
|
||||
[
|
||||
{
|
||||
message:
|
||||
'Consider enabling "Include Any Unpaired Items" in options or check your inputs',
|
||||
},
|
||||
],
|
||||
);
|
||||
this.addExecutionHints({
|
||||
message: 'Consider enabling "Include Any Unpaired Items" in options or check your inputs',
|
||||
});
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
import { NodeExecutionOutput, NodeOperationError } from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import * as database from './database/Database.resource';
|
||||
import type { PostgresType } from './node.type';
|
||||
|
@ -54,15 +54,10 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
|
|||
}
|
||||
|
||||
if (operation === 'select' && items.length > 1 && !node.executeOnce) {
|
||||
return new NodeExecutionOutput(
|
||||
[returnData],
|
||||
[
|
||||
{
|
||||
message: `This node ran ${items.length} times, once for each input item. To run for the first item only, enable 'execute once' in the node settings`,
|
||||
location: 'outputPane',
|
||||
},
|
||||
],
|
||||
);
|
||||
this.addExecutionHints({
|
||||
message: `This node ran ${items.length} times, once for each input item. To run for the first item only, enable 'execute once' in the node settings`,
|
||||
location: 'outputPane',
|
||||
});
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
type IPairedItemData,
|
||||
NodeConnectionType,
|
||||
type NodeExecutionHint,
|
||||
NodeExecutionOutput,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { addBinariesToItem } from './utils';
|
||||
|
@ -432,7 +431,9 @@ export class Aggregate implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
if (hints.length) return new NodeExecutionOutput([[returnData]], hints);
|
||||
if (hints.length) {
|
||||
this.addExecutionHints(...hints);
|
||||
}
|
||||
}
|
||||
|
||||
return [[returnData]];
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
import {
|
||||
NodeConnectionType,
|
||||
NodeExecutionOutput,
|
||||
NodeOperationError,
|
||||
tryToParseDateTime,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionType, NodeOperationError, tryToParseDateTime } from 'n8n-workflow';
|
||||
import type {
|
||||
INodeTypeBaseDescription,
|
||||
IExecuteFunctions,
|
||||
|
@ -126,13 +121,12 @@ export class RemoveDuplicatesV2 implements INodeType {
|
|||
);
|
||||
|
||||
if (maxEntriesNum > 0 && processedDataCount / maxEntriesNum > 0.5) {
|
||||
return new NodeExecutionOutput(returnData, [
|
||||
{
|
||||
message: `Some duplicates may be not be removed since you're approaching the maximum history size (${maxEntriesNum} items). You can raise this limit using the ‘history size’ option.`,
|
||||
location: 'outputPane',
|
||||
},
|
||||
]);
|
||||
} else return returnData;
|
||||
this.addExecutionHints({
|
||||
message: `Some duplicates may be not be removed since you're approaching the maximum history size (${maxEntriesNum} items). You can raise this limit using the ‘history size’ option.`,
|
||||
location: 'outputPane',
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
} else if (logic === 'removeItemsUpToStoredIncrementalKey') {
|
||||
if (!['node', 'workflow'].includes(scope)) {
|
||||
throw new NodeOperationError(
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import get from 'lodash/get';
|
||||
import unset from 'lodash/unset';
|
||||
import {
|
||||
NodeOperationError,
|
||||
deepCopy,
|
||||
NodeExecutionOutput,
|
||||
NodeConnectionType,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeOperationError, deepCopy, NodeConnectionType } from 'n8n-workflow';
|
||||
import type {
|
||||
IBinaryData,
|
||||
IDataObject,
|
||||
|
@ -281,7 +276,9 @@ export class SplitOut implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
if (hints.length) return new NodeExecutionOutput([returnData], hints);
|
||||
if (hints.length) {
|
||||
this.addExecutionHints(...hints);
|
||||
}
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
type INodeExecutionData,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
NodeExecutionOutput,
|
||||
type NodeExecutionHint,
|
||||
type IDataObject,
|
||||
} from 'n8n-workflow';
|
||||
|
@ -345,6 +344,10 @@ export class Summarize implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
if (fieldsNotFound.length) {
|
||||
this.addExecutionHints(...fieldsNotFound);
|
||||
}
|
||||
|
||||
if (options.outputFormat === 'singleItem') {
|
||||
const executionData: INodeExecutionData = {
|
||||
json: aggregationResult,
|
||||
|
@ -352,7 +355,7 @@ export class Summarize implements INodeType {
|
|||
item: index,
|
||||
})),
|
||||
};
|
||||
return new NodeExecutionOutput([[executionData]], fieldsNotFound);
|
||||
return [[executionData]];
|
||||
} else {
|
||||
if (!fieldsToSplitBy.length) {
|
||||
const { pairedItems, ...json } = aggregationResult;
|
||||
|
@ -362,7 +365,7 @@ export class Summarize implements INodeType {
|
|||
item: index,
|
||||
})),
|
||||
};
|
||||
return new NodeExecutionOutput([[executionData]], fieldsNotFound);
|
||||
return [[executionData]];
|
||||
}
|
||||
let returnData: IDataObject[] = [];
|
||||
if (nodeVersion > 1) {
|
||||
|
@ -379,7 +382,7 @@ export class Summarize implements INodeType {
|
|||
})),
|
||||
};
|
||||
});
|
||||
return new NodeExecutionOutput([executionData], fieldsNotFound);
|
||||
return [executionData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { MockProxy } from 'jest-mock-extended';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions } from 'n8n-workflow';
|
||||
import { NodeExecutionOutput, NodeOperationError } from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { Summarize } from '../../Summarize.node';
|
||||
import type { Aggregations } from '../../utils';
|
||||
|
@ -43,14 +43,11 @@ describe('Test Summarize Node, execute', () => {
|
|||
|
||||
const result = await summarizeNode.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toBeInstanceOf(NodeExecutionOutput);
|
||||
expect(result).toEqual([[{ json: { sum_nonexistentField: 0 }, pairedItem: [{ item: 0 }] }]]);
|
||||
expect((result as NodeExecutionOutput).getHints()).toEqual([
|
||||
{
|
||||
location: 'outputPane',
|
||||
message: "The field 'nonexistentField' does not exist in any items",
|
||||
},
|
||||
]);
|
||||
expect(mockExecuteFunctions.addExecutionHints).toHaveBeenCalledWith({
|
||||
location: 'outputPane',
|
||||
message: "The field 'nonexistentField' does not exist in any items",
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error if node version is < 1.1 and fields not found', async () => {
|
||||
|
|
|
@ -14,7 +14,7 @@ import type { URLSearchParams } from 'url';
|
|||
|
||||
import type { CODE_EXECUTION_MODES, CODE_LANGUAGES, LOG_LEVELS } from './Constants';
|
||||
import type { IDeferredPromise } from './DeferredPromise';
|
||||
import { ApplicationError, type ExecutionCancelledError } from './errors';
|
||||
import type { ExecutionCancelledError } from './errors';
|
||||
import type { ExpressionError } from './errors/expression.error';
|
||||
import type { NodeApiError } from './errors/node-api.error';
|
||||
import type { NodeOperationError } from './errors/node-operation.error';
|
||||
|
@ -398,7 +398,8 @@ export interface INodeTypeNameVersion {
|
|||
}
|
||||
|
||||
export interface IRunNodeResponse {
|
||||
data: INodeExecutionData[][] | NodeExecutionOutput | null | undefined;
|
||||
data: INodeExecutionData[][] | null | undefined;
|
||||
hints?: NodeExecutionHint[];
|
||||
closeFunction?: CloseFunction;
|
||||
}
|
||||
|
||||
|
@ -918,6 +919,8 @@ export type IExecuteFunctions = ExecuteFunctions.GetNodeParameterFn &
|
|||
metadata?: ITaskMetadata,
|
||||
): void;
|
||||
|
||||
addExecutionHints(...hints: NodeExecutionHint[]): void;
|
||||
|
||||
nodeHelpers: NodeHelperFunctions;
|
||||
helpers: RequestHelperFunctions &
|
||||
BaseHelperFunctions &
|
||||
|
@ -1553,28 +1556,6 @@ export interface SupplyData {
|
|||
closeFunction?: CloseFunction;
|
||||
}
|
||||
|
||||
export class NodeExecutionOutput extends Array<INodeExecutionData[]> {
|
||||
constructor(data: INodeExecutionData[][], hints: NodeExecutionHint[] = []) {
|
||||
super();
|
||||
// TODO: This is a temporary solution for NODE-1740, until we move away from extending native Array class
|
||||
Object.defineProperty(data, 'getHints', {
|
||||
value: () => hints,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: false,
|
||||
});
|
||||
return data as NodeExecutionOutput;
|
||||
}
|
||||
|
||||
static [Symbol.hasInstance](instance: unknown) {
|
||||
return Array.isArray(instance) && 'getHints' in instance;
|
||||
}
|
||||
|
||||
getHints(): NodeExecutionHint[] {
|
||||
throw new ApplicationError('This should not have been called');
|
||||
}
|
||||
}
|
||||
|
||||
export interface INodeType {
|
||||
description: INodeTypeDescription;
|
||||
supplyData?(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
||||
|
|
Loading…
Reference in a new issue