Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Update operations to run per item #8967

Merged
merged 14 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading