fix(core): Fix .map calls on NodeExecutionOutput (no-changelog) (#11955)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-12-02 16:55:01 +01:00 committed by GitHub
parent 967340a293
commit 969439ce56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 75 additions and 61 deletions

View file

@ -1194,7 +1194,7 @@ export class WorkflowExecute {
} }
if (nodeSuccessData instanceof NodeExecutionOutput) { if (nodeSuccessData instanceof NodeExecutionOutput) {
const hints: NodeExecutionHint[] = nodeSuccessData.getHints(); const hints = (nodeSuccessData as NodeExecutionOutput).getHints();
executionHints.push(...hints); executionHints.push(...hints);
} }

View file

@ -100,7 +100,7 @@ describe('Test MergeV3, combineBySql operation', () => {
inputsData, inputsData,
); );
expect(returnData[0].json).toEqual({ expect(returnData[0][0].json).toEqual({
data_1: 'a', data_1: 'a',
id: 1, id: 1,
data: 'aa', data: 'aa',
@ -120,7 +120,9 @@ describe('Test MergeV3, combineBySql operation', () => {
[inputsData[0], []], [inputsData[0], []],
); );
expect(returnData[0].json).toEqual({ expect(returnData.length).toEqual(1);
expect(returnData[0].length).toEqual(5);
expect(returnData[0][0].json).toEqual({
data: 'a', data: 'a',
data_1: 'a', data_1: 'a',
id: 1, id: 1,
@ -179,13 +181,15 @@ describe('Test MergeV3, combineBySql operation', () => {
inputsData, inputsData,
); );
expect(returnData[0].json).toEqual({ expect(returnData.length).toEqual(1);
expect(returnData[0].length).toEqual(5);
expect(returnData[0][0].json).toEqual({
id: 1, id: 1,
data: 'aa', data: 'aa',
name: 'Sam', name: 'Sam',
country: 'PL', country: 'PL',
}); });
expect(returnData[4].json).toEqual({ expect(returnData[0][4].json).toEqual({
id: 5, id: 5,
data: 'ff', data: 'ff',
country: 'ES', country: 'ES',
@ -203,8 +207,9 @@ describe('Test MergeV3, combineBySql operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(3); expect(returnData.length).toEqual(1);
expect(returnData[2].json).toEqual({ expect(returnData[0].length).toEqual(3);
expect(returnData[0][2].json).toEqual({
id: 3, id: 3,
data: 'cc', data: 'cc',
name: 'Jon', name: 'Jon',
@ -223,8 +228,9 @@ describe('Test MergeV3, combineBySql operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(7); expect(returnData.length).toEqual(1);
expect(returnData[2].json).toEqual({ expect(returnData[0].length).toEqual(7);
expect(returnData[0][2].json).toEqual({
id: 3, id: 3,
data: 'cc', data: 'cc',
name: 'Jon', name: 'Jon',
@ -242,8 +248,9 @@ describe('Test MergeV3, combineBySql operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(25); expect(returnData.length).toEqual(1);
expect(returnData[0].json).toEqual({ expect(returnData[0].length).toEqual(25);
expect(returnData[0][0].json).toEqual({
data_1: 'a', data_1: 'a',
id: 1, id: 1,
data: 'aa', data: 'aa',
@ -262,8 +269,9 @@ describe('Test MergeV3, append operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(10); expect(returnData.length).toEqual(1);
expect(returnData[0].json).toEqual({ expect(returnData[0].length).toEqual(10);
expect(returnData[0][0].json).toEqual({
id: 1, id: 1,
data: 'a', data: 'a',
name: 'Sam', name: 'Sam',
@ -283,8 +291,9 @@ describe('Test MergeV3, combineByFields operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(3); expect(returnData.length).toEqual(1);
expect(returnData[1].json).toEqual({ expect(returnData[0].length).toEqual(3);
expect(returnData[0][1].json).toEqual({
id: 2, id: 2,
data: 'bb', data: 'bb',
name: 'Dan', name: 'Dan',
@ -302,8 +311,9 @@ describe('Test MergeV3, combineByPosition operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(5); expect(returnData.length).toEqual(1);
expect(returnData[4].json).toEqual({ expect(returnData[0].length).toEqual(5);
expect(returnData[0][4].json).toEqual({
id: 5, id: 5,
data: 'ff', data: 'ff',
name: 'Joe', name: 'Joe',
@ -325,8 +335,9 @@ describe('Test MergeV3, chooseBranch operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(5); expect(returnData.length).toEqual(1);
expect(returnData[0].json).toEqual({ expect(returnData[0].length).toEqual(5);
expect(returnData[0][0].json).toEqual({
id: 1, id: 1,
data: 'aa', data: 'aa',
country: 'PL', country: 'PL',
@ -345,8 +356,9 @@ describe('Test MergeV3, combineAll operation', () => {
inputsData, inputsData,
); );
expect(returnData.length).toEqual(25); expect(returnData.length).toEqual(1);
expect(returnData[0].json).toEqual({ expect(returnData[0].length).toEqual(25);
expect(returnData[0][0].json).toEqual({
id: 1, id: 1,
data: 'aa', data: 'aa',
name: 'Sam', name: 'Sam',

View file

@ -20,12 +20,12 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
for (let i = 0; i < inputsData.length; i++) { for (let i = 0; i < inputsData.length; i++) {
returnData.push.apply(returnData, inputsData[i]); returnData.push.apply(returnData, inputsData[i]);
} }
return returnData; return [returnData];
} }

View file

@ -72,7 +72,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const chooseBranchMode = this.getNodeParameter('chooseBranchMode', 0) as string; const chooseBranchMode = this.getNodeParameter('chooseBranchMode', 0) as string;
@ -105,5 +105,5 @@ export async function execute(
} }
} }
return returnData; return [returnData];
} }

View file

@ -35,7 +35,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const clashHandling = this.getNodeParameter( const clashHandling = this.getNodeParameter(
@ -59,7 +59,7 @@ export async function execute(
const mergeIntoSingleObject = selectMergeMethod(clashHandling); const mergeIntoSingleObject = selectMergeMethod(clashHandling);
if (!input1 || !input2) { if (!input1 || !input2) {
return returnData; return [returnData];
} }
let entry1: INodeExecutionData; let entry1: INodeExecutionData;
@ -79,5 +79,5 @@ export async function execute(
} }
} }
return returnData; return [returnData];
} }

View file

@ -260,7 +260,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const advanced = this.getNodeParameter('advanced', 0) as boolean; const advanced = this.getNodeParameter('advanced', 0) as boolean;
let matchFields; let matchFields;
@ -297,7 +297,7 @@ export async function execute(
options.disableDotNotation || false, options.disableDotNotation || false,
'Input 1', 'Input 1',
); );
if (!input1) return returnData; if (!input1) return [returnData];
input2 = checkInput( input2 = checkInput(
this.getInputData(1), this.getInputData(1),
@ -306,14 +306,14 @@ export async function execute(
'Input 2', 'Input 2',
); );
} else { } else {
if (!input1) return returnData; if (!input1) return [returnData];
} }
if (input1.length === 0 || input2.length === 0) { if (input1.length === 0 || input2.length === 0) {
if (!input1.length && joinMode === 'keepNonMatches' && outputDataFrom === 'input1') if (!input1.length && joinMode === 'keepNonMatches' && outputDataFrom === 'input1')
return returnData; return [returnData];
if (!input2.length && joinMode === 'keepNonMatches' && outputDataFrom === 'input2') if (!input2.length && joinMode === 'keepNonMatches' && outputDataFrom === 'input2')
return returnData; return [returnData];
if (joinMode === 'keepMatches') { if (joinMode === 'keepMatches') {
// Stop the execution // Stop the execution
@ -326,11 +326,11 @@ export async function execute(
return []; return [];
} else { } else {
// Return the data of any of the inputs that contains data // Return the data of any of the inputs that contains data
return [...input1, ...input2]; return [[...input1, ...input2]];
} }
} }
if (!input1) return returnData; if (!input1) return [returnData];
if (!input2 || !matchFields.length) { if (!input2 || !matchFields.length) {
if ( if (
@ -338,9 +338,9 @@ export async function execute(
joinMode === 'keepEverything' || joinMode === 'keepEverything' ||
joinMode === 'enrichInput2' joinMode === 'enrichInput2'
) { ) {
return returnData; return [returnData];
} }
return input1; return [input1];
} }
const matches = findMatches(input1, input2, matchFields, options); const matches = findMatches(input1, input2, matchFields, options);
@ -378,16 +378,16 @@ export async function execute(
if (joinMode === 'keepNonMatches') { if (joinMode === 'keepNonMatches') {
if (outputDataFrom === 'input1') { if (outputDataFrom === 'input1') {
return matches.unmatched1; return [matches.unmatched1];
} }
if (outputDataFrom === 'input2') { if (outputDataFrom === 'input2') {
return matches.unmatched2; return [matches.unmatched2];
} }
if (outputDataFrom === 'both') { if (outputDataFrom === 'both') {
let output: INodeExecutionData[] = []; let output: INodeExecutionData[] = [];
output = output.concat(addSourceField(matches.unmatched1, 'input1')); output = output.concat(addSourceField(matches.unmatched1, 'input1'));
output = output.concat(addSourceField(matches.unmatched2, 'input2')); output = output.concat(addSourceField(matches.unmatched2, 'input2'));
return output; return [output];
} }
} }
@ -415,5 +415,5 @@ export async function execute(
} }
} }
return returnData; return [returnData];
} }

View file

@ -50,7 +50,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const clashHandling = this.getNodeParameter( const clashHandling = this.getNodeParameter(
@ -120,5 +120,5 @@ export async function execute(
returnData.push({ json, binary, pairedItem }); returnData.push({ json, binary, pairedItem });
} }
return returnData; return [returnData];
} }

View file

@ -41,7 +41,7 @@ export const description = updateDisplayOptions(displayOptions, properties);
export async function execute( export async function execute(
this: IExecuteFunctions, this: IExecuteFunctions,
inputsData: INodeExecutionData[][], inputsData: INodeExecutionData[][],
): Promise<INodeExecutionData[]> { ): Promise<INodeExecutionData[][]> {
const nodeId = this.getNode().id; const nodeId = this.getNode().id;
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const pairedItem: IPairedItemData[] = []; const pairedItem: IPairedItemData[] = [];
@ -132,5 +132,5 @@ export async function execute(
delete alasql.databases[nodeId]; delete alasql.databases[nodeId];
return returnData; return [returnData];
} }

View file

@ -1,4 +1,4 @@
import { NodeExecutionOutput, type IExecuteFunctions } from 'n8n-workflow'; import type { IExecuteFunctions } from 'n8n-workflow';
import { getNodeInputsData } from '../helpers/utils'; import { getNodeInputsData } from '../helpers/utils';
import type { MergeType } from './node.type'; import type { MergeType } from './node.type';
import * as mode from './mode'; import * as mode from './mode';
@ -12,11 +12,5 @@ export async function router(this: IExecuteFunctions) {
operationMode = combineBy; operationMode = combineBy;
} }
const returnData = await mode[operationMode as MergeType].execute.call(this, inputsData); return await mode[operationMode as MergeType].execute.call(this, inputsData);
if (returnData instanceof NodeExecutionOutput) {
return returnData;
} else {
return [returnData];
}
} }

View file

@ -14,7 +14,7 @@ import type { URLSearchParams } from 'url';
import type { CODE_EXECUTION_MODES, CODE_LANGUAGES, LOG_LEVELS } from './Constants'; import type { CODE_EXECUTION_MODES, CODE_LANGUAGES, LOG_LEVELS } from './Constants';
import type { IDeferredPromise } from './DeferredPromise'; import type { IDeferredPromise } from './DeferredPromise';
import type { ExecutionCancelledError } from './errors'; import { ApplicationError, type ExecutionCancelledError } from './errors';
import type { ExpressionError } from './errors/expression.error'; import type { ExpressionError } from './errors/expression.error';
import type { NodeApiError } from './errors/node-api.error'; import type { NodeApiError } from './errors/node-api.error';
import type { NodeOperationError } from './errors/node-operation.error'; import type { NodeOperationError } from './errors/node-operation.error';
@ -1587,17 +1587,25 @@ export interface SupplyData {
closeFunction?: CloseFunction; closeFunction?: CloseFunction;
} }
export class NodeExecutionOutput extends Array { export class NodeExecutionOutput extends Array<INodeExecutionData[]> {
private hints: NodeExecutionHint[];
constructor(data: INodeExecutionData[][], hints: NodeExecutionHint[] = []) { constructor(data: INodeExecutionData[][], hints: NodeExecutionHint[] = []) {
super(); super();
this.push(...data); // TODO: This is a temporary solution for NODE-1740, until we move away from extending native Array class
this.hints = hints; Object.defineProperty(data, 'getHints', {
value: () => hints,
enumerable: false,
writable: false,
configurable: false,
});
return data as NodeExecutionOutput;
} }
public getHints(): NodeExecutionHint[] { static [Symbol.hasInstance](instance: unknown) {
return this.hints; return Array.isArray(instance) && 'getHints' in instance;
}
getHints(): NodeExecutionHint[] {
throw new ApplicationError('This should not have been called');
} }
} }