mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 12:44:07 -08:00
fix(core): Missing pairing info (#7326)
Github issue / Community forum post (link here to close automatically):
This commit is contained in:
parent
6479eb180f
commit
e2c3c7aceb
|
@ -61,9 +61,11 @@ describe('Test AirtableV2, base => getMany', () => {
|
|||
name: 'base 1',
|
||||
permissionLevel: 'create',
|
||||
},
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
json: {
|
||||
|
@ -71,9 +73,11 @@ describe('Test AirtableV2, base => getMany', () => {
|
|||
name: 'base 2',
|
||||
permissionLevel: 'edit',
|
||||
},
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
json: {
|
||||
|
@ -81,9 +85,11 @@ describe('Test AirtableV2, base => getMany', () => {
|
|||
name: 'base 3',
|
||||
permissionLevel: 'create',
|
||||
},
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -107,9 +113,11 @@ describe('Test AirtableV2, base => getMany', () => {
|
|||
name: 'base 2',
|
||||
permissionLevel: 'edit',
|
||||
},
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -16,6 +16,9 @@ export const node: INode = {
|
|||
|
||||
export const createMockExecuteFunction = (nodeParameters: IDataObject) => {
|
||||
const fakeExecuteFunction = {
|
||||
getInputData() {
|
||||
return [{ json: {} }];
|
||||
},
|
||||
getNodeParameter(
|
||||
parameterName: string,
|
||||
_itemIndex: number,
|
||||
|
|
|
@ -110,9 +110,11 @@ describe('Test AirtableV2, search operation', () => {
|
|||
expect(result).toHaveLength(2);
|
||||
expect(result[0]).toEqual({
|
||||
json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' },
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -152,9 +154,11 @@ describe('Test AirtableV2, search operation', () => {
|
|||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual({
|
||||
json: { id: 'recYYY', foo: 'foo 2', bar: 'bar 2' },
|
||||
pairedItem: {
|
||||
pairedItem: [
|
||||
{
|
||||
item: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import type { IRecord } from './GenericFunctions';
|
|||
import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from './GenericFunctions';
|
||||
|
||||
import { oldVersionNotice } from '../../../utils/descriptions';
|
||||
import { generatePairedItemData } from '../../../utils/utilities';
|
||||
|
||||
const versionDescription: INodeTypeDescription = {
|
||||
displayName: 'Airtable',
|
||||
|
@ -727,9 +728,11 @@ export class AirtableV1 implements INodeType {
|
|||
}
|
||||
|
||||
// We can return from here
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
return [
|
||||
this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(returnData), {
|
||||
itemData: { item: 0 },
|
||||
itemData,
|
||||
}),
|
||||
];
|
||||
} catch (error) {
|
||||
|
|
|
@ -4,7 +4,11 @@ import type {
|
|||
INodeProperties,
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-workflow';
|
||||
import { updateDisplayOptions, wrapData } from '../../../../../utils/utilities';
|
||||
import {
|
||||
generatePairedItemData,
|
||||
updateDisplayOptions,
|
||||
wrapData,
|
||||
} from '../../../../../utils/utilities';
|
||||
import { apiRequest } from '../../transport';
|
||||
|
||||
const properties: INodeProperties[] = [
|
||||
|
@ -107,8 +111,10 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
bases = bases.filter((base) => permissionLevel.includes(base.permissionLevel as string));
|
||||
}
|
||||
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
|
||||
const returnData = this.helpers.constructExecutionMetaData(wrapData(bases), {
|
||||
itemData: { item: 0 },
|
||||
itemData,
|
||||
});
|
||||
|
||||
return returnData;
|
||||
|
|
|
@ -4,7 +4,7 @@ import type {
|
|||
INodeProperties,
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-workflow';
|
||||
import { updateDisplayOptions } from '../../../../../utils/utilities';
|
||||
import { generatePairedItemData, updateDisplayOptions } from '../../../../../utils/utilities';
|
||||
import { apiRequest, apiRequestAllItems, downloadRecordAttachments } from '../../transport';
|
||||
import type { IRecord } from '../../helpers/interfaces';
|
||||
import { flattenOutput } from '../../helpers/utils';
|
||||
|
@ -205,8 +205,10 @@ export async function execute(
|
|||
json: flattenOutput(record as IDataObject),
|
||||
}));
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
returnData = this.helpers.constructExecutionMetaData(returnData, {
|
||||
itemData: { item: 0 },
|
||||
itemData,
|
||||
});
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import unset from 'lodash/unset';
|
|||
import { cloneDeep } from 'lodash';
|
||||
import set from 'lodash/set';
|
||||
import union from 'lodash/union';
|
||||
import { fuzzyCompare } from '@utils/utilities';
|
||||
import { fuzzyCompare, preparePairedItemDataArray } from '@utils/utilities';
|
||||
|
||||
type PairToMatch = {
|
||||
field1: string;
|
||||
|
@ -141,6 +141,10 @@ function compareItems(
|
|||
|
||||
return {
|
||||
json: { keys, same, different, ...(!isEmpty(skipped) && { skipped }) },
|
||||
pairedItem: [
|
||||
...preparePairedItemDataArray(item1.pairedItem),
|
||||
...preparePairedItemDataArray(item2.pairedItem),
|
||||
],
|
||||
} as INodeExecutionData;
|
||||
}
|
||||
|
||||
|
|
|
@ -340,6 +340,10 @@ export class Filter implements INodeType {
|
|||
value2,
|
||||
);
|
||||
|
||||
if (item.pairedItem === undefined) {
|
||||
item.pairedItem = [{ item: itemIndex }];
|
||||
}
|
||||
|
||||
// If the operation is "OR" it means the item did match one condition no ned to check further
|
||||
if (compareResult && combineConditions === 'OR') {
|
||||
returnDataTrue.push(item);
|
||||
|
|
|
@ -20,6 +20,7 @@ import { recordFields, recordOperations } from './RecordDescription';
|
|||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { oldVersionNotice } from '@utils/descriptions';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
const versionDescription: INodeTypeDescription = {
|
||||
displayName: 'Google BigQuery',
|
||||
|
@ -198,6 +199,8 @@ export class GoogleBigQueryV1 implements INodeType {
|
|||
|
||||
body.rows = rows;
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
try {
|
||||
responseData = await googleApiRequest.call(
|
||||
this,
|
||||
|
@ -208,14 +211,14 @@ export class GoogleBigQueryV1 implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import type {
|
|||
} from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { updateDisplayOptions } from '@utils/utilities';
|
||||
import { generatePairedItemData, updateDisplayOptions } from '@utils/utilities';
|
||||
import type { TableSchema } from '../../helpers/interfaces';
|
||||
import { checkSchema, wrapData } from '../../helpers/utils';
|
||||
import { googleApiRequest } from '../../transport';
|
||||
|
@ -225,6 +225,7 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
}
|
||||
}
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
for (let i = 0; i < rows.length; i += batchSize) {
|
||||
const batch = rows.slice(i, i + batchSize);
|
||||
body.rows = batch;
|
||||
|
@ -279,7 +280,7 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
import { collectionFields, collectionOperations } from './CollectionDescription';
|
||||
|
||||
import { documentFields, documentOperations } from './DocumentDescription';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
export class GoogleFirebaseCloudFirestore implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -90,6 +91,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
|
@ -130,7 +132,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -213,7 +215,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -395,7 +397,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
|
|
@ -26,6 +26,7 @@ import { googleApiRequest, hexToRgb } from './GenericFunctions';
|
|||
|
||||
import { versionDescription } from './versionDescription';
|
||||
import { getGoogleAccessToken } from '../../GenericFunctions';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
export class GoogleSheetsV1 implements INodeType {
|
||||
description: INodeTypeDescription;
|
||||
|
@ -295,7 +296,16 @@ export class GoogleSheetsV1 implements INodeType {
|
|||
returnData = [];
|
||||
}
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
const pairedItem = generatePairedItemData(items.length);
|
||||
|
||||
const lookupOutput = returnData.map((item) => {
|
||||
return {
|
||||
json: item,
|
||||
pairedItem,
|
||||
};
|
||||
});
|
||||
|
||||
return [lookupOutput];
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [this.helpers.returnJsonArray({ error: error.message })];
|
||||
|
|
|
@ -234,6 +234,13 @@ export async function execute(
|
|||
if (nodeVersion < 4 || dataMode === 'autoMapInputData') {
|
||||
return items;
|
||||
} else {
|
||||
return this.helpers.returnJsonArray(setData);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
for (const [index, entry] of setData.entries()) {
|
||||
returnData.push({
|
||||
json: entry,
|
||||
pairedItems: { item: index },
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -387,6 +387,13 @@ export async function execute(
|
|||
if (nodeVersion < 4 || dataMode === 'autoMapInputData') {
|
||||
return items;
|
||||
} else {
|
||||
return this.helpers.returnJsonArray(mappedValues);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
for (const [index, entry] of mappedValues.entries()) {
|
||||
returnData.push({
|
||||
json: entry,
|
||||
pairedItems: { item: index },
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import type { SheetProperties } from '../../helpers/GoogleSheets.types';
|
|||
import { apiRequest } from '../../transport';
|
||||
import type { GoogleSheet } from '../../helpers/GoogleSheet';
|
||||
import { getExistingSheetNames, hexToRgb } from '../../helpers/GoogleSheets.utils';
|
||||
import { wrapData } from '../../../../../../utils/utilities';
|
||||
|
||||
export const description: SheetProperties = [
|
||||
{
|
||||
|
@ -78,7 +79,7 @@ export async function execute(
|
|||
sheetName: string,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
let responseData;
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const items = this.getInputData();
|
||||
|
||||
const existingSheetNames = await getExistingSheetNames(sheet);
|
||||
|
@ -120,7 +121,12 @@ export async function execute(
|
|||
|
||||
existingSheetNames.push(sheetTitle);
|
||||
|
||||
returnData.push(responseData as IDataObject);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
return this.helpers.returnJsonArray(returnData);
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-wor
|
|||
import type { SheetProperties } from '../../helpers/GoogleSheets.types';
|
||||
import type { GoogleSheet } from '../../helpers/GoogleSheet';
|
||||
import { getColumnNumber, untilSheetSelected } from '../../helpers/GoogleSheets.utils';
|
||||
import { generatePairedItemData, wrapData } from '../../../../../../utils/utilities';
|
||||
|
||||
export const description: SheetProperties = [
|
||||
{
|
||||
|
@ -164,5 +165,10 @@ export async function execute(
|
|||
await sheet.spreadsheetBatchUpdate(requests);
|
||||
}
|
||||
|
||||
return this.helpers.returnJsonArray({ success: true });
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
const returnData = this.helpers.constructExecutionMetaData(wrapData({ success: true }), {
|
||||
itemData,
|
||||
});
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import type {
|
|||
SheetRangeData,
|
||||
ValueRenderOption,
|
||||
} from '../../helpers/GoogleSheets.types';
|
||||
import { generatePairedItemData } from '../../../../../../utils/utilities';
|
||||
|
||||
export const description: SheetProperties = [
|
||||
{
|
||||
|
@ -139,7 +140,7 @@ export async function execute(
|
|||
|
||||
const { data, headerRow, firstDataRow } = prepareSheetData(sheetData, dataLocationOnSheetOptions);
|
||||
|
||||
let returnData = [];
|
||||
let responseData = [];
|
||||
|
||||
const lookupValues = this.getNodeParameter('filtersUI.values', 0, []) as ILookupValues[];
|
||||
|
||||
|
@ -154,7 +155,7 @@ export async function execute(
|
|||
}
|
||||
}
|
||||
|
||||
returnData = await sheet.lookupValues(
|
||||
responseData = await sheet.lookupValues(
|
||||
data as string[][],
|
||||
headerRow,
|
||||
firstDataRow,
|
||||
|
@ -162,8 +163,18 @@ export async function execute(
|
|||
returnAllMatches,
|
||||
);
|
||||
} else {
|
||||
returnData = sheet.structureArrayDataByColumn(data as string[][], headerRow, firstDataRow);
|
||||
responseData = sheet.structureArrayDataByColumn(data as string[][], headerRow, firstDataRow);
|
||||
}
|
||||
|
||||
return this.helpers.returnJsonArray(returnData);
|
||||
const items = this.getInputData();
|
||||
const pairedItem = generatePairedItemData(items.length);
|
||||
|
||||
const returnData: INodeExecutionData[] = responseData.map((item, index) => {
|
||||
return {
|
||||
json: item,
|
||||
pairedItem,
|
||||
};
|
||||
});
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||
import { apiRequest } from '../../transport';
|
||||
import type { GoogleSheet } from '../../helpers/GoogleSheet';
|
||||
import { wrapData } from '../../../../../../utils/utilities';
|
||||
|
||||
export async function execute(
|
||||
this: IExecuteFunctions,
|
||||
sheet: GoogleSheet,
|
||||
sheetName: string,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const items = this.getInputData();
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const [spreadsheetId, sheetWithinDocument] = sheetName.split('||');
|
||||
|
@ -26,8 +27,14 @@ export async function execute(
|
|||
{ requests },
|
||||
);
|
||||
delete responseData.replies;
|
||||
returnData.push(responseData as IDataObject);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
return this.helpers.returnJsonArray(returnData);
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -380,6 +380,14 @@ export async function execute(
|
|||
if (!updateData.length) {
|
||||
return [];
|
||||
}
|
||||
return this.helpers.returnJsonArray(mappedValues);
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
for (const [index, entry] of mappedValues.entries()) {
|
||||
returnData.push({
|
||||
json: entry,
|
||||
pairedItems: { item: index },
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||
import type { SpreadSheetProperties } from '../../helpers/GoogleSheets.types';
|
||||
import { apiRequest } from '../../transport';
|
||||
import { wrapData } from '../../../../../../utils/utilities';
|
||||
|
||||
export const description: SpreadSheetProperties = [
|
||||
{
|
||||
|
@ -115,7 +116,7 @@ export const description: SpreadSheetProperties = [
|
|||
|
||||
export async function execute(this: IExecuteFunctions): Promise<INodeExecutionData[]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const title = this.getNodeParameter('title', i) as string;
|
||||
|
@ -145,8 +146,14 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
body.properties.locale = options.locale ? (options.locale as string) : undefined;
|
||||
|
||||
const response = await apiRequest.call(this, 'POST', '/v4/spreadsheets', body);
|
||||
returnData.push(response as IDataObject);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(response as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
return this.helpers.returnJsonArray(returnData);
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
import type { SpreadSheetProperties } from '../../helpers/GoogleSheets.types';
|
||||
import { apiRequest } from '../../transport';
|
||||
import { GOOGLE_DRIVE_FILE_URL_REGEX } from '../../../../constants';
|
||||
import { wrapData } from '../../../../../../utils/utilities';
|
||||
|
||||
export const description: SpreadSheetProperties = [
|
||||
// {
|
||||
// displayName: 'Spreadsheet ID',
|
||||
// name: 'spreadsheetId',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// resource: ['spreadsheet'],
|
||||
// operation: ['deleteSpreadsheet'],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
{
|
||||
displayName: 'Document',
|
||||
name: 'documentId',
|
||||
|
@ -77,7 +66,7 @@ export const description: SpreadSheetProperties = [
|
|||
|
||||
export async function execute(this: IExecuteFunctions): Promise<INodeExecutionData[]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
// const spreadsheetId = this.getNodeParameter('spreadsheetId', i) as string;
|
||||
|
@ -94,8 +83,12 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
`https://www.googleapis.com/drive/v3/files/${documentId}`,
|
||||
);
|
||||
|
||||
returnData.push({ success: true });
|
||||
const executionData = this.helpers.constructExecutionMetaData(wrapData({ success: true }), {
|
||||
itemData: { item: i },
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
return this.helpers.returnJsonArray(returnData);
|
||||
return returnData;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import type { IForm } from './FormInterface';
|
|||
import type { IAssociation, IDeal } from './DealInterface';
|
||||
|
||||
import { snakeCase } from 'change-case';
|
||||
import { generatePairedItemData } from '../../../utils/utilities';
|
||||
|
||||
export class HubspotV2 implements INodeType {
|
||||
description: INodeTypeDescription;
|
||||
|
@ -1168,9 +1169,12 @@ export class HubspotV2 implements INodeType {
|
|||
body,
|
||||
);
|
||||
}
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
|
@ -3030,7 +3034,10 @@ export class HubspotV2 implements INodeType {
|
|||
throw new NodeOperationError(this.getNode(), error as string);
|
||||
}
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ json: { error: (error as JsonObject).message } });
|
||||
returnData.push({
|
||||
json: { error: (error as JsonObject).message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
|
|
|
@ -470,6 +470,10 @@ export class If implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
if (item.pairedItem === undefined) {
|
||||
item.pairedItem = [{ item: itemIndex }];
|
||||
}
|
||||
|
||||
if (combineOperation === 'all') {
|
||||
// If the operation is "all" it means the item did match all conditions
|
||||
// so it passes.
|
||||
|
|
|
@ -15,6 +15,7 @@ import type {
|
|||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
export class Kafka implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -257,6 +258,7 @@ export class Kafka implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
const length = items.length;
|
||||
|
||||
|
@ -396,10 +398,15 @@ export class Kafka implements INodeType {
|
|||
|
||||
await producer.disconnect();
|
||||
|
||||
return [this.helpers.returnJsonArray(responseData)];
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
return [executionData];
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [this.helpers.returnJsonArray({ error: error.message })];
|
||||
return [[{ json: { error: error.message }, pairedItem: itemData }]];
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import assignWith from 'lodash/assignWith';
|
|||
import get from 'lodash/get';
|
||||
import merge from 'lodash/merge';
|
||||
import mergeWith from 'lodash/mergeWith';
|
||||
import { fuzzyCompare } from '@utils/utilities';
|
||||
import { fuzzyCompare, preparePairedItemDataArray } from '@utils/utilities';
|
||||
|
||||
type PairToMatch = {
|
||||
field1: string;
|
||||
|
@ -257,6 +257,7 @@ export function mergeMatched(
|
|||
|
||||
let json: IDataObject = {};
|
||||
let binary: IBinaryKeyData = {};
|
||||
let pairedItem: IPairedItemData[] = [];
|
||||
|
||||
if (resolveClash === 'addSuffix') {
|
||||
const suffix1 = '1';
|
||||
|
@ -270,6 +271,10 @@ export function mergeMatched(
|
|||
{ ...entry.binary },
|
||||
...matches.map((item) => item.binary as IDataObject),
|
||||
);
|
||||
pairedItem = [
|
||||
...preparePairedItemDataArray(entry.pairedItem),
|
||||
...matches.map((item) => preparePairedItemDataArray(item.pairedItem)).flat(),
|
||||
];
|
||||
} else {
|
||||
const preferInput1 = 'preferInput1';
|
||||
const preferInput2 = 'preferInput2';
|
||||
|
@ -294,6 +299,12 @@ export function mergeMatched(
|
|||
...restMatches.map((item) => item.binary as IDataObject),
|
||||
entry.binary as IDataObject,
|
||||
);
|
||||
|
||||
pairedItem = [
|
||||
...preparePairedItemDataArray(firstMatch.pairedItem),
|
||||
...restMatches.map((item) => preparePairedItemDataArray(item.pairedItem)).flat(),
|
||||
...preparePairedItemDataArray(entry.pairedItem),
|
||||
];
|
||||
}
|
||||
|
||||
if (resolveClash === preferInput2) {
|
||||
|
@ -302,13 +313,12 @@ export function mergeMatched(
|
|||
{ ...entry.binary },
|
||||
...matches.map((item) => item.binary as IDataObject),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const pairedItem = [
|
||||
entry.pairedItem as IPairedItemData,
|
||||
...matches.map((m) => m.pairedItem as IPairedItemData),
|
||||
pairedItem = [
|
||||
...preparePairedItemDataArray(entry.pairedItem),
|
||||
...matches.map((item) => preparePairedItemDataArray(item.pairedItem)).flat(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
returnData.push({
|
||||
json,
|
||||
|
|
|
@ -19,6 +19,9 @@ const node: INode = {
|
|||
|
||||
const fakeExecute = (nodeParameters: IDataObject[]) => {
|
||||
const fakeExecuteFunction = {
|
||||
getInputData() {
|
||||
return [{ json: {} }];
|
||||
},
|
||||
getNodeParameter(
|
||||
parameterName: string,
|
||||
itemIndex: number,
|
||||
|
@ -90,6 +93,9 @@ const responseData = {
|
|||
describe('Test MicrosoftExcelV2, prepareOutput', () => {
|
||||
const thisArg = mock<IExecuteFunctions>({
|
||||
helpers: mock({ constructExecutionMetaData }),
|
||||
getInputData() {
|
||||
return [{ json: {} }];
|
||||
},
|
||||
});
|
||||
|
||||
it('should return empty array', () => {
|
||||
|
|
|
@ -25,6 +25,7 @@ import { worksheetFields, worksheetOperations } from './WorksheetDescription';
|
|||
import { tableFields, tableOperations } from './TableDescription';
|
||||
|
||||
import { oldVersionNotice } from '@utils/descriptions';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
const versionDescription: INodeTypeDescription = {
|
||||
displayName: 'Microsoft Excel',
|
||||
|
@ -176,6 +177,7 @@ export class MicrosoftExcelV1 implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
let qs: IDataObject = {};
|
||||
|
@ -249,7 +251,7 @@ export class MicrosoftExcelV1 implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -257,7 +259,7 @@ export class MicrosoftExcelV1 implements INodeType {
|
|||
if (this.continueOnFail()) {
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,7 @@ import type {
|
|||
INodeExecutionData,
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import type { ExcelResponse } from '../../helpers/interfaces';
|
||||
import { prepareOutput } from '../../helpers/utils';
|
||||
import { microsoftApiRequest } from '../../transport';
|
||||
|
@ -272,9 +272,10 @@ export async function execute(
|
|||
);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
} else {
|
||||
|
|
|
@ -5,7 +5,7 @@ import type {
|
|||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
|
||||
import { prepareOutput, updateByAutoMaping, updateByDefinedValues } from '../../helpers/utils';
|
||||
import { microsoftApiRequest } from '../../transport';
|
||||
|
@ -366,9 +366,10 @@ export async function execute(
|
|||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
} else {
|
||||
|
|
|
@ -5,7 +5,7 @@ import type {
|
|||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import { generatePairedItemData, processJsonInput, updateDisplayOptions } from '@utils/utilities';
|
||||
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
|
||||
import { prepareOutput, updateByAutoMaping, updateByDefinedValues } from '../../helpers/utils';
|
||||
import { microsoftApiRequest } from '../../transport';
|
||||
|
@ -323,9 +323,10 @@ export async function execute(
|
|||
);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { IDataObject, IExecuteFunctions, INode, INodeExecutionData } from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import type { ExcelResponse, SheetData, UpdateSummary } from './interfaces';
|
||||
import { wrapData } from '@utils/utilities';
|
||||
import { generatePairedItemData, wrapData } from '@utils/utilities';
|
||||
|
||||
type PrepareOutputConfig = {
|
||||
rawData: boolean;
|
||||
|
@ -60,9 +60,10 @@ export function prepareOutput(
|
|||
returnData.push(...executionData);
|
||||
}
|
||||
} else {
|
||||
const itemData = generatePairedItemData(this.getInputData().length);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData({ [config.dataProperty || 'data']: responseData }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
extractValues,
|
||||
formatColumns,
|
||||
} from './GenericFunctions';
|
||||
import { chunk, flatten, getResolvables } from '@utils/utilities';
|
||||
import { chunk, flatten, generatePairedItemData, getResolvables } from '@utils/utilities';
|
||||
|
||||
export class MicrosoftSql implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -442,9 +442,11 @@ export class MicrosoftSql implements INodeType {
|
|||
|
||||
// Close the connection
|
||||
await pool.close();
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnItems.push(...executionData);
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
} from './GenericFunctions';
|
||||
|
||||
import type { IMongoParametricCredentials } from './mongoDb.types';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
export class MongoDb implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -365,9 +366,11 @@ export class MongoDb implements INodeType {
|
|||
|
||||
stringifyObjectIDs(responseData);
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnItems.push(...executionData);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { IDataObject, INode } from 'n8n-workflow';
|
||||
|
||||
import { createMockExecuteFunction } from '@test/nodes/Helpers';
|
||||
|
||||
import mysql2 from 'mysql2/promise';
|
||||
import * as deleteTable from '../../v2/actions/database/deleteTable.operation';
|
||||
|
||||
import * as executeQuery from '../../v2/actions/database/executeQuery.operation';
|
||||
import * as insert from '../../v2/actions/database/insert.operation';
|
||||
import * as select from '../../v2/actions/database/select.operation';
|
||||
|
@ -11,8 +11,7 @@ import * as upsert from '../../v2/actions/database/upsert.operation';
|
|||
|
||||
import type { Mysql2Pool, QueryRunner } from '../../v2/helpers/interfaces';
|
||||
import { configureQueryRunner } from '../../v2/helpers/utils';
|
||||
|
||||
import mysql2 from 'mysql2/promise';
|
||||
import { createMockExecuteFunction } from '@test/nodes/Helpers';
|
||||
|
||||
const mySqlMockNode: INode = {
|
||||
id: '1',
|
||||
|
@ -97,7 +96,7 @@ describe('Test MySql V2, operations', () => {
|
|||
const result = await deleteTable.execute.call(fakeExecuteFunction, emptyInputItems, runQueries);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]);
|
||||
|
||||
expect(poolQuerySpy).toBeCalledTimes(1);
|
||||
expect(poolQuerySpy).toBeCalledWith('DROP TABLE IF EXISTS `test_table`');
|
||||
|
@ -133,7 +132,7 @@ describe('Test MySql V2, operations', () => {
|
|||
const result = await deleteTable.execute.call(fakeExecuteFunction, emptyInputItems, runQueries);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]);
|
||||
|
||||
expect(poolQuerySpy).toBeCalledTimes(1);
|
||||
expect(poolQuerySpy).toBeCalledWith('TRUNCATE TABLE `test_table`');
|
||||
|
@ -183,7 +182,7 @@ describe('Test MySql V2, operations', () => {
|
|||
const result = await deleteTable.execute.call(fakeExecuteFunction, emptyInputItems, runQueries);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]);
|
||||
|
||||
expect(poolQuerySpy).toBeCalledTimes(1);
|
||||
expect(poolQuerySpy).toBeCalledWith(
|
||||
|
@ -312,7 +311,7 @@ describe('Test MySql V2, operations', () => {
|
|||
const result = await select.execute.call(fakeExecuteFunction, emptyInputItems, runQueries);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: { item: 0 } }]);
|
||||
|
||||
const connectionBeginTransactionSpy = jest.spyOn(fakeConnection, 'beginTransaction');
|
||||
const connectionCommitSpy = jest.spyOn(fakeConnection, 'commit');
|
||||
|
@ -378,7 +377,7 @@ describe('Test MySql V2, operations', () => {
|
|||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: { item: 0 } }]);
|
||||
|
||||
expect(connectionQuerySpy).toBeCalledTimes(1);
|
||||
expect(connectionQuerySpy).toBeCalledWith(
|
||||
|
@ -439,7 +438,10 @@ describe('Test MySql V2, operations', () => {
|
|||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }, { json: { success: true } }]);
|
||||
expect(result).toEqual([
|
||||
{ json: { success: true }, pairedItem: { item: 0 } },
|
||||
{ json: { success: true }, pairedItem: { item: 1 } },
|
||||
]);
|
||||
|
||||
expect(connectionQuerySpy).toBeCalledTimes(2);
|
||||
expect(connectionQuerySpy).toBeCalledWith(
|
||||
|
@ -501,7 +503,7 @@ describe('Test MySql V2, operations', () => {
|
|||
);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }, { item: 1 }] }]);
|
||||
|
||||
expect(poolQuerySpy).toBeCalledTimes(1);
|
||||
expect(poolQuerySpy).toBeCalledWith(
|
||||
|
|
|
@ -67,7 +67,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]);
|
||||
|
||||
expect(poolGetConnectionSpy).toBeCalledTimes(1);
|
||||
|
||||
|
@ -108,7 +108,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: { item: 0 } }]);
|
||||
|
||||
expect(poolGetConnectionSpy).toBeCalledTimes(1);
|
||||
|
||||
|
@ -155,7 +155,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: { item: 0 } }]);
|
||||
|
||||
expect(poolGetConnectionSpy).toBeCalledTimes(1);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import type {
|
|||
} from './interfaces';
|
||||
|
||||
import { BATCH_MODE } from './interfaces';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
export const prepareQueryAndReplacements = (rawQuery: string, replacements?: QueryValues) => {
|
||||
if (replacements === undefined) {
|
||||
|
@ -122,6 +123,7 @@ export function prepareOutput(
|
|||
itemData: IPairedItemData | IPairedItemData[];
|
||||
},
|
||||
) => NodeExecutionWithMetadata[],
|
||||
itemData: IPairedItemData | IPairedItemData[],
|
||||
) {
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
|
@ -133,7 +135,7 @@ export function prepareOutput(
|
|||
};
|
||||
|
||||
const executionData = constructExecutionHelper(wrapData(item), {
|
||||
itemData: { item: index },
|
||||
itemData,
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -141,9 +143,9 @@ export function prepareOutput(
|
|||
} else {
|
||||
response
|
||||
.filter((entry) => Array.isArray(entry))
|
||||
.forEach((entry, index) => {
|
||||
.forEach((entry) => {
|
||||
const executionData = constructExecutionHelper(wrapData(entry), {
|
||||
itemData: { item: index },
|
||||
itemData,
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -152,7 +154,7 @@ export function prepareOutput(
|
|||
|
||||
if (!returnData.length) {
|
||||
if ((options?.nodeVersion as number) < 2.2) {
|
||||
returnData.push({ json: { success: true } });
|
||||
returnData.push({ json: { success: true }, pairedItem: itemData });
|
||||
} else {
|
||||
const isSelectQuery = statements
|
||||
.filter((statement) => !statement.startsWith('--'))
|
||||
|
@ -165,7 +167,7 @@ export function prepareOutput(
|
|||
);
|
||||
|
||||
if (!isSelectQuery) {
|
||||
returnData.push({ json: { success: true } });
|
||||
returnData.push({ json: { success: true }, pairedItem: itemData });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,8 +220,17 @@ export function configureQueryRunner(
|
|||
response = [response];
|
||||
}
|
||||
|
||||
//because single query is used in this mode mapping itemIndex not posible, setting all items as paired
|
||||
const pairedItem = generatePairedItemData(queries.length);
|
||||
|
||||
returnData.push(
|
||||
...prepareOutput(response, options, statements, this.helpers.constructExecutionMetaData),
|
||||
...prepareOutput(
|
||||
response,
|
||||
options,
|
||||
statements,
|
||||
this.helpers.constructExecutionMetaData,
|
||||
pairedItem,
|
||||
),
|
||||
);
|
||||
} catch (err) {
|
||||
const error = parseMySqlError.call(this, err, 0, formatedQueries);
|
||||
|
@ -250,6 +261,7 @@ export function configureQueryRunner(
|
|||
options,
|
||||
statements,
|
||||
this.helpers.constructExecutionMetaData,
|
||||
{ item: index },
|
||||
),
|
||||
);
|
||||
} catch (err) {
|
||||
|
@ -288,6 +300,7 @@ export function configureQueryRunner(
|
|||
options,
|
||||
statements,
|
||||
this.helpers.constructExecutionMetaData,
|
||||
{ item: index },
|
||||
),
|
||||
);
|
||||
} catch (err) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { URLSearchParams } from 'url';
|
|||
import { parseString } from 'xml2js';
|
||||
|
||||
import { nextCloudApiRequest } from './GenericFunctions';
|
||||
import { wrapData } from '../../utils/utilities';
|
||||
|
||||
export class NextCloud implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -860,7 +861,7 @@ export class NextCloud implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData().slice();
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||
let credentials;
|
||||
|
@ -1103,7 +1104,7 @@ export class NextCloud implements INodeType {
|
|||
if (resource === 'file' && operation === 'download') {
|
||||
items[i].json = { error: error.message };
|
||||
} else {
|
||||
returnData.push({ error: error.message });
|
||||
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1114,6 +1115,7 @@ export class NextCloud implements INodeType {
|
|||
if (resource === 'file' && operation === 'download') {
|
||||
const newItem: INodeExecutionData = {
|
||||
json: items[i].json,
|
||||
pairedItem: { item: i },
|
||||
binary: {},
|
||||
};
|
||||
|
||||
|
@ -1153,7 +1155,12 @@ export class NextCloud implements INodeType {
|
|||
});
|
||||
});
|
||||
|
||||
returnData.push(jsonResponseData);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(jsonResponseData),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} else if (resource === 'user') {
|
||||
if (operation !== 'getAll') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||
|
@ -1180,7 +1187,12 @@ export class NextCloud implements INodeType {
|
|||
});
|
||||
});
|
||||
|
||||
returnData.push(jsonResponseData);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(jsonResponseData),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||
const jsonResponseData: IDataObject[] = await new Promise((resolve, reject) => {
|
||||
|
@ -1204,7 +1216,7 @@ export class NextCloud implements INodeType {
|
|||
});
|
||||
|
||||
jsonResponseData.forEach((value) => {
|
||||
returnData.push({ id: value } as IDataObject);
|
||||
returnData.push({ json: { id: value }, pairedItem: { item: i } });
|
||||
});
|
||||
}
|
||||
} else if (resource === 'folder' && operation === 'list') {
|
||||
|
@ -1265,19 +1277,23 @@ export class NextCloud implements INodeType {
|
|||
// @ts-ignore
|
||||
newItem.eTag = props['d:getetag'].slice(1, -1);
|
||||
|
||||
returnData.push(newItem);
|
||||
returnData.push({ json: newItem, pairedItem: { item: i } });
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
returnData.push(responseData as IDataObject);
|
||||
const executionData = this.helpers.constructExecutionMetaData(wrapData(responseData), {
|
||||
itemData: { item: i },
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
if (resource === 'file' && operation === 'download') {
|
||||
items[i].json = { error: error.message };
|
||||
} else {
|
||||
returnData.push({ error: error.message });
|
||||
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1290,7 +1306,7 @@ export class NextCloud implements INodeType {
|
|||
return [items];
|
||||
} else {
|
||||
// For all other ones does the output get replaced
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4887,6 +4887,7 @@ export class Pipedrive implements INodeType {
|
|||
if (resource === 'file' && operation === 'download') {
|
||||
const newItem: INodeExecutionData = {
|
||||
json: items[i].json,
|
||||
pairedItem: { item: i },
|
||||
binary: {},
|
||||
};
|
||||
|
||||
|
@ -4940,7 +4941,7 @@ export class Pipedrive implements INodeType {
|
|||
if (resource === 'file' && operation === 'download') {
|
||||
items[i].json = { error: error.message };
|
||||
} else {
|
||||
returnData.push({ json: { error: error.message } });
|
||||
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('Test PostgresV2, runQueries', () => {
|
|||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([{ json: { success: true } }]);
|
||||
expect(result).toEqual([{ json: { success: true }, pairedItem: [{ item: 0 }] }]);
|
||||
expect(dbMultiSpy).toHaveBeenCalledWith('SELECT * FROM table');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ import type {
|
|||
SortRule,
|
||||
WhereClause,
|
||||
} from './interfaces';
|
||||
import { generatePairedItemData } from '../../../../utils/utilities';
|
||||
|
||||
export function wrapData(data: IDataObject | IDataObject[]): INodeExecutionData[] {
|
||||
if (!Array.isArray(data)) {
|
||||
|
@ -217,7 +218,8 @@ export function configureQueryRunner(
|
|||
) {
|
||||
return async (queries: QueryWithValues[], items: INodeExecutionData[], options: IDataObject) => {
|
||||
let returnData: INodeExecutionData[] = [];
|
||||
const emptyReturnData = options.operation === 'select' ? [] : [{ json: { success: true } }];
|
||||
const emptyReturnData: INodeExecutionData[] =
|
||||
options.operation === 'select' ? [] : [{ json: { success: true } }];
|
||||
|
||||
const queryBatching = (options.queryBatching as QueryMode) || 'single';
|
||||
|
||||
|
@ -232,12 +234,17 @@ export function configureQueryRunner(
|
|||
.flat();
|
||||
|
||||
if (!returnData.length) {
|
||||
const pairedItem = generatePairedItemData(queries.length);
|
||||
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
if (emptyReturnData.length) {
|
||||
emptyReturnData[0].pairedItem = pairedItem;
|
||||
}
|
||||
returnData = emptyReturnData;
|
||||
} else {
|
||||
returnData = queries.every((query) => isSelectQuery(query.query))
|
||||
? []
|
||||
: [{ json: { success: true } }];
|
||||
: [{ json: { success: true }, pairedItem }];
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import { fileFields, fileOperations } from './FileDescription';
|
|||
import { recordFields, recordOperations } from './RecordDescription';
|
||||
|
||||
import { reportFields, reportOperations } from './ReportDescription';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
export class QuickBase implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -116,6 +117,7 @@ export class QuickBase implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
const qs: IDataObject = {};
|
||||
|
@ -295,7 +297,7 @@ export class QuickBase implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -465,7 +467,7 @@ export class QuickBase implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
@ -548,7 +550,7 @@ export class QuickBase implements INodeType {
|
|||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
|
|
|
@ -6,6 +6,7 @@ import type {
|
|||
} from 'n8n-workflow';
|
||||
|
||||
import glob from 'fast-glob';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
export class ReadBinaryFiles implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -45,6 +46,7 @@ export class ReadBinaryFiles implements INodeType {
|
|||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const fileSelector = this.getNodeParameter('fileSelector', 0) as string;
|
||||
const dataPropertyName = this.getNodeParameter('dataPropertyName', 0);
|
||||
const pairedItem = generatePairedItemData(this.getInputData().length);
|
||||
|
||||
const files = await glob(fileSelector);
|
||||
|
||||
|
@ -56,9 +58,7 @@ export class ReadBinaryFiles implements INodeType {
|
|||
[dataPropertyName]: await this.helpers.prepareBinaryData(stream, filePath),
|
||||
},
|
||||
json: {},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
pairedItem,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import { NodeOperationError } from 'n8n-workflow';
|
|||
|
||||
import Parser from 'rss-parser';
|
||||
import { URL } from 'url';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
// Utility function
|
||||
|
||||
|
@ -64,6 +65,8 @@ export class RssFeedRead implements INodeType {
|
|||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const pairedItem = generatePairedItemData(this.getInputData().length);
|
||||
|
||||
try {
|
||||
const url = this.getNodeParameter('url', 0) as string;
|
||||
const options = this.getNodeParameter('options', 0);
|
||||
|
@ -97,19 +100,22 @@ export class RssFeedRead implements INodeType {
|
|||
throw new NodeOperationError(this.getNode(), error as Error);
|
||||
}
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
// For now we just take the items and ignore everything else
|
||||
if (feed.items) {
|
||||
feed.items.forEach((item) => {
|
||||
returnData.push(item);
|
||||
returnData.push({
|
||||
json: item,
|
||||
pairedItem,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
return [returnData];
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [[{ json: { error: error.message } }]];
|
||||
return [[{ json: { error: error.message }, pairedItem }]];
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ export class SetV1 implements INodeType {
|
|||
|
||||
const newItem: INodeExecutionData = {
|
||||
json: {},
|
||||
pairedItem: item.pairedItem,
|
||||
pairedItem: { item: itemIndex },
|
||||
};
|
||||
|
||||
if (!keepOnlySet) {
|
||||
|
|
|
@ -52,7 +52,7 @@ export function composeReturnItem(
|
|||
) {
|
||||
const newItem: INodeExecutionData = {
|
||||
json: {},
|
||||
pairedItem: inputItem.pairedItem,
|
||||
pairedItem: { item: itemIndex },
|
||||
};
|
||||
|
||||
if (options.includeBinary && inputItem.binary !== undefined) {
|
||||
|
|
|
@ -204,7 +204,7 @@ export async function execute(
|
|||
return composeReturnItem.call(this, i, item, newData, options);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return { json: { error: (error as Error).message } };
|
||||
return { json: { error: (error as Error).message, pairedItem: { item: i } } };
|
||||
}
|
||||
throw new NodeOperationError(this.getNode(), error as Error, {
|
||||
itemIndex: i,
|
||||
|
|
|
@ -59,7 +59,7 @@ export async function execute(
|
|||
return composeReturnItem.call(this, i, item, newData, options);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return { json: { error: (error as Error).message } };
|
||||
return { json: { error: (error as Error).message }, pairedItem: { item: i } };
|
||||
}
|
||||
throw new NodeOperationError(node, error as Error, {
|
||||
itemIndex: i,
|
||||
|
|
|
@ -29,7 +29,7 @@ import {
|
|||
toFileProperties,
|
||||
optionsProperties,
|
||||
} from '../description';
|
||||
import { flattenObject } from '@utils/utilities';
|
||||
import { flattenObject, generatePairedItemData } from '@utils/utilities';
|
||||
import { oldVersionNotice } from '@utils/descriptions';
|
||||
|
||||
export class SpreadsheetFileV1 implements INodeType {
|
||||
|
@ -57,6 +57,7 @@ export class SpreadsheetFileV1 implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const pairedItem = generatePairedItemData(items.length);
|
||||
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
|
@ -227,9 +228,7 @@ export class SpreadsheetFileV1 implements INodeType {
|
|||
const newItem: INodeExecutionData = {
|
||||
json: {},
|
||||
binary: {},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
pairedItem,
|
||||
};
|
||||
|
||||
let fileName = `spreadsheet.${fileFormat}`;
|
||||
|
@ -246,9 +245,7 @@ export class SpreadsheetFileV1 implements INodeType {
|
|||
json: {
|
||||
error: error.message,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
pairedItem,
|
||||
});
|
||||
} else {
|
||||
throw error;
|
||||
|
|
|
@ -33,7 +33,7 @@ import {
|
|||
optionsProperties,
|
||||
fromFileV2Properties,
|
||||
} from '../description';
|
||||
import { flattenObject } from '@utils/utilities';
|
||||
import { flattenObject, generatePairedItemData } from '@utils/utilities';
|
||||
|
||||
export class SpreadsheetFileV2 implements INodeType {
|
||||
description: INodeTypeDescription;
|
||||
|
@ -202,6 +202,7 @@ export class SpreadsheetFileV2 implements INodeType {
|
|||
|
||||
return [newItems];
|
||||
} else if (operation === 'toFile') {
|
||||
const pairedItem = generatePairedItemData(items.length);
|
||||
try {
|
||||
// Write the workflow data to spreadsheet file
|
||||
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
|
||||
|
@ -260,9 +261,7 @@ export class SpreadsheetFileV2 implements INodeType {
|
|||
const newItem: INodeExecutionData = {
|
||||
json: {},
|
||||
binary: {},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
pairedItem,
|
||||
};
|
||||
|
||||
let fileName = `spreadsheet.${fileFormat}`;
|
||||
|
@ -279,9 +278,7 @@ export class SpreadsheetFileV2 implements INodeType {
|
|||
json: {
|
||||
error: error.message,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
pairedItem,
|
||||
});
|
||||
} else {
|
||||
throw error;
|
||||
|
|
|
@ -9,6 +9,7 @@ import { NodeOperationError } from 'n8n-workflow';
|
|||
|
||||
import type { IRecord } from './GenericFunction';
|
||||
import { apiRequest, apiRequestAllItems } from './GenericFunction';
|
||||
import { generatePairedItemData } from '../../utils/utilities';
|
||||
|
||||
export class Stackby implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -282,9 +283,10 @@ export class Stackby implements INodeType {
|
|||
);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: 0 } },
|
||||
{ itemData },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,7 @@ import { checklistFields, checklistOperations } from './ChecklistDescription';
|
|||
import { checklistItemFields, checklistItemOperations } from './ChecklistItemDescription';
|
||||
|
||||
import { listFields, listOperations } from './ListDescription';
|
||||
import { wrapData } from '../../utils/utilities';
|
||||
|
||||
// https://wekan.github.io/api/v4.41/
|
||||
|
||||
|
@ -234,7 +235,7 @@ export class Wekan implements INodeType {
|
|||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
let returnAll;
|
||||
let limit;
|
||||
|
||||
|
@ -659,14 +660,15 @@ export class Wekan implements INodeType {
|
|||
responseData = responseData.splice(0, limit);
|
||||
}
|
||||
|
||||
if (Array.isArray(responseData)) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} else {
|
||||
returnData.push(responseData as IDataObject);
|
||||
}
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ error: error.message });
|
||||
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
|
|
|
@ -303,3 +303,17 @@ export function generatePairedItemData(length: number): IPairedItemData[] {
|
|||
item,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Paired Item Data Array
|
||||
*
|
||||
* @param {number | IPairedItemData | IPairedItemData[] | undefined} pairedItem
|
||||
*/
|
||||
export function preparePairedItemDataArray(
|
||||
pairedItem: number | IPairedItemData | IPairedItemData[] | undefined,
|
||||
): IPairedItemData[] {
|
||||
if (pairedItem === undefined) return [];
|
||||
if (typeof pairedItem === 'number') return [{ item: pairedItem }];
|
||||
if (Array.isArray(pairedItem)) return pairedItem;
|
||||
return [pairedItem];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue