feat: Do not assign all paired items (no-changelog) (#11716)

This commit is contained in:
Michael Kret 2025-02-06 15:46:28 +02:00 committed by GitHub
parent 2eabca5613
commit 4c2546dc78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 55 additions and 236 deletions

View file

@ -49,11 +49,6 @@ describe('Test AirtableV2, base => getMany', () => {
name: 'base 1', name: 'base 1',
permissionLevel: 'create', permissionLevel: 'create',
}, },
pairedItem: [
{
item: 0,
},
],
}, },
{ {
json: { json: {
@ -61,11 +56,6 @@ describe('Test AirtableV2, base => getMany', () => {
name: 'base 2', name: 'base 2',
permissionLevel: 'edit', permissionLevel: 'edit',
}, },
pairedItem: [
{
item: 0,
},
],
}, },
{ {
json: { json: {
@ -73,11 +63,6 @@ describe('Test AirtableV2, base => getMany', () => {
name: 'base 3', name: 'base 3',
permissionLevel: 'create', permissionLevel: 'create',
}, },
pairedItem: [
{
item: 0,
},
],
}, },
]); ]);
}); });
@ -101,11 +86,6 @@ describe('Test AirtableV2, base => getMany', () => {
name: 'base 2', name: 'base 2',
permissionLevel: 'edit', permissionLevel: 'edit',
}, },
pairedItem: [
{
item: 0,
},
],
}, },
]); ]);
}); });

View file

@ -98,11 +98,7 @@ describe('Test AirtableV2, search operation', () => {
expect(result).toHaveLength(2); expect(result).toHaveLength(2);
expect(result[0]).toEqual({ expect(result[0]).toEqual({
json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' }, json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' },
pairedItem: [ pairedItem: [],
{
item: 0,
},
],
}); });
}); });
@ -142,11 +138,7 @@ describe('Test AirtableV2, search operation', () => {
expect(result).toHaveLength(1); expect(result).toHaveLength(1);
expect(result[0]).toEqual({ expect(result[0]).toEqual({
json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' }, json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' },
pairedItem: [ pairedItem: [],
{
item: 0,
},
],
}); });
}); });
}); });

View file

@ -12,7 +12,6 @@ import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import type { IRecord } from './GenericFunctions'; import type { IRecord } from './GenericFunctions';
import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from './GenericFunctions'; import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from './GenericFunctions';
import { oldVersionNotice } from '../../../utils/descriptions'; import { oldVersionNotice } from '../../../utils/descriptions';
import { generatePairedItemData } from '../../../utils/utilities';
const versionDescription: INodeTypeDescription = { const versionDescription: INodeTypeDescription = {
displayName: 'Airtable', displayName: 'Airtable',
@ -737,24 +736,16 @@ export class AirtableV1 implements INodeType {
const downloadFieldNames = ( const downloadFieldNames = (
this.getNodeParameter('downloadFieldNames', 0) as string this.getNodeParameter('downloadFieldNames', 0) as string
).split(','); ).split(',');
const pairedItem = generatePairedItemData(items.length);
const data = await downloadRecordAttachments.call( const data = await downloadRecordAttachments.call(
this, this,
responseData.records as IRecord[], responseData.records as IRecord[],
downloadFieldNames, downloadFieldNames,
pairedItem,
); );
return [data]; return [data];
} }
// We can return from here return [this.helpers.returnJsonArray(returnData)];
const itemData = generatePairedItemData(items.length);
return [
this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(returnData), {
itemData,
}),
];
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } }); returnData.push({ json: { error: error.message } });

View file

@ -5,11 +5,7 @@ import type {
IExecuteFunctions, IExecuteFunctions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import { updateDisplayOptions, wrapData } from '../../../../../utils/utilities';
generatePairedItemData,
updateDisplayOptions,
wrapData,
} from '../../../../../utils/utilities';
import { apiRequest } from '../../transport'; import { apiRequest } from '../../transport';
const properties: INodeProperties[] = [ const properties: INodeProperties[] = [
@ -112,11 +108,7 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
bases = bases.filter((base) => permissionLevel.includes(base.permissionLevel as string)); bases = bases.filter((base) => permissionLevel.includes(base.permissionLevel as string));
} }
const itemData = generatePairedItemData(this.getInputData().length); const returnData = wrapData(bases);
const returnData = this.helpers.constructExecutionMetaData(wrapData(bases), {
itemData,
});
return returnData; return returnData;
} }

View file

@ -5,7 +5,7 @@ import type {
IExecuteFunctions, IExecuteFunctions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { generatePairedItemData, updateDisplayOptions } from '../../../../../utils/utilities'; import { updateDisplayOptions } from '../../../../../utils/utilities';
import type { IRecord } from '../../helpers/interfaces'; import type { IRecord } from '../../helpers/interfaces';
import { flattenOutput } from '../../helpers/utils'; import { flattenOutput } from '../../helpers/utils';
import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from '../../transport'; import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from '../../transport';
@ -156,12 +156,9 @@ export async function execute(
const endpoint = `${base}/${table}`; const endpoint = `${base}/${table}`;
let itemsLength = items.length ? 1 : 0; let itemsLength = items.length ? 1 : 0;
let fallbackPairedItems;
if (nodeVersion >= 2.1) { if (nodeVersion >= 2.1) {
itemsLength = items.length; itemsLength = items.length;
} else {
fallbackPairedItems = generatePairedItemData(items.length);
} }
for (let i = 0; i < itemsLength; i++) { for (let i = 0; i < itemsLength; i++) {
@ -208,7 +205,7 @@ export async function execute(
this, this,
responseData.records as IRecord[], responseData.records as IRecord[],
options.downloadFields as string[], options.downloadFields as string[],
fallbackPairedItems || [{ item: i }], nodeVersion >= 2.1 ? [{ item: i }] : undefined,
); );
returnData.push(...itemWithAttachments); returnData.push(...itemWithAttachments);
continue; continue;
@ -220,7 +217,7 @@ export async function execute(
json: flattenOutput(record), json: flattenOutput(record),
})) as INodeExecutionData[]; })) as INodeExecutionData[];
const itemData = fallbackPairedItems || [{ item: i }]; const itemData = nodeVersion >= 2.1 ? [{ item: i }] : [];
const executionData = this.helpers.constructExecutionMetaData(records, { const executionData = this.helpers.constructExecutionMetaData(records, {
itemData, itemData,

View file

@ -9,7 +9,6 @@ import type {
import { getWorkflowInfo } from './GenericFunctions'; import { getWorkflowInfo } from './GenericFunctions';
import { localResourceMapping } from './methods'; import { localResourceMapping } from './methods';
import { generatePairedItemData } from '../../../utils/utilities';
import { getCurrentWorkflowInputData } from '../../../utils/workflowInputsResourceMapping/GenericFunctions'; import { getCurrentWorkflowInputData } from '../../../utils/workflowInputsResourceMapping/GenericFunctions';
export class ExecuteWorkflow implements INodeType { export class ExecuteWorkflow implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -422,8 +421,6 @@ export class ExecuteWorkflow implements INodeType {
const workflowResult = executionResult.data as INodeExecutionData[][]; const workflowResult = executionResult.data as INodeExecutionData[][];
const fallbackPairedItemData = generatePairedItemData(items.length);
for (const output of workflowResult) { for (const output of workflowResult) {
const sameLength = output.length === items.length; const sameLength = output.length === items.length;
@ -432,17 +429,14 @@ export class ExecuteWorkflow implements INodeType {
if (sameLength) { if (sameLength) {
item.pairedItem = { item: itemIndex }; item.pairedItem = { item: itemIndex };
} else {
item.pairedItem = fallbackPairedItemData;
} }
} }
} }
return workflowResult; return workflowResult;
} catch (error) { } catch (error) {
const pairedItem = generatePairedItemData(items.length);
if (this.continueOnFail()) { if (this.continueOnFail()) {
return [[{ json: { error: error.message }, pairedItem }]]; return [[{ json: { error: error.message } }]];
} }
throw error; throw error;
} }

View file

@ -7,7 +7,7 @@ import {
import type { JsonToSpreadsheetBinaryOptions, JsonToSpreadsheetBinaryFormat } from '@utils/binary'; import type { JsonToSpreadsheetBinaryOptions, JsonToSpreadsheetBinaryFormat } from '@utils/binary';
import { convertJsonToSpreadsheetBinary } from '@utils/binary'; import { convertJsonToSpreadsheetBinary } from '@utils/binary';
import { generatePairedItemData, updateDisplayOptions } from '@utils/utilities'; import { updateDisplayOptions } from '@utils/utilities';
export const operations = ['csv', 'html', 'rtf', 'ods', 'xls', 'xlsx']; export const operations = ['csv', 'html', 'rtf', 'ods', 'xls', 'xlsx'];
@ -98,7 +98,6 @@ export async function execute(
) { ) {
let returnData: INodeExecutionData[] = []; let returnData: INodeExecutionData[] = [];
const pairedItem = generatePairedItemData(items.length);
try { try {
const options = this.getNodeParameter('options', 0, {}) as JsonToSpreadsheetBinaryOptions; const options = this.getNodeParameter('options', 0, {}) as JsonToSpreadsheetBinaryOptions;
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0, 'data'); const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0, 'data');
@ -116,7 +115,6 @@ export async function execute(
binary: { binary: {
[binaryPropertyName]: binaryData, [binaryPropertyName]: binaryData,
}, },
pairedItem,
}; };
returnData = [newItem]; returnData = [newItem];
@ -126,7 +124,6 @@ export async function execute(
json: { json: {
error: error.message, error: error.message,
}, },
pairedItem,
}); });
} else { } else {
throw new NodeOperationError(this.getNode(), error); throw new NodeOperationError(this.getNode(), error);

View file

@ -3,7 +3,7 @@ import { NodeOperationError } from 'n8n-workflow';
import { createBinaryFromJson } from '@utils/binary'; import { createBinaryFromJson } from '@utils/binary';
import { encodeDecodeOptions } from '@utils/descriptions'; import { encodeDecodeOptions } from '@utils/descriptions';
import { generatePairedItemData, updateDisplayOptions } from '@utils/utilities'; import { updateDisplayOptions } from '@utils/utilities';
export const properties: INodeProperties[] = [ export const properties: INodeProperties[] = [
{ {
@ -92,7 +92,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
const mode = this.getNodeParameter('mode', 0, 'once') as string; const mode = this.getNodeParameter('mode', 0, 'once') as string;
if (mode === 'once') { if (mode === 'once') {
const pairedItem = generatePairedItemData(items.length);
try { try {
const options = this.getNodeParameter('options', 0, {}); const options = this.getNodeParameter('options', 0, {});
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0, 'data'); const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0, 'data');
@ -114,7 +113,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
binary: { binary: {
[binaryPropertyName]: binaryData, [binaryPropertyName]: binaryData,
}, },
pairedItem,
}; };
returnData = [newItem]; returnData = [newItem];
@ -124,7 +122,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
json: { json: {
error: error.message, error: error.message,
}, },
pairedItem,
}); });
} }
throw new NodeOperationError(this.getNode(), error); throw new NodeOperationError(this.getNode(), error);

View file

@ -19,7 +19,7 @@ import type { Readable } from 'stream';
import { pipeline } from 'stream/promises'; import { pipeline } from 'stream/promises';
import { file as tmpFile } from 'tmp-promise'; import { file as tmpFile } from 'tmp-promise';
import { formatPrivateKey, generatePairedItemData } from '@utils/utilities'; import { formatPrivateKey } from '@utils/utilities';
interface ReturnFtpItem { interface ReturnFtpItem {
type: string; type: string;
@ -550,9 +550,7 @@ export class Ftp implements INodeType {
} }
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const pairedItem = generatePairedItemData(items.length); return [[{ json: { error: error.message } }]];
return [[{ json: { error: error.message }, pairedItem }]];
} }
throw error; throw error;
} }

View file

@ -16,7 +16,6 @@ import { oldVersionNotice } from '@utils/descriptions';
import { googleApiRequest, googleApiRequestAllItems, simplify } from './GenericFunctions'; import { googleApiRequest, googleApiRequestAllItems, simplify } from './GenericFunctions';
import { recordFields, recordOperations } from './RecordDescription'; import { recordFields, recordOperations } from './RecordDescription';
import { generatePairedItemData } from '../../../../utils/utilities';
const versionDescription: INodeTypeDescription = { const versionDescription: INodeTypeDescription = {
displayName: 'Google BigQuery', displayName: 'Google BigQuery',
@ -195,8 +194,6 @@ export class GoogleBigQueryV1 implements INodeType {
body.rows = rows; body.rows = rows;
const itemData = generatePairedItemData(items.length);
try { try {
responseData = await googleApiRequest.call( responseData = await googleApiRequest.call(
this, this,
@ -205,17 +202,11 @@ export class GoogleBigQueryV1 implements INodeType {
body, body,
); );
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const executionErrorData = this.helpers.constructExecutionMetaData( const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} }
throw new NodeApiError(this.getNode(), error as JsonObject, { itemIndex: 0 }); throw new NodeApiError(this.getNode(), error as JsonObject, { itemIndex: 0 });

View file

@ -7,7 +7,7 @@ import type {
import { NodeOperationError } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { generatePairedItemData, updateDisplayOptions } from '@utils/utilities'; import { updateDisplayOptions } from '@utils/utilities';
import type { TableSchema } from '../../helpers/interfaces'; import type { TableSchema } from '../../helpers/interfaces';
import { checkSchema, wrapData } from '../../helpers/utils'; import { checkSchema, wrapData } from '../../helpers/utils';
@ -227,7 +227,6 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
} }
} }
const itemData = generatePairedItemData(items.length);
for (let i = 0; i < rows.length; i += batchSize) { for (let i = 0; i < rows.length; i += batchSize) {
const batch = rows.slice(i, i + batchSize); const batch = rows.slice(i, i + batchSize);
body.rows = batch; body.rows = batch;
@ -281,10 +280,7 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
}); });
} }
const executionData = this.helpers.constructExecutionMetaData( const executionData = wrapData(responseData as IDataObject[]);
wrapData(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} }

View file

@ -17,7 +17,6 @@ import {
googleApiRequestAllItems, googleApiRequestAllItems,
jsonToDocument, jsonToDocument,
} from './GenericFunctions'; } from './GenericFunctions';
import { generatePairedItemData } from '../../../../utils/utilities';
export class GoogleFirebaseCloudFirestore implements INodeType { export class GoogleFirebaseCloudFirestore implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -121,7 +120,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const itemData = generatePairedItemData(items.length);
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
let responseData; let responseData;
@ -136,7 +135,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
if (nodeVersion >= 1.1) { if (nodeVersion >= 1.1) {
itemsLength = items.length; itemsLength = items.length;
} else { } else {
fallbackPairedItems = generatePairedItemData(items.length); fallbackPairedItems = [];
} }
if (resource === 'document') { if (resource === 'document') {
@ -172,10 +171,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
.filter((el: IDataObject) => !!el); .filter((el: IDataObject) => !!el);
} }
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} else if (operation === 'create') { } else if (operation === 'create') {

View file

@ -23,7 +23,6 @@ import type {
} from './GoogleSheet'; } from './GoogleSheet';
import { GoogleSheet } from './GoogleSheet'; import { GoogleSheet } from './GoogleSheet';
import { versionDescription } from './versionDescription'; import { versionDescription } from './versionDescription';
import { generatePairedItemData } from '../../../../utils/utilities';
import { getGoogleAccessToken } from '../../GenericFunctions'; import { getGoogleAccessToken } from '../../GenericFunctions';
export class GoogleSheetsV1 implements INodeType { export class GoogleSheetsV1 implements INodeType {
@ -294,12 +293,9 @@ export class GoogleSheetsV1 implements INodeType {
returnData = []; returnData = [];
} }
const pairedItem = generatePairedItemData(items.length);
const lookupOutput = returnData.map((item) => { const lookupOutput = returnData.map((item) => {
return { return {
json: item, json: item,
pairedItem,
}; };
}); });

View file

@ -1,6 +1,6 @@
import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow'; import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow';
import { generatePairedItemData, wrapData } from '../../../../../../utils/utilities'; import { wrapData } from '../../../../../../utils/utilities';
import type { GoogleSheet } from '../../helpers/GoogleSheet'; import type { GoogleSheet } from '../../helpers/GoogleSheet';
import type { SheetProperties } from '../../helpers/GoogleSheets.types'; import type { SheetProperties } from '../../helpers/GoogleSheets.types';
import { getColumnNumber, untilSheetSelected } from '../../helpers/GoogleSheets.utils'; import { getColumnNumber, untilSheetSelected } from '../../helpers/GoogleSheets.utils';
@ -166,10 +166,7 @@ export async function execute(
await sheet.spreadsheetBatchUpdate(requests); await sheet.spreadsheetBatchUpdate(requests);
} }
const itemData = generatePairedItemData(this.getInputData().length); const returnData = wrapData({ success: true });
const returnData = this.helpers.constructExecutionMetaData(wrapData({ success: true }), {
itemData,
});
return returnData; return returnData;
} }

View file

@ -38,7 +38,6 @@ import {
validateCredentials, validateCredentials,
} from './GenericFunctions'; } from './GenericFunctions';
import { ticketFields, ticketOperations } from './TicketDescription'; import { ticketFields, ticketOperations } from './TicketDescription';
import { generatePairedItemData } from '../../../utils/utilities';
export class HubspotV2 implements INodeType { export class HubspotV2 implements INodeType {
description: INodeTypeDescription; description: INodeTypeDescription;
@ -1185,12 +1184,7 @@ export class HubspotV2 implements INodeType {
); );
} }
const itemData = generatePairedItemData(items.length); const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {

View file

@ -14,8 +14,6 @@ import type {
} from 'n8n-workflow'; } from 'n8n-workflow';
import { ApplicationError, NodeConnectionType, NodeOperationError } from 'n8n-workflow'; import { ApplicationError, NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import { generatePairedItemData } from '../../utils/utilities';
export class Kafka implements INodeType { export class Kafka implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Kafka', displayName: 'Kafka',
@ -260,7 +258,6 @@ export class Kafka implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const itemData = generatePairedItemData(items.length);
const length = items.length; const length = items.length;
@ -400,15 +397,12 @@ export class Kafka implements INodeType {
await producer.disconnect(); await producer.disconnect();
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData);
this.helpers.returnJsonArray(responseData),
{ itemData },
);
return [executionData]; return [executionData];
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
return [[{ json: { error: error.message }, pairedItem: itemData }]]; return [[{ json: { error: error.message } }]];
} else { } else {
throw error; throw error;
} }

View file

@ -21,7 +21,6 @@ import {
import { tableFields, tableOperations } from './TableDescription'; import { tableFields, tableOperations } from './TableDescription';
import { workbookFields, workbookOperations } from './WorkbookDescription'; import { workbookFields, workbookOperations } from './WorkbookDescription';
import { worksheetFields, worksheetOperations } from './WorksheetDescription'; import { worksheetFields, worksheetOperations } from './WorksheetDescription';
import { generatePairedItemData } from '../../../../utils/utilities';
const versionDescription: INodeTypeDescription = { const versionDescription: INodeTypeDescription = {
displayName: 'Microsoft Excel', displayName: 'Microsoft Excel',
@ -173,7 +172,6 @@ export class MicrosoftExcelV1 implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const itemData = generatePairedItemData(items.length);
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const length = items.length; const length = items.length;
let qs: IDataObject = {}; let qs: IDataObject = {};
@ -245,18 +243,12 @@ export class MicrosoftExcelV1 implements INodeType {
{ 'workbook-session-id': id }, { 'workbook-session-id': id },
); );
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const executionErrorData = this.helpers.constructExecutionMetaData( const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} else { } else {
throw error; throw error;

View file

@ -5,7 +5,7 @@ import type {
INodeProperties, INodeProperties,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities'; import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse } from '../../helpers/interfaces'; import type { ExcelResponse } from '../../helpers/interfaces';
import { prepareOutput } from '../../helpers/utils'; import { prepareOutput } from '../../helpers/utils';
@ -274,11 +274,7 @@ export async function execute(
); );
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const itemData = generatePairedItemData(this.getInputData().length); const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} else { } else {
throw error; throw error;

View file

@ -6,7 +6,7 @@ import type {
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow';
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities'; import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces'; import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
import { import {
@ -375,11 +375,7 @@ export async function execute(
} }
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const itemData = generatePairedItemData(this.getInputData().length); const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} else { } else {
throw error; throw error;

View file

@ -6,7 +6,7 @@ import type {
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow';
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities'; import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces'; import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
import { import {
@ -382,11 +382,7 @@ export async function execute(
); );
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const itemData = generatePairedItemData(this.getInputData().length); const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} else { } else {
throw error; throw error;

View file

@ -1,7 +1,7 @@
import type { IDataObject, IExecuteFunctions, INode, INodeExecutionData } from 'n8n-workflow'; import type { IDataObject, IExecuteFunctions, INode, INodeExecutionData } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow';
import { generatePairedItemData, wrapData } from '@utils/utilities'; import { wrapData } from '@utils/utilities';
import type { ExcelResponse, SheetData, UpdateSummary } from './interfaces'; import type { ExcelResponse, SheetData, UpdateSummary } from './interfaces';
@ -62,11 +62,7 @@ export function prepareOutput(
returnData.push(...executionData); returnData.push(...executionData);
} }
} else { } else {
const itemData = generatePairedItemData(this.getInputData().length); const executionData = wrapData({ [config.dataProperty || 'data']: responseData });
const executionData = this.helpers.constructExecutionMetaData(
wrapData({ [config.dataProperty || 'data']: responseData }),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} }

View file

@ -12,7 +12,7 @@ import {
NodeConnectionType, NodeConnectionType,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { flatten, generatePairedItemData, getResolvables } from '@utils/utilities'; import { flatten, getResolvables } from '@utils/utilities';
import { import {
configurePool, configurePool,
@ -343,12 +343,7 @@ export class MicrosoftSql implements INodeType {
responseData = await deleteOperation(tables, pool); responseData = await deleteOperation(tables, pool);
} }
const itemData = generatePairedItemData(items.length); returnData = this.helpers.returnJsonArray(responseData);
returnData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData),
{ itemData },
);
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
responseData = items; responseData = items;

View file

@ -28,7 +28,6 @@ import {
} from './GenericFunctions'; } from './GenericFunctions';
import type { IMongoParametricCredentials } from './mongoDb.types'; import type { IMongoParametricCredentials } from './mongoDb.types';
import { nodeProperties } from './MongoDbProperties'; import { nodeProperties } from './MongoDbProperties';
import { generatePairedItemData } from '../../utils/utilities';
export class MongoDb implements INodeType { export class MongoDb implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -118,7 +117,7 @@ export class MongoDb implements INodeType {
if (nodeVersion >= 1.1) { if (nodeVersion >= 1.1) {
itemsLength = items.length; itemsLength = items.length;
} else { } else {
fallbackPairedItems = generatePairedItemData(items.length); fallbackPairedItems = [];
} }
if (operation === 'aggregate') { if (operation === 'aggregate') {
@ -235,7 +234,6 @@ export class MongoDb implements INodeType {
} }
if (operation === 'findOneAndReplace') { if (operation === 'findOneAndReplace') {
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
const fields = prepareFields(this.getNodeParameter('fields', 0) as string); const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean; const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
const dateFields = prepareFields( const dateFields = prepareFields(
@ -270,14 +268,10 @@ export class MongoDb implements INodeType {
} }
} }
returnData = this.helpers.constructExecutionMetaData( returnData = this.helpers.returnJsonArray(updateItems);
this.helpers.returnJsonArray(updateItems),
{ itemData: fallbackPairedItems },
);
} }
if (operation === 'findOneAndUpdate') { if (operation === 'findOneAndUpdate') {
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
const fields = prepareFields(this.getNodeParameter('fields', 0) as string); const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean; const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
const dateFields = prepareFields( const dateFields = prepareFields(
@ -312,14 +306,10 @@ export class MongoDb implements INodeType {
} }
} }
returnData = this.helpers.constructExecutionMetaData( returnData = this.helpers.returnJsonArray(updateItems);
this.helpers.returnJsonArray(updateItems),
{ itemData: fallbackPairedItems },
);
} }
if (operation === 'insert') { if (operation === 'insert') {
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
let responseData: IDataObject[] = []; let responseData: IDataObject[] = [];
try { try {
// Prepare the data to insert and copy it to be returned // Prepare the data to insert and copy it to be returned
@ -350,14 +340,10 @@ export class MongoDb implements INodeType {
} }
} }
returnData = this.helpers.constructExecutionMetaData( returnData = this.helpers.returnJsonArray(responseData);
this.helpers.returnJsonArray(responseData),
{ itemData: fallbackPairedItems },
);
} }
if (operation === 'update') { if (operation === 'update') {
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
const fields = prepareFields(this.getNodeParameter('fields', 0) as string); const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean; const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
const dateFields = prepareFields( const dateFields = prepareFields(
@ -392,10 +378,7 @@ export class MongoDb implements INodeType {
} }
} }
returnData = this.helpers.constructExecutionMetaData( returnData = this.helpers.returnJsonArray(updateItems);
this.helpers.returnJsonArray(updateItems),
{ itemData: fallbackPairedItems },
);
} }
await client.close(); await client.close();

View file

@ -49,7 +49,7 @@ describe('Test PostgresV2, runQueries', () => {
expect(result).toBeDefined(); expect(result).toBeDefined();
expect(result).toHaveLength(1); expect(result).toHaveLength(1);
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]); expect(result).toEqual([{ json: { success: true }, pairedItem: undefined }]);
expect(dbMultiSpy).toHaveBeenCalledWith('SELECT * FROM table'); expect(dbMultiSpy).toHaveBeenCalledWith('SELECT * FROM table');
}); });
}); });

View file

@ -19,7 +19,6 @@ import type {
SortRule, SortRule,
WhereClause, WhereClause,
} from './interfaces'; } from './interfaces';
import { generatePairedItemData } from '../../../../utils/utilities';
export function isJSON(str: string) { export function isJSON(str: string) {
try { try {
@ -252,17 +251,15 @@ export function configureQueryRunner(
.flat(); .flat();
if (!returnData.length) { if (!returnData.length) {
const pairedItem = generatePairedItemData(queries.length);
if ((options?.nodeVersion as number) < 2.3) { if ((options?.nodeVersion as number) < 2.3) {
if (emptyReturnData.length) { if (emptyReturnData.length) {
emptyReturnData[0].pairedItem = pairedItem; emptyReturnData[0].pairedItem = undefined;
} }
returnData = emptyReturnData; returnData = emptyReturnData;
} else { } else {
returnData = queries.every((query) => isSelectQuery(query.query)) returnData = queries.every((query) => isSelectQuery(query.query))
? [] ? []
: [{ json: { success: true }, pairedItem }]; : [{ json: { success: true } }];
} }
} }
} catch (err) { } catch (err) {

View file

@ -19,7 +19,6 @@ import {
} from './GenericFunctions'; } from './GenericFunctions';
import { recordFields, recordOperations } from './RecordDescription'; import { recordFields, recordOperations } from './RecordDescription';
import { reportFields, reportOperations } from './ReportDescription'; import { reportFields, reportOperations } from './ReportDescription';
import { generatePairedItemData } from '../../utils/utilities';
export class QuickBase implements INodeType { export class QuickBase implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -114,7 +113,6 @@ export class QuickBase implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const itemData = generatePairedItemData(items.length);
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const length = items.length; const length = items.length;
const qs: IDataObject = {}; const qs: IDataObject = {};
@ -292,10 +290,7 @@ export class QuickBase implements INodeType {
} }
} }
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} }
@ -462,10 +457,7 @@ export class QuickBase implements INodeType {
} }
} }
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} }
@ -545,10 +537,7 @@ export class QuickBase implements INodeType {
} }
} }
const executionData = this.helpers.constructExecutionMetaData( const executionData = this.helpers.returnJsonArray(responseData as IDataObject[]);
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData },
);
returnData.push(...executionData); returnData.push(...executionData);
} }

View file

@ -7,8 +7,6 @@ import {
type INodeTypeDescription, type INodeTypeDescription,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { generatePairedItemData } from '../../utils/utilities';
export class ReadBinaryFiles implements INodeType { export class ReadBinaryFiles implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
hidden: true, hidden: true,
@ -48,7 +46,6 @@ export class ReadBinaryFiles implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const fileSelector = this.getNodeParameter('fileSelector', 0) as string; const fileSelector = this.getNodeParameter('fileSelector', 0) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', 0); const dataPropertyName = this.getNodeParameter('dataPropertyName', 0);
const pairedItem = generatePairedItemData(this.getInputData().length);
const files = await glob(fileSelector); const files = await glob(fileSelector);
@ -60,7 +57,6 @@ export class ReadBinaryFiles implements INodeType {
[dataPropertyName]: await this.helpers.prepareBinaryData(stream, filePath), [dataPropertyName]: await this.helpers.prepareBinaryData(stream, filePath),
}, },
json: {}, json: {},
pairedItem,
}); });
} }

View file

@ -21,7 +21,7 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
import type { Readable } from 'stream'; import type { Readable } from 'stream';
import { formatPrivateKey, generatePairedItemData } from '../../utils/utilities'; import { formatPrivateKey } from '../../utils/utilities';
export class RespondToWebhook implements INodeType { export class RespondToWebhook implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -443,11 +443,7 @@ export class RespondToWebhook implements INodeType {
this.sendResponse(response); this.sendResponse(response);
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const itemData = generatePairedItemData(items.length); const returnData = [{ json: { error: error.message } }];
const returnData = this.helpers.constructExecutionMetaData(
[{ json: { error: error.message } }],
{ itemData },
);
return [returnData]; return [returnData];
} }

View file

@ -253,7 +253,6 @@ describe('RespondToWebhook Node', () => {
[ [
{ {
json: { error: 'The Response Data option "notSupportedRespondWith" is not supported!' }, json: { error: 'The Response Data option "notSupportedRespondWith" is not supported!' },
pairedItem: [{ item: 0 }],
}, },
], ],
]); ]);

View file

