Skip to content

Commit

Permalink
fix: Update operations to run per item (#8967)
Browse files Browse the repository at this point in the history
Co-authored-by: Elias Meire <elias@meire.dev>
  • Loading branch information
michael-radency and elsmr authored May 22, 2024
1 parent 870412f commit ef9d4ab
Show file tree
Hide file tree
Showing 12 changed files with 600 additions and 431 deletions.
11 changes: 10 additions & 1 deletion packages/nodes-base/credentials/CodaApi.credentials.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
import type { ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';

export class CodaApi implements ICredentialType {
name = 'codaApi';
Expand All @@ -16,4 +16,13 @@ export class CodaApi implements ICredentialType {
default: '',
},
];

test: ICredentialTestRequest = {
request: {
baseURL: 'https://coda.io/apis/v1/whoami',
headers: {
Authorization: '=Bearer {{$credentials.accessToken}}',
},
},
};
}
3 changes: 2 additions & 1 deletion packages/nodes-base/nodes/Airtable/Airtable.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ export class Airtable extends VersionedNodeType {
icon: 'file:airtable.svg',
group: ['input'],
description: 'Read, update, write and delete data from Airtable',
defaultVersion: 2,
defaultVersion: 2.1,
};

const nodeVersions: IVersionedNodeType['nodeVersions'] = {
1: new AirtableV1(baseDescription),
2: new AirtableV2(baseDescription),
2.1: new AirtableV2(baseDescription),
};

super(nodeVersions, baseDescription);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,74 +149,90 @@ export async function execute(
base: string,
table: string,
): Promise<INodeExecutionData[]> {
let returnData: INodeExecutionData[] = [];

const body: IDataObject = {};
const qs: IDataObject = {};
const returnData: INodeExecutionData[] = [];
const nodeVersion = this.getNode().typeVersion;

const endpoint = `${base}/${table}`;

try {
const returnAll = this.getNodeParameter('returnAll', 0);
const options = this.getNodeParameter('options', 0, {});
const sort = this.getNodeParameter('sort', 0, {}) as IDataObject;
const filterByFormula = this.getNodeParameter('filterByFormula', 0) as string;
let itemsLength = items.length ? 1 : 0;
let fallbackPairedItems;

if (filterByFormula) {
qs.filterByFormula = filterByFormula;
}
if (nodeVersion >= 2.1) {
itemsLength = items.length;
} else {
fallbackPairedItems = generatePairedItemData(items.length);
}

if (options.fields) {
if (typeof options.fields === 'string') {
qs.fields = options.fields.split(',').map((field) => field.trim());
} else {
qs.fields = options.fields as string[];
for (let i = 0; i < itemsLength; i++) {
try {
const returnAll = this.getNodeParameter('returnAll', i);
const options = this.getNodeParameter('options', i, {});
const sort = this.getNodeParameter('sort', i, {}) as IDataObject;
const filterByFormula = this.getNodeParameter('filterByFormula', i) as string;

const body: IDataObject = {};
const qs: IDataObject = {};

if (filterByFormula) {
qs.filterByFormula = filterByFormula;
}
}

if (sort.property) {
qs.sort = sort.property;
}
if (options.fields) {
if (typeof options.fields === 'string') {
qs.fields = options.fields.split(',').map((field) => field.trim());
} else {
qs.fields = options.fields as string[];
}
}

if (options.view) {
qs.view = (options.view as IDataObject).value as string;
}
if (sort.property) {
qs.sort = sort.property;
}

let responseData;
if (options.view) {
qs.view = (options.view as IDataObject).value as string;
}

if (returnAll) {
responseData = await apiRequestAllItems.call(this, 'GET', endpoint, body, qs);
} else {
qs.maxRecords = this.getNodeParameter('limit', 0);
responseData = await apiRequest.call(this, 'GET', endpoint, body, qs);
}
let responseData;

returnData = responseData.records as INodeExecutionData[];
if (returnAll) {
responseData = await apiRequestAllItems.call(this, 'GET', endpoint, body, qs);
} else {
qs.maxRecords = this.getNodeParameter('limit', i);
responseData = await apiRequest.call(this, 'GET', endpoint, body, qs);
}

if (options.downloadFields) {
const pairedItem = generatePairedItemData(items.length);
return await downloadRecordAttachments.call(
this,
responseData.records as IRecord[],
options.downloadFields as string[],
pairedItem,
);
}
if (options.downloadFields) {
const itemWithAttachments = await downloadRecordAttachments.call(
this,
responseData.records as IRecord[],
options.downloadFields as string[],
fallbackPairedItems || [{ item: i }],
);
returnData.push(...itemWithAttachments);
continue;
}

let records = responseData.records;

records = (records as IDataObject[]).map((record) => ({
json: flattenOutput(record),
})) as INodeExecutionData[];

returnData = returnData.map((record) => ({
json: flattenOutput(record as IDataObject),
}));
const itemData = fallbackPairedItems || [{ item: i }];

const itemData = generatePairedItemData(items.length);
const executionData = this.helpers.constructExecutionMetaData(records, {
itemData,
});

returnData = this.helpers.constructExecutionMetaData(returnData, {
itemData,
});
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { message: error.message, error } });
} else {
throw error;
returnData.push(...executionData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { message: error.message, error }, pairedItem: { item: i } });
continue;
} else {
throw error;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const versionDescription: INodeTypeDescription = {
name: 'airtable',
icon: 'file:airtable.svg',
group: ['input'],
version: 2,
version: [2, 2.1],
subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
description: 'Read, update, write and delete data from Airtable',
defaults: {
Expand Down
Loading

0 comments on commit ef9d4ab

Please sign in to comment.