mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-26 21:19:43 -08:00
7ce7285f7a
* Changes to types so that credentials can be always loaded from DB This first commit changes all return types from the execute functions and calls to get credentials to be async so we can use await. This is a first step as previously credentials were loaded in memory and always available. We will now be loading them from the DB which requires turning the whole call chain async. * Fix updated files * Removed unnecessary credential loading to improve performance * Fix typo * ⚡ Fix issue * Updated new nodes to load credentials async * ⚡ Remove not needed comment Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
204 lines
5.5 KiB
TypeScript
204 lines
5.5 KiB
TypeScript
import {
|
|
IExecuteFunctions,
|
|
} from 'n8n-core';
|
|
|
|
import {
|
|
IDataObject,
|
|
INodeExecutionData,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
NodeOperationError
|
|
} from 'n8n-workflow';
|
|
|
|
import {
|
|
nodeDescription,
|
|
} from './mongo.node.options';
|
|
|
|
import {
|
|
MongoClient,
|
|
ObjectID,
|
|
} from 'mongodb';
|
|
|
|
import {
|
|
getItemCopy,
|
|
handleDateFields,
|
|
validateAndResolveMongoCredentials
|
|
} from './mongo.node.utils';
|
|
|
|
export class MongoDb implements INodeType {
|
|
description: INodeTypeDescription = nodeDescription;
|
|
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const { database, connectionString } = validateAndResolveMongoCredentials(
|
|
this,
|
|
await this.getCredentials('mongoDb'),
|
|
);
|
|
|
|
const client: MongoClient = await MongoClient.connect(connectionString, {
|
|
useNewUrlParser: true,
|
|
useUnifiedTopology: true,
|
|
});
|
|
|
|
const mdb = client.db(database as string);
|
|
|
|
let returnItems = [];
|
|
|
|
const items = this.getInputData();
|
|
const operation = this.getNodeParameter('operation', 0) as string;
|
|
|
|
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));
|
|
|
|
returnItems = this.helpers.returnJsonArray([{ deletedCount }]);
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
returnItems = this.helpers.returnJsonArray({ error: error.message });
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
} else if (operation === 'find') {
|
|
// ----------------------------------
|
|
// find
|
|
// ----------------------------------
|
|
|
|
try {
|
|
let query = mdb
|
|
.collection(this.getNodeParameter('collection', 0) as string)
|
|
.find(JSON.parse(this.getNodeParameter('query', 0) as string));
|
|
|
|
const options = this.getNodeParameter('options', 0) as IDataObject;
|
|
const limit = options.limit as number;
|
|
const skip = options.skip as number;
|
|
const sort = options.sort && JSON.parse(options.sort as string);
|
|
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();
|
|
|
|
returnItems = this.helpers.returnJsonArray(queryResult as IDataObject[]);
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
returnItems = this.helpers.returnJsonArray({ error: error.message } );
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
} else if (operation === 'insert') {
|
|
// ----------------------------------
|
|
// insert
|
|
// ----------------------------------
|
|
try {
|
|
// Prepare the data to insert and copy it to be returned
|
|
const fields = (this.getNodeParameter('fields', 0) as string)
|
|
.split(',')
|
|
.map(f => f.trim())
|
|
.filter(f => !!f);
|
|
|
|
const options = this.getNodeParameter('options', 0) as IDataObject;
|
|
const insertItems = getItemCopy(items, fields);
|
|
|
|
if (options.dateFields) {
|
|
handleDateFields(insertItems, options.dateFields as string);
|
|
}
|
|
|
|
const { insertedIds } = await mdb
|
|
.collection(this.getNodeParameter('collection', 0) as string)
|
|
.insertMany(insertItems);
|
|
|
|
// Add the id to the data
|
|
for (const i of Object.keys(insertedIds)) {
|
|
returnItems.push({
|
|
json: {
|
|
...insertItems[parseInt(i, 10)],
|
|
id: insertedIds[parseInt(i, 10)] as string,
|
|
},
|
|
});
|
|
}
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
returnItems = this.helpers.returnJsonArray({ error: error.message });
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
} else if (operation === 'update') {
|
|
// ----------------------------------
|
|
// update
|
|
// ----------------------------------
|
|
|
|
const fields = (this.getNodeParameter('fields', 0) as string)
|
|
.split(',')
|
|
.map(f => f.trim())
|
|
.filter(f => !!f);
|
|
|
|
const options = this.getNodeParameter('options', 0) as IDataObject;
|
|
|
|
let updateKey = this.getNodeParameter('updateKey', 0) as string;
|
|
updateKey = updateKey.trim();
|
|
|
|
const updateOptions = (this.getNodeParameter('upsert', 0) as boolean)
|
|
? { upsert: true } : undefined;
|
|
|
|
if (!fields.includes(updateKey)) {
|
|
fields.push(updateKey);
|
|
}
|
|
|
|
// Prepare the data to update and copy it to be returned
|
|
const updateItems = getItemCopy(items, fields);
|
|
|
|
if (options.dateFields) {
|
|
handleDateFields(updateItems, options.dateFields as string);
|
|
}
|
|
|
|
for (const item of updateItems) {
|
|
try {
|
|
if (item[updateKey] === undefined) {
|
|
continue;
|
|
}
|
|
|
|
const filter: { [key: string]: string | ObjectID } = {};
|
|
filter[updateKey] = item[updateKey] as string;
|
|
if (updateKey === '_id') {
|
|
filter[updateKey] = new ObjectID(filter[updateKey]);
|
|
delete item['_id'];
|
|
}
|
|
await mdb
|
|
.collection(this.getNodeParameter('collection', 0) as string)
|
|
.updateOne(filter, { $set: item }, updateOptions);
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
item.json = { error: error.message };
|
|
continue;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
returnItems = this.helpers.returnJsonArray(updateItems as IDataObject[]);
|
|
} else {
|
|
if (this.continueOnFail()) {
|
|
returnItems = this.helpers.returnJsonArray({ json: { error: `The operation "${operation}" is not supported!` } });
|
|
} else {
|
|
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`);
|
|
}
|
|
}
|
|
|
|
client.close();
|
|
return this.prepareOutputData(returnItems);
|
|
}
|
|
}
|