@ -4,13 +4,12 @@ import type {
INodeExecutionData, INodeExecutionData,
INodeType, INodeType,
INodeTypeDescription, INodeTypeDescription,
IPairedItemData,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow'; import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import Parser from 'rss-parser'; import Parser from 'rss-parser';
import { URL } from 'url'; import { URL } from 'url';
import { generatePairedItemData } from '../../utils/utilities';
// Utility function // Utility function
function validateURL(url: string) { function validateURL(url: string) {
@ -77,7 +76,7 @@ export class RssFeedRead implements INodeType {
if (nodeVersion >= 1.1) { if (nodeVersion >= 1.1) {
itemsLength = items.length; itemsLength = items.length;
} else { } else {
fallbackPairedItems = generatePairedItemData(items.length); fallbackPairedItems = [] as IPairedItemData[];
} }
for (let i = 0; i < itemsLength; i++) { for (let i = 0; i < itemsLength; i++) {

View file

@ -22,7 +22,7 @@ import {
} from 'xlsx'; } from 'xlsx';
import { oldVersionNotice } from '@utils/descriptions'; import { oldVersionNotice } from '@utils/descriptions';
import { flattenObject, generatePairedItemData } from '@utils/utilities'; import { flattenObject } from '@utils/utilities';
import { import {
operationProperty, operationProperty,
@ -58,7 +58,6 @@ export class SpreadsheetFileV1 implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
const pairedItem = generatePairedItemData(items.length);
const operation = this.getNodeParameter('operation', 0); const operation = this.getNodeParameter('operation', 0);
@ -230,7 +229,6 @@ export class SpreadsheetFileV1 implements INodeType {
const newItem: INodeExecutionData = { const newItem: INodeExecutionData = {
json: {}, json: {},
binary: {}, binary: {},
pairedItem,
}; };
let fileName = `spreadsheet.${fileFormat}`; let fileName = `spreadsheet.${fileFormat}`;
@ -247,7 +245,6 @@ export class SpreadsheetFileV1 implements INodeType {
json: { json: {
error: error.message, error: error.message,
}, },
pairedItem,
}); });
} else { } else {
throw error; throw error;

View file

@ -2,7 +2,6 @@ import type { IExecuteFunctions, INodeExecutionData, INodeProperties } from 'n8n
import type { JsonToSpreadsheetBinaryFormat, JsonToSpreadsheetBinaryOptions } from '@utils/binary'; import type { JsonToSpreadsheetBinaryFormat, JsonToSpreadsheetBinaryOptions } from '@utils/binary';
import { convertJsonToSpreadsheetBinary } from '@utils/binary'; import { convertJsonToSpreadsheetBinary } from '@utils/binary';
import { generatePairedItemData } from '@utils/utilities';
import { toFileOptions, toFileProperties } from '../description'; import { toFileOptions, toFileProperties } from '../description';
@ -11,8 +10,6 @@ export const description: INodeProperties[] = [...toFileProperties, toFileOption
export async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) { export async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) {
const returnData: INodeExecutionData[] = []; const returnData: INodeExecutionData[] = [];
const pairedItem = generatePairedItemData(items.length);
try { try {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0); const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
const fileFormat = this.getNodeParameter('fileFormat', 0) as JsonToSpreadsheetBinaryFormat; const fileFormat = this.getNodeParameter('fileFormat', 0) as JsonToSpreadsheetBinaryFormat;
@ -25,7 +22,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
binary: { binary: {
[binaryPropertyName]: binaryData, [binaryPropertyName]: binaryData,
}, },
pairedItem,
}; };
returnData.push(newItem); returnData.push(newItem);
@ -35,7 +31,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData
json: { json: {
error: error.message, error: error.message,
}, },
pairedItem,
}); });
} else { } else {
throw error; throw error;

View file

@ -9,7 +9,6 @@ import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
import type { IRecord } from './GenericFunction'; import type { IRecord } from './GenericFunction';
import { apiRequest, apiRequestAllItems } from './GenericFunction'; import { apiRequest, apiRequestAllItems } from './GenericFunction';
import { generatePairedItemData } from '../../utils/utilities';
export class Stackby implements INodeType { export class Stackby implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@ -284,11 +283,7 @@ export class Stackby implements INodeType {
); );
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
const itemData = generatePairedItemData(items.length); const executionErrorData = this.helpers.returnJsonArray({ error: error.message });
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData },
);
returnData.push(...executionErrorData); returnData.push(...executionErrorData);
} else { } else {
throw error; throw error;