mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
fix: Update operations to run per item (#8967)
Co-authored-by: Elias Meire <elias@meire.dev>
This commit is contained in:
parent
870412f093
commit
ef9d4aba90
|
@ -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';
|
||||
|
@ -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}}',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
returnData = returnData.map((record) => ({
|
||||
json: flattenOutput(record as IDataObject),
|
||||
}));
|
||||
let records = responseData.records;
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
records = (records as IDataObject[]).map((record) => ({
|
||||
json: flattenOutput(record),
|
||||
})) as INodeExecutionData[];
|
||||
|
||||
returnData = this.helpers.constructExecutionMetaData(returnData, {
|
||||
itemData,
|
||||
});
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ json: { message: error.message, error } });
|
||||
} else {
|
||||
throw error;
|
||||
const itemData = fallbackPairedItems || [{ item: i }];
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(records, {
|
||||
itemData,
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ json: { message: error.message, error }, pairedItem: { item: i } });
|
||||
continue;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Coda implements INodeType {
|
|||
name: 'coda',
|
||||
icon: 'file:coda.svg',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
version: [1, 1.1],
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Coda API',
|
||||
defaults: {
|
||||
|
@ -240,6 +240,7 @@ export class Coda implements INodeType {
|
|||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const items = this.getInputData();
|
||||
let responseData;
|
||||
|
@ -363,61 +364,83 @@ export class Coda implements INodeType {
|
|||
}
|
||||
// https://coda.io/developers/apis/v1beta1#operation/listRows
|
||||
if (operation === 'getAllRows') {
|
||||
const docId = this.getNodeParameter('docId', 0) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const tableId = this.getNodeParameter('tableId', 0) as string;
|
||||
const options = this.getNodeParameter('options', 0);
|
||||
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
|
||||
if (options.useColumnNames === false) {
|
||||
qs.useColumnNames = options.useColumnNames as boolean;
|
||||
} else {
|
||||
qs.useColumnNames = true;
|
||||
}
|
||||
if (options.valueFormat) {
|
||||
qs.valueFormat = options.valueFormat as string;
|
||||
}
|
||||
if (options.sortBy) {
|
||||
qs.sortBy = options.sortBy as string;
|
||||
}
|
||||
if (options.visibleOnly) {
|
||||
qs.visibleOnly = options.visibleOnly as boolean;
|
||||
}
|
||||
if (options.query) {
|
||||
qs.query = options.query as string;
|
||||
}
|
||||
try {
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(
|
||||
this,
|
||||
'items',
|
||||
'GET',
|
||||
endpoint,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [this.helpers.returnJsonArray({ error: error.message })];
|
||||
}
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
let itemsLength = items.length ? 1 : 0;
|
||||
|
||||
if (nodeVersion >= 1.1) {
|
||||
itemsLength = items.length;
|
||||
}
|
||||
|
||||
if (options.rawData === true) {
|
||||
return [this.helpers.returnJsonArray(responseData as IDataObject[])];
|
||||
} else {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
id: item.id,
|
||||
...item.values,
|
||||
});
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
const docId = this.getNodeParameter('docId', i) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const tableId = this.getNodeParameter('tableId', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
|
||||
if (options.useColumnNames === false) {
|
||||
qs.useColumnNames = options.useColumnNames as boolean;
|
||||
} else {
|
||||
qs.useColumnNames = true;
|
||||
}
|
||||
if (options.valueFormat) {
|
||||
qs.valueFormat = options.valueFormat as string;
|
||||
}
|
||||
if (options.sortBy) {
|
||||
qs.sortBy = options.sortBy as string;
|
||||
}
|
||||
if (options.visibleOnly) {
|
||||
qs.visibleOnly = options.visibleOnly as boolean;
|
||||
}
|
||||
if (options.query) {
|
||||
qs.query = options.query as string;
|
||||
}
|
||||
try {
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(
|
||||
this,
|
||||
'items',
|
||||
'GET',
|
||||
endpoint,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
||||
if (options.rawData === true) {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
json: item,
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
json: {
|
||||
id: item.id,
|
||||
...item.values,
|
||||
},
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (error instanceof NodeApiError) throw error;
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
// https://coda.io/developers/apis/v1beta1#operation/deleteRows
|
||||
if (operation === 'deleteRow') {
|
||||
|
@ -630,15 +653,15 @@ export class Coda implements INodeType {
|
|||
}
|
||||
//https://coda.io/developers/apis/v1beta1#operation/listControls
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const docId = this.getNodeParameter('docId', i) as string;
|
||||
const endpoint = `/docs/${docId}/controls`;
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
@ -680,15 +703,15 @@ export class Coda implements INodeType {
|
|||
}
|
||||
//https://coda.io/developers/apis/v1beta1#operation/listViews
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const docId = this.getNodeParameter('docId', i) as string;
|
||||
const endpoint = `/docs/${docId}/tables?tableTypes=view`;
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
@ -712,58 +735,80 @@ export class Coda implements INodeType {
|
|||
return [returnData];
|
||||
}
|
||||
if (operation === 'getAllViewRows') {
|
||||
const docId = this.getNodeParameter('docId', 0) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const viewId = this.getNodeParameter('viewId', 0) as string;
|
||||
const options = this.getNodeParameter('options', 0);
|
||||
const endpoint = `/docs/${docId}/tables/${viewId}/rows`;
|
||||
if (options.useColumnNames === false) {
|
||||
qs.useColumnNames = options.useColumnNames as boolean;
|
||||
} else {
|
||||
qs.useColumnNames = true;
|
||||
}
|
||||
if (options.valueFormat) {
|
||||
qs.valueFormat = options.valueFormat as string;
|
||||
}
|
||||
if (options.sortBy) {
|
||||
qs.sortBy = options.sortBy as string;
|
||||
}
|
||||
if (options.query) {
|
||||
qs.query = options.query as string;
|
||||
}
|
||||
try {
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(
|
||||
this,
|
||||
'items',
|
||||
'GET',
|
||||
endpoint,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [this.helpers.returnJsonArray({ error: error.message })];
|
||||
}
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
let itemsLength = items.length ? 1 : 0;
|
||||
|
||||
if (nodeVersion >= 1.1) {
|
||||
itemsLength = items.length;
|
||||
}
|
||||
|
||||
if (options.rawData === true) {
|
||||
return [this.helpers.returnJsonArray(responseData as IDataObject[])];
|
||||
} else {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
id: item.id,
|
||||
...item.values,
|
||||
});
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
const docId = this.getNodeParameter('docId', i) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const viewId = this.getNodeParameter('viewId', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const endpoint = `/docs/${docId}/tables/${viewId}/rows`;
|
||||
if (options.useColumnNames === false) {
|
||||
qs.useColumnNames = options.useColumnNames as boolean;
|
||||
} else {
|
||||
qs.useColumnNames = true;
|
||||
}
|
||||
if (options.valueFormat) {
|
||||
qs.valueFormat = options.valueFormat as string;
|
||||
}
|
||||
if (options.sortBy) {
|
||||
qs.sortBy = options.sortBy as string;
|
||||
}
|
||||
if (options.query) {
|
||||
qs.query = options.query as string;
|
||||
}
|
||||
try {
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(
|
||||
this,
|
||||
'items',
|
||||
'GET',
|
||||
endpoint,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
||||
if (options.rawData === true) {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
json: item,
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (const item of responseData) {
|
||||
returnData.push({
|
||||
json: {
|
||||
id: item.id,
|
||||
...item.values,
|
||||
},
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (error instanceof NodeApiError) throw error;
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
//https://coda.io/developers/apis/v1beta1#operation/deleteViewRow
|
||||
if (operation === 'deleteViewRow') {
|
||||
|
@ -823,16 +868,16 @@ export class Coda implements INodeType {
|
|||
return [returnData];
|
||||
}
|
||||
if (operation === 'getAllViewColumns') {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const docId = this.getNodeParameter('docId', i) as string;
|
||||
const viewId = this.getNodeParameter('viewId', i) as string;
|
||||
const endpoint = `/docs/${docId}/tables/${viewId}/columns`;
|
||||
if (returnAll) {
|
||||
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', 0);
|
||||
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
|
|
@ -27,12 +27,13 @@ export const tableOperations: INodeProperties[] = [
|
|||
{
|
||||
name: 'Get All Columns',
|
||||
value: 'getAllColumns',
|
||||
description: 'Get all columns in a table',
|
||||
action: 'Get all columns',
|
||||
},
|
||||
{
|
||||
name: 'Get All Rows',
|
||||
value: 'getAllRows',
|
||||
description: 'Get all the rows',
|
||||
description: 'Get all rows in a table',
|
||||
action: 'Get all rows',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
||||
icon: 'file:googleFirebaseCloudFirestore.png',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 1.1],
|
||||
subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
|
||||
description: 'Interact with Google Firebase - Cloud Firestore API',
|
||||
defaults: {
|
||||
|
@ -94,15 +94,27 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
const itemData = generatePairedItemData(items.length);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
let responseData;
|
||||
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
|
||||
let itemsLength = items.length ? 1 : 0;
|
||||
let fallbackPairedItems;
|
||||
|
||||
if (nodeVersion >= 1.1) {
|
||||
itemsLength = items.length;
|
||||
} else {
|
||||
fallbackPairedItems = generatePairedItemData(items.length);
|
||||
}
|
||||
|
||||
if (resource === 'document') {
|
||||
if (operation === 'get') {
|
||||
const projectId = this.getNodeParameter('projectId', 0) as string;
|
||||
const database = this.getNodeParameter('database', 0) as string;
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
const documentList = items.map((item: IDataObject, i: number) => {
|
||||
const documentList = items.map((_: IDataObject, i: number) => {
|
||||
const collection = this.getNodeParameter('collection', i) as string;
|
||||
const documentId = this.getNodeParameter('documentId', i) as string;
|
||||
return `projects/${projectId}/databases/${database}/documents/${collection}/${documentId}`;
|
||||
|
@ -179,49 +191,64 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
}),
|
||||
);
|
||||
} else if (operation === 'getAll') {
|
||||
const projectId = this.getNodeParameter('projectId', 0) as string;
|
||||
const database = this.getNodeParameter('database', 0) as string;
|
||||
const collection = this.getNodeParameter('collection', 0) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const projectId = this.getNodeParameter('projectId', i) as string;
|
||||
const database = this.getNodeParameter('database', i) as string;
|
||||
const collection = this.getNodeParameter('collection', i) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await googleApiRequestAllItems.call(
|
||||
this,
|
||||
'documents',
|
||||
'GET',
|
||||
`/${projectId}/databases/${database}/documents/${collection}`,
|
||||
);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', 0);
|
||||
const getAllResponse = (await googleApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${projectId}/databases/${database}/documents/${collection}`,
|
||||
{},
|
||||
{ pageSize: limit },
|
||||
)) as IDataObject;
|
||||
responseData = getAllResponse.documents;
|
||||
if (returnAll) {
|
||||
responseData = await googleApiRequestAllItems.call(
|
||||
this,
|
||||
'documents',
|
||||
'GET',
|
||||
`/${projectId}/databases/${database}/documents/${collection}`,
|
||||
);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
const getAllResponse = (await googleApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${projectId}/databases/${database}/documents/${collection}`,
|
||||
{},
|
||||
{ pageSize: limit },
|
||||
)) as IDataObject;
|
||||
responseData = getAllResponse.documents;
|
||||
}
|
||||
|
||||
responseData = responseData.map((element: IDataObject) => {
|
||||
element.id = (element.name as string).split('/').pop();
|
||||
return element;
|
||||
});
|
||||
|
||||
if (simple) {
|
||||
responseData = responseData.map((element: IDataObject) =>
|
||||
fullDocumentToJson(element),
|
||||
);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: fallbackPairedItems ?? [{ item: i }] },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
responseData = responseData.map((element: IDataObject) => {
|
||||
element.id = (element.name as string).split('/').pop();
|
||||
return element;
|
||||
});
|
||||
|
||||
if (simple) {
|
||||
responseData = responseData.map((element: IDataObject) => fullDocumentToJson(element));
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} else if (operation === 'delete') {
|
||||
await Promise.all(
|
||||
items.map(async (item: IDataObject, i: number) => {
|
||||
items.map(async (_: IDataObject, i: number) => {
|
||||
const projectId = this.getNodeParameter('projectId', i) as string;
|
||||
const database = this.getNodeParameter('database', i) as string;
|
||||
const collection = this.getNodeParameter('collection', i) as string;
|
||||
|
@ -295,44 +322,13 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
// } else if (operation === 'update') {
|
||||
// const projectId = this.getNodeParameter('projectId', 0) as string;
|
||||
// const database = this.getNodeParameter('database', 0) as string;
|
||||
// const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
|
||||
// await Promise.all(items.map(async (item: IDataObject, i: number) => {
|
||||
// const collection = this.getNodeParameter('collection', i) as string;
|
||||
// const updateKey = this.getNodeParameter('updateKey', i) as string;
|
||||
// // @ts-ignore
|
||||
// const documentId = item['json'][updateKey] as string;
|
||||
// const columns = this.getNodeParameter('columns', i) as string;
|
||||
// const columnList = columns.split(',').map(column => column.trim()) as string[];
|
||||
// const document = {};
|
||||
// columnList.map(column => {
|
||||
// // @ts-ignore
|
||||
// document[column] = item['json'].hasOwnProperty(column) ? jsonToDocument(item['json'][column]) : jsonToDocument(null);
|
||||
// });
|
||||
// responseData = await googleApiRequest.call(
|
||||
// this,
|
||||
// 'PATCH',
|
||||
// `/${projectId}/databases/${database}/documents/${collection}/${documentId}`,
|
||||
// { fields: document },
|
||||
// { [`updateMask.fieldPaths`]: columnList },
|
||||
// );
|
||||
// if (simple === false) {
|
||||
// returnData.push(responseData);
|
||||
// } else {
|
||||
// returnData.push(fullDocumentToJson(responseData as IDataObject));
|
||||
// }
|
||||
// }));
|
||||
} else if (operation === 'query') {
|
||||
const projectId = this.getNodeParameter('projectId', 0) as string;
|
||||
const database = this.getNodeParameter('database', 0) as string;
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
|
||||
await Promise.all(
|
||||
items.map(async (item: IDataObject, i: number) => {
|
||||
items.map(async (_: IDataObject, i: number) => {
|
||||
const query = this.getNodeParameter('query', i) as string;
|
||||
responseData = await googleApiRequest.call(
|
||||
this,
|
||||
|
@ -369,38 +365,51 @@ export class GoogleFirebaseCloudFirestore implements INodeType {
|
|||
}
|
||||
} else if (resource === 'collection') {
|
||||
if (operation === 'getAll') {
|
||||
const projectId = this.getNodeParameter('projectId', 0) as string;
|
||||
const database = this.getNodeParameter('database', 0) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0);
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const projectId = this.getNodeParameter('projectId', i) as string;
|
||||
const database = this.getNodeParameter('database', i) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
|
||||
if (returnAll) {
|
||||
const getAllResponse = await googleApiRequestAllItems.call(
|
||||
this,
|
||||
'collectionIds',
|
||||
'POST',
|
||||
`/${projectId}/databases/${database}/documents:listCollectionIds`,
|
||||
);
|
||||
// @ts-ignore
|
||||
responseData = getAllResponse.map((o) => ({ name: o }));
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', 0);
|
||||
const getAllResponse = (await googleApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/${projectId}/databases/${database}/documents:listCollectionIds`,
|
||||
{},
|
||||
{ pageSize: limit },
|
||||
)) as IDataObject;
|
||||
// @ts-ignore
|
||||
responseData = getAllResponse.collectionIds.map((o) => ({ name: o }));
|
||||
if (returnAll) {
|
||||
const getAllResponse = await googleApiRequestAllItems.call(
|
||||
this,
|
||||
'collectionIds',
|
||||
'POST',
|
||||
`/${projectId}/databases/${database}/documents:listCollectionIds`,
|
||||
);
|
||||
// @ts-ignore
|
||||
responseData = getAllResponse.map((o) => ({ name: o }));
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
const getAllResponse = (await googleApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/${projectId}/databases/${database}/documents:listCollectionIds`,
|
||||
{},
|
||||
{ pageSize: limit },
|
||||
)) as IDataObject;
|
||||
// @ts-ignore
|
||||
responseData = getAllResponse.collectionIds.map((o) => ({ name: o }));
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: fallbackPairedItems ?? [{ item: i }] },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
// const spreadsheetId = this.getNodeParameter('spreadsheetId', i) as string;
|
||||
const documentId = this.getNodeParameter('documentId', i, undefined, {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
|
|
@ -10,7 +10,6 @@ import type {
|
|||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import type { ITables } from './interfaces';
|
||||
|
||||
|
@ -30,7 +29,7 @@ export class MicrosoftSql implements INodeType {
|
|||
name: 'microsoftSql',
|
||||
icon: 'file:mssql.svg',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 1.1],
|
||||
description: 'Get, add and update data in Microsoft SQL',
|
||||
defaults: {
|
||||
name: 'Microsoft SQL',
|
||||
|
@ -250,10 +249,50 @@ export class MicrosoftSql implements INodeType {
|
|||
await pool.connect();
|
||||
|
||||
let responseData: IDataObject | IDataObject[] = [];
|
||||
let returnData: INodeExecutionData[] = [];
|
||||
|
||||
const items = this.getInputData();
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
|
||||
if (operation === 'executeQuery' && nodeVersion >= 1.1) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
let rawQuery = this.getNodeParameter('query', i) as string;
|
||||
|
||||
for (const resolvable of getResolvables(rawQuery)) {
|
||||
rawQuery = rawQuery.replace(
|
||||
resolvable,
|
||||
this.evaluateExpression(resolvable, i) as string,
|
||||
);
|
||||
}
|
||||
|
||||
const { recordsets }: IResult<any[]> = await pool.request().query(rawQuery);
|
||||
|
||||
const result: IDataObject[] = recordsets.length > 1 ? flatten(recordsets) : recordsets[0];
|
||||
|
||||
for (const entry of result) {
|
||||
returnData.push({
|
||||
json: entry,
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
await pool.close();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
await pool.close();
|
||||
return [returnData];
|
||||
}
|
||||
try {
|
||||
if (operation === 'executeQuery') {
|
||||
let rawQuery = this.getNodeParameter('query', 0) as string;
|
||||
|
@ -267,15 +306,19 @@ export class MicrosoftSql implements INodeType {
|
|||
const result = recordsets.length > 1 ? flatten(recordsets) : recordsets[0];
|
||||
|
||||
responseData = result;
|
||||
} else if (operation === 'insert') {
|
||||
}
|
||||
|
||||
if (operation === 'insert') {
|
||||
const tables = createTableStruct(this.getNodeParameter, items);
|
||||
|
||||
await insertOperation(tables, pool);
|
||||
|
||||
responseData = items;
|
||||
} else if (operation === 'update') {
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
const updateKeys = items.map(
|
||||
(item, index) => this.getNodeParameter('updateKey', index) as string,
|
||||
(_, index) => this.getNodeParameter('updateKey', index) as string,
|
||||
);
|
||||
|
||||
const tables = createTableStruct(
|
||||
|
@ -288,7 +331,9 @@ export class MicrosoftSql implements INodeType {
|
|||
await updateOperation(tables, pool);
|
||||
|
||||
responseData = items;
|
||||
} else if (operation === 'delete') {
|
||||
}
|
||||
|
||||
if (operation === 'delete') {
|
||||
const tables = items.reduce((acc, item, index) => {
|
||||
const table = this.getNodeParameter('table', index) as string;
|
||||
const deleteKey = this.getNodeParameter('deleteKey', index) as string;
|
||||
|
@ -303,13 +348,14 @@ export class MicrosoftSql implements INodeType {
|
|||
}, {} as ITables);
|
||||
|
||||
responseData = await deleteOperation(tables, pool);
|
||||
} else {
|
||||
await pool.close();
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`The operation "${operation}" is not supported!`,
|
||||
);
|
||||
}
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
returnData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData },
|
||||
);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
responseData = items;
|
||||
|
@ -322,13 +368,6 @@ export class MicrosoftSql implements INodeType {
|
|||
// shuts down the connection pool associated with the db object to allow the process to finish
|
||||
await pool.close();
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
const returnItems = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
return [returnItems];
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,15 +132,17 @@ export function prepareFields(fields: string) {
|
|||
.filter((field) => !!field);
|
||||
}
|
||||
|
||||
export function stringifyObjectIDs(items: IDataObject[]) {
|
||||
export function stringifyObjectIDs(items: INodeExecutionData[]) {
|
||||
items.forEach((item) => {
|
||||
if (item._id instanceof ObjectId) {
|
||||
item._id = item._id.toString();
|
||||
item.json._id = item._id.toString();
|
||||
}
|
||||
if (item.id instanceof ObjectId) {
|
||||
item.id = item.id.toString();
|
||||
item.json.id = item.id.toString();
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
export async function connectMongoClient(connectionString: string, credentials: IDataObject = {}) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import type {
|
|||
INodeTypeDescription,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { ApplicationError, NodeOperationError } from 'n8n-workflow';
|
||||
import { ApplicationError } from 'n8n-workflow';
|
||||
|
||||
import type {
|
||||
FindOneAndReplaceOptions,
|
||||
|
@ -38,7 +38,7 @@ export class MongoDb implements INodeType {
|
|||
name: 'mongoDb',
|
||||
icon: 'file:mongodb.svg',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 1.1],
|
||||
description: 'Find, insert and update documents in MongoDB',
|
||||
defaults: {
|
||||
name: 'MongoDB',
|
||||
|
@ -108,101 +108,126 @@ export class MongoDb implements INodeType {
|
|||
|
||||
const mdb = client.db(database);
|
||||
|
||||
let responseData: IDataObject | IDataObject[] = [];
|
||||
let returnData: INodeExecutionData[] = [];
|
||||
|
||||
const items = this.getInputData();
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
|
||||
let itemsLength = items.length ? 1 : 0;
|
||||
let fallbackPairedItems;
|
||||
|
||||
if (nodeVersion >= 1.1) {
|
||||
itemsLength = items.length;
|
||||
} else {
|
||||
fallbackPairedItems = generatePairedItemData(items.length);
|
||||
}
|
||||
|
||||
if (operation === 'aggregate') {
|
||||
// ----------------------------------
|
||||
// aggregate
|
||||
// ----------------------------------
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const queryParameter = JSON.parse(
|
||||
this.getNodeParameter('query', i) as string,
|
||||
) as IDataObject;
|
||||
|
||||
try {
|
||||
const queryParameter = JSON.parse(
|
||||
this.getNodeParameter('query', 0) as string,
|
||||
) as IDataObject;
|
||||
if (queryParameter._id && typeof queryParameter._id === 'string') {
|
||||
queryParameter._id = new ObjectId(queryParameter._id);
|
||||
}
|
||||
|
||||
if (queryParameter._id && typeof queryParameter._id === 'string') {
|
||||
queryParameter._id = new ObjectId(queryParameter._id);
|
||||
}
|
||||
const query = mdb
|
||||
.collection(this.getNodeParameter('collection', i) as string)
|
||||
.aggregate(queryParameter as unknown as Document[]);
|
||||
|
||||
const query = mdb
|
||||
.collection(this.getNodeParameter('collection', 0) as string)
|
||||
.aggregate(queryParameter as unknown as Document[]);
|
||||
|
||||
responseData = await query.toArray();
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
responseData = [{ error: (error as JsonObject).message }];
|
||||
} else {
|
||||
for (const entry of await query.toArray()) {
|
||||
returnData.push({ json: entry, pairedItem: fallbackPairedItems ?? [{ item: i }] });
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: (error as JsonObject).message },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else if (operation === 'delete') {
|
||||
// ----------------------------------
|
||||
// delete
|
||||
// ----------------------------------
|
||||
}
|
||||
|
||||
try {
|
||||
const { deletedCount } = await mdb
|
||||
.collection(this.getNodeParameter('collection', 0) as string)
|
||||
.deleteMany(JSON.parse(this.getNodeParameter('query', 0) as string) as Document);
|
||||
if (operation === 'delete') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const { deletedCount } = await mdb
|
||||
.collection(this.getNodeParameter('collection', i) as string)
|
||||
.deleteMany(JSON.parse(this.getNodeParameter('query', i) as string) as Document);
|
||||
|
||||
responseData = [{ deletedCount }];
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
responseData = [{ error: (error as JsonObject).message }];
|
||||
} else {
|
||||
returnData.push({
|
||||
json: { deletedCount },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: (error as JsonObject).message },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else if (operation === 'find') {
|
||||
// ----------------------------------
|
||||
// find
|
||||
// ----------------------------------
|
||||
}
|
||||
|
||||
try {
|
||||
const queryParameter = JSON.parse(
|
||||
this.getNodeParameter('query', 0) as string,
|
||||
) as IDataObject;
|
||||
if (operation === 'find') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const queryParameter = JSON.parse(
|
||||
this.getNodeParameter('query', i) as string,
|
||||
) as IDataObject;
|
||||
|
||||
if (queryParameter._id && typeof queryParameter._id === 'string') {
|
||||
queryParameter._id = new ObjectId(queryParameter._id);
|
||||
}
|
||||
if (queryParameter._id && typeof queryParameter._id === 'string') {
|
||||
queryParameter._id = new ObjectId(queryParameter._id);
|
||||
}
|
||||
|
||||
let query = mdb
|
||||
.collection(this.getNodeParameter('collection', 0) as string)
|
||||
.find(queryParameter as unknown as Document);
|
||||
let query = mdb
|
||||
.collection(this.getNodeParameter('collection', i) as string)
|
||||
.find(queryParameter as unknown as Document);
|
||||
|
||||
const options = this.getNodeParameter('options', 0);
|
||||
const limit = options.limit as number;
|
||||
const skip = options.skip as number;
|
||||
const sort = options.sort && (JSON.parse(options.sort as string) as Sort);
|
||||
if (skip > 0) {
|
||||
query = query.skip(skip);
|
||||
}
|
||||
if (limit > 0) {
|
||||
query = query.limit(limit);
|
||||
}
|
||||
if (sort && Object.keys(sort).length !== 0 && sort.constructor === Object) {
|
||||
query = query.sort(sort);
|
||||
}
|
||||
const queryResult = await query.toArray();
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const limit = options.limit as number;
|
||||
const skip = options.skip as number;
|
||||
const sort = options.sort && (JSON.parse(options.sort as string) as Sort);
|
||||
|
||||
responseData = queryResult;
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
responseData = [{ error: (error as JsonObject).message }];
|
||||
} else {
|
||||
if (skip > 0) {
|
||||
query = query.skip(skip);
|
||||
}
|
||||
if (limit > 0) {
|
||||
query = query.limit(limit);
|
||||
}
|
||||
if (sort && Object.keys(sort).length !== 0 && sort.constructor === Object) {
|
||||
query = query.sort(sort);
|
||||
}
|
||||
|
||||
const queryResult = await query.toArray();
|
||||
|
||||
for (const entry of queryResult) {
|
||||
returnData.push({ json: entry, pairedItem: fallbackPairedItems ?? [{ item: i }] });
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: (error as JsonObject).message },
|
||||
pairedItem: fallbackPairedItems ?? [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else if (operation === 'findOneAndReplace') {
|
||||
// ----------------------------------
|
||||
// findOneAndReplace
|
||||
// ----------------------------------
|
||||
}
|
||||
|
||||
if (operation === 'findOneAndReplace') {
|
||||
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
|
||||
const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
|
||||
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
|
||||
const dateFields = prepareFields(
|
||||
|
@ -237,12 +262,14 @@ export class MongoDb implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
responseData = updateItems;
|
||||
} else if (operation === 'findOneAndUpdate') {
|
||||
// ----------------------------------
|
||||
// findOneAndUpdate
|
||||
// ----------------------------------
|
||||
returnData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(updateItems),
|
||||
{ itemData: fallbackPairedItems },
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === 'findOneAndUpdate') {
|
||||
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
|
||||
const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
|
||||
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
|
||||
const dateFields = prepareFields(
|
||||
|
@ -277,11 +304,15 @@ export class MongoDb implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
responseData = updateItems;
|
||||
} else if (operation === 'insert') {
|
||||
// ----------------------------------
|
||||
// insert
|
||||
// ----------------------------------
|
||||
returnData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(updateItems),
|
||||
{ itemData: fallbackPairedItems },
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === 'insert') {
|
||||
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
|
||||
let responseData: IDataObject[] = [];
|
||||
try {
|
||||
// Prepare the data to insert and copy it to be returned
|
||||
const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
|
||||
|
@ -310,11 +341,15 @@ export class MongoDb implements INodeType {
|
|||
throw error;
|
||||
}
|
||||
}
|
||||
} else if (operation === 'update') {
|
||||
// ----------------------------------
|
||||
// update
|
||||
// ----------------------------------
|
||||
|
||||
returnData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData: fallbackPairedItems },
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
fallbackPairedItems = fallbackPairedItems ?? generatePairedItemData(items.length);
|
||||
const fields = prepareFields(this.getNodeParameter('fields', 0) as string);
|
||||
const useDotNotation = this.getNodeParameter('options.useDotNotation', 0, false) as boolean;
|
||||
const dateFields = prepareFields(
|
||||
|
@ -349,30 +384,14 @@ export class MongoDb implements INodeType {
|
|||
}
|
||||
}
|
||||
|
||||
responseData = updateItems;
|
||||
} else {
|
||||
if (this.continueOnFail()) {
|
||||
responseData = [{ error: `The operation "${operation}" is not supported!` }];
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`The operation "${operation}" is not supported!`,
|
||||
{ itemIndex: 0 },
|
||||
);
|
||||
}
|
||||
returnData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(updateItems),
|
||||
{ itemData: fallbackPairedItems },
|
||||
);
|
||||
}
|
||||
|
||||
await client.close();
|
||||
|
||||
stringifyObjectIDs(responseData);
|
||||
|
||||
const itemData = generatePairedItemData(items.length);
|
||||
|
||||
const returnItems = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData),
|
||||
{ itemData },
|
||||
);
|
||||
|
||||
return [returnItems];
|
||||
return [stringifyObjectIDs(returnData)];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export class RssFeedRead implements INodeType {
|
|||
name: 'rssFeedRead',
|
||||
icon: 'fa:rss',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 1.1],
|
||||
description: 'Reads data from an RSS Feed',
|
||||
defaults: {
|
||||
name: 'RSS Read',
|
||||
|
@ -65,59 +65,88 @@ export class RssFeedRead implements INodeType {
|
|||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const pairedItem = generatePairedItemData(this.getInputData().length);
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
const items = this.getInputData();
|
||||
|
||||
try {
|
||||
const url = this.getNodeParameter('url', 0) as string;
|
||||
const options = this.getNodeParameter('options', 0);
|
||||
const ignoreSSL = Boolean(options.ignoreSSL);
|
||||
let itemsLength = items.length ? 1 : 0;
|
||||
let fallbackPairedItems;
|
||||
|
||||
if (!url) {
|
||||
throw new NodeOperationError(this.getNode(), 'The parameter "URL" has to be set!');
|
||||
}
|
||||
if (nodeVersion >= 1.1) {
|
||||
itemsLength = items.length;
|
||||
} else {
|
||||
fallbackPairedItems = generatePairedItemData(items.length);
|
||||
}
|
||||
|
||||
if (!validateURL(url)) {
|
||||
throw new NodeOperationError(this.getNode(), 'The provided "URL" is not valid!');
|
||||
}
|
||||
|
||||
const parser = new Parser({
|
||||
requestOptions: {
|
||||
rejectUnauthorized: !ignoreSSL,
|
||||
},
|
||||
});
|
||||
|
||||
let feed: Parser.Output<IDataObject>;
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
feed = await parser.parseURL(url);
|
||||
} catch (error) {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`It was not possible to connect to the URL. Please make sure the URL "${url}" it is valid!`,
|
||||
);
|
||||
const url = this.getNodeParameter('url', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const ignoreSSL = Boolean(options.ignoreSSL);
|
||||
|
||||
if (!url) {
|
||||
throw new NodeOperationError(this.getNode(), 'The parameter "URL" has to be set!', {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
|
||||
throw new NodeOperationError(this.getNode(), error as Error);
|
||||
}
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
// For now we just take the items and ignore everything else
|
||||
if (feed.items) {
|
||||
feed.items.forEach((item) => {
|
||||
returnData.push({
|
||||
json: item,
|
||||
pairedItem,
|
||||
if (!validateURL(url)) {
|
||||
throw new NodeOperationError(this.getNode(), 'The provided "URL" is not valid!', {
|
||||
itemIndex: i,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
return [[{ json: { error: error.message }, pairedItem }]];
|
||||
const parser = new Parser({
|
||||
requestOptions: {
|
||||
rejectUnauthorized: !ignoreSSL,
|
||||
},
|
||||
});
|
||||
|
||||
let feed: Parser.Output<IDataObject>;
|
||||
try {
|
||||
feed = await parser.parseURL(url);
|
||||
} catch (error) {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`It was not possible to connect to the URL. Please make sure the URL "${url}" it is valid!`,
|
||||
{
|
||||
itemIndex: i,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
throw new NodeOperationError(this.getNode(), error as Error, {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
|
||||
// For now we just take the items and ignore everything else
|
||||
if (feed.items) {
|
||||
const feedItems = (feed.items as IDataObject[]).map((item) => ({
|
||||
json: item,
|
||||
})) as INodeExecutionData[];
|
||||
|
||||
const itemData = fallbackPairedItems || [{ item: i }];
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(feedItems, {
|
||||
itemData,
|
||||
});
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: fallbackPairedItems || [{ item: i }],
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue