From 1fde2d77785a4086bfec9ce8cef15a4ea6cf7f0c Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Fri, 19 Jan 2024 04:56:20 +0200 Subject: [PATCH 1/2] :zap: fix --- packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts b/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts index c246339c0ddf9..2df877965818b 100644 --- a/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts +++ b/packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts @@ -29,6 +29,7 @@ import { } from './GenericFunctions'; import { optionsDescription } from './OptionsDescription'; +import { generatePairedItemData } from '../../../utils/utilities'; const versionDescription: INodeTypeDescription = { displayName: 'Merge', @@ -599,7 +600,8 @@ export class MergeV2 implements INodeType { returnData.push.apply(returnData, this.getInputData(1)); } if (output === 'empty') { - returnData.push({ json: {} }); + const itemData = generatePairedItemData(this.getInputData(0).length); + returnData.push({ json: {}, pairedItem: itemData }); } } } From aaab501a7e694af74eca4a29cacac9d5c600ed63 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Fri, 19 Jan 2024 11:19:11 +0200 Subject: [PATCH 2/2] :zap: pairedItem fixes --- packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts | 2 ++ packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts | 5 +++++ .../nodes/Airtable/v2/actions/record/search.operation.ts | 2 ++ packages/nodes-base/nodes/Airtable/v2/transport/index.ts | 5 +++++ packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts | 4 +++- packages/nodes-base/nodes/NocoDB/GenericFunctions.ts | 5 +++++ packages/nodes-base/nodes/NocoDB/NocoDB.node.ts | 2 ++ packages/nodes-base/nodes/Notion/GenericFunctions.ts | 6 +++++- packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts | 4 +++- packages/nodes-base/nodes/Redis/Redis.node.ts | 2 +- packages/nodes-base/nodes/Set/v1/SetV1.node.ts | 2 +- 11 files changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts b/packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts index f24993b5a54b6..aebef1c310bad 100644 --- a/packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts +++ b/packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts @@ -718,10 +718,12 @@ export class AirtableV1 implements INodeType { const downloadFieldNames = ( this.getNodeParameter('downloadFieldNames', 0) as string ).split(','); + const pairedItem = generatePairedItemData(items.length); const data = await downloadRecordAttachments.call( this, responseData.records as IRecord[], downloadFieldNames, + pairedItem, ); return [data]; } diff --git a/packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts b/packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts index ea0f6b42735b9..d95c8b45fea13 100644 --- a/packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts @@ -7,6 +7,7 @@ import type { IPollFunctions, ILoadOptionsFunctions, INodeExecutionData, + IPairedItemData, } from 'n8n-workflow'; interface IAttachment { @@ -100,10 +101,14 @@ export async function downloadRecordAttachments( this: IExecuteFunctions | IPollFunctions, records: IRecord[], fieldNames: string[], + pairedItem?: IPairedItemData[], ): Promise { const elements: INodeExecutionData[] = []; for (const record of records) { const element: INodeExecutionData = { json: {}, binary: {} }; + if (pairedItem) { + element.pairedItem = pairedItem; + } element.json = record as unknown as IDataObject; for (const fieldName of fieldNames) { if (record.fields[fieldName] !== undefined) { diff --git a/packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts b/packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts index 75f4e47d9aead..e731f8b170ddd 100644 --- a/packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts +++ b/packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts @@ -194,10 +194,12 @@ export async function execute( returnData = responseData.records as INodeExecutionData[]; if (options.downloadFields) { + const pairedItem = generatePairedItemData(items.length); return await downloadRecordAttachments.call( this, responseData.records as IRecord[], options.downloadFields as string[], + pairedItem, ); } diff --git a/packages/nodes-base/nodes/Airtable/v2/transport/index.ts b/packages/nodes-base/nodes/Airtable/v2/transport/index.ts index bf2ff876fba50..591ce29deb9a5 100644 --- a/packages/nodes-base/nodes/Airtable/v2/transport/index.ts +++ b/packages/nodes-base/nodes/Airtable/v2/transport/index.ts @@ -7,6 +7,7 @@ import type { IPollFunctions, ILoadOptionsFunctions, INodeExecutionData, + IPairedItemData, } from 'n8n-workflow'; import { ApplicationError } from 'n8n-workflow'; import type { IAttachment, IRecord } from '../helpers/interfaces'; @@ -87,6 +88,7 @@ export async function downloadRecordAttachments( this: IExecuteFunctions | IPollFunctions, records: IRecord[], fieldNames: string | string[], + pairedItem?: IPairedItemData[], ): Promise { if (typeof fieldNames === 'string') { fieldNames = fieldNames.split(',').map((item) => item.trim()); @@ -99,6 +101,9 @@ export async function downloadRecordAttachments( const elements: INodeExecutionData[] = []; for (const record of records) { const element: INodeExecutionData = { json: {}, binary: {} }; + if (pairedItem) { + element.pairedItem = pairedItem; + } element.json = flattenOutput(record as unknown as IDataObject); for (const fieldName of fieldNames) { if (record.fields[fieldName] !== undefined) { diff --git a/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts b/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts index d0f10e29b21df..e8224d0eef4ac 100644 --- a/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts +++ b/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts @@ -13,6 +13,7 @@ import type { import { deepCopy } from 'n8n-workflow'; import { oldVersionNotice } from '@utils/descriptions'; +import { generatePairedItemData } from '../../../utils/utilities'; const versionDescription: INodeTypeDescription = { displayName: 'Merge', @@ -477,7 +478,8 @@ export class MergeV1 implements INodeType { returnData.push.apply(returnData, this.getInputData(1)); } } else if (mode === 'wait') { - returnData.push({ json: {} }); + const pairedItem = generatePairedItemData(this.getInputData(0).length); + returnData.push({ json: {}, pairedItem }); } return [returnData]; diff --git a/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts b/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts index 5edc220c5a944..8900cc04e3de5 100644 --- a/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts +++ b/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts @@ -7,6 +7,7 @@ import type { IHookFunctions, ILoadOptionsFunctions, INodeExecutionData, + IPairedItemData, IPollFunctions, } from 'n8n-workflow'; import { jsonParse, NodeOperationError } from 'n8n-workflow'; @@ -106,11 +107,15 @@ export async function downloadRecordAttachments( this: IExecuteFunctions | IPollFunctions, records: IDataObject[], fieldNames: string[], + pairedItem?: IPairedItemData[], ): Promise { const elements: INodeExecutionData[] = []; for (const record of records) { const element: INodeExecutionData = { json: {}, binary: {} }; + if (pairedItem) { + element.pairedItem = pairedItem; + } element.json = record as unknown as IDataObject; for (const fieldName of fieldNames) { let attachments = record[fieldName] as IAttachment[]; diff --git a/packages/nodes-base/nodes/NocoDB/NocoDB.node.ts b/packages/nodes-base/nodes/NocoDB/NocoDB.node.ts index fd010508f0bbd..4fffdaaa421f0 100644 --- a/packages/nodes-base/nodes/NocoDB/NocoDB.node.ts +++ b/packages/nodes-base/nodes/NocoDB/NocoDB.node.ts @@ -521,6 +521,7 @@ export class NocoDB implements INodeType { this, responseData as IDataObject[], downloadFieldNames, + [{ item: i }], ); data.push(...response); } @@ -584,6 +585,7 @@ export class NocoDB implements INodeType { this, [responseData as IDataObject], downloadFieldNames, + [{ item: i }], ); const newItem = { binary: data[0].binary, diff --git a/packages/nodes-base/nodes/Notion/GenericFunctions.ts b/packages/nodes-base/nodes/Notion/GenericFunctions.ts index 54f872b91da8a..73190752e323b 100644 --- a/packages/nodes-base/nodes/Notion/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Notion/GenericFunctions.ts @@ -9,6 +9,7 @@ import type { ILoadOptionsFunctions, INodeExecutionData, INodeProperties, + IPairedItemData, IPollFunctions, JsonObject, } from 'n8n-workflow'; @@ -860,12 +861,15 @@ export type FileRecord = { }; }; // prettier-ignore -export async function downloadFiles(this: IExecuteFunctions | IPollFunctions, records: FileRecord[]): Promise { +export async function downloadFiles(this: IExecuteFunctions | IPollFunctions, records: FileRecord[], pairedItem?: IPairedItemData[]): Promise { const elements: INodeExecutionData[] = []; for (const record of records) { const element: INodeExecutionData = { json: {}, binary: {} }; element.json = record as unknown as IDataObject; + if (pairedItem) { + element.pairedItems = pairedItem; + } for (const key of Object.keys(record.properties)) { if (record.properties[key].type === 'files') { if (record.properties[key].files.length) { diff --git a/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts b/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts index 4bb9afca5450b..2809f8ff9ea9f 100644 --- a/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts +++ b/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts @@ -591,7 +591,9 @@ export class NotionV2 implements INodeType { responseData = responseData.results; } if (download) { - responseData = await downloadFiles.call(this, responseData as FileRecord[]); + responseData = await downloadFiles.call(this, responseData as FileRecord[], [ + { item: i }, + ]); } if (simple) { responseData = simplifyObjects(responseData, download); diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 414176db949c6..70d2dfc681f09 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -530,7 +530,7 @@ export class Redis implements INodeType { let item: INodeExecutionData; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { - item = { json: {} }; + item = { json: {}, pairedItem: { item: itemIndex } }; if (operation === 'delete') { const keyDelete = this.getNodeParameter('key', itemIndex) as string; diff --git a/packages/nodes-base/nodes/Set/v1/SetV1.node.ts b/packages/nodes-base/nodes/Set/v1/SetV1.node.ts index d4a08a2e73362..b505b62451b58 100644 --- a/packages/nodes-base/nodes/Set/v1/SetV1.node.ts +++ b/packages/nodes-base/nodes/Set/v1/SetV1.node.ts @@ -150,7 +150,7 @@ export class SetV1 implements INodeType { const nodeVersion = this.getNode().typeVersion; if (items.length === 0) { - items.push({ json: {} }); + items.push({ json: {}, pairedItem: { item: 0 } }); } const returnData: INodeExecutionData[] = [];