MongoDB utilities.
$ npm install -S @haensl/mongo mongodb
$ yarn add @haensl/mongo mongodb
-
Install @haensl/mongo (and
mongodb
, it's a peer dependency) -
Use mongo in your projects:
ESM, i.e.
import
import factory from '@haensl/mongo'; const mongo = factory({ mongoUri }); // Spreading the import works, too. // import { client } from '@haensl/mongo'; const client = await mongo.client();
CJS, i.e.
require
const mongo = require('@haensl/mongo')({ mongoUri }); // ... const client = await mongo.client(); client.db('my_database') .collection('my_collection')
The mongo
utility wraps functions around getting a MongoClient
, identifying errors and connection pool cleanup. It is exposed as a factory:
// Factory.
// Takes Mongo connection URI.
// Returns service object.
({ mongoUri }) => ({
// Collects the changes made to doc by the given patch.
// Returns an array of objects of the form { field, from , to }
changes: (doc, patch) => [changes],
// Cleanup function to close the connection pool.
// Invoke e.g. at instance shutdown.
cleanup: async () => void,
// Returns a mongo client.
// Connects if necessary.
client: async () => MongoClient,
// Map of MongoDB error numbers.
errors: {
duplicateKey: 11000
},
// Checks if the given Error is a MongoDB error with given code.
// Returns a boolean.
isError: (error, code) => boolean,
// Checks if the given patch would change the given field in doc.
// Returns a boolean.
patchChangesField: ({ doc, field, patch }) => boolean,
// Returns the value stored in obj at the given keyPath.
// A key path is a string like `prop.subProp`.
// E.g. resolveKeyPath({ foo: { bar: 'baz' }}, 'foo.bar')
// returns 'baz'
resolveKeyPath: (obj, keyPath) => any,
// Transforms a patch object (with sub objects)
// into a MongoDB patch (with `prop.sub` keys)
// E.g.
// {
// foo: {
// bar: 'baz'
// }
// }
// becomes
// { 'foo.bar': 'baz' }
toMongoPatch: (patch) => mongoPatch
})
// mongo.js
// Wrap @haensl/mongo in a local module.
// Generate the service once and share it across your app.
const mongo = require('@haensl/mongo')(process.env.MONGO_URI);
process.on('exit', mongo.cleanup);
process.on('SIGINT', mongo.cleanup);
process.on('SIGTERM', mongo.cleanup);
module.exports = mongo;
In other modules that access your MongoDB, you use this local module:
// Use local wrapper created above
const mongo = require('./mongo');
const findThing = async (id) => {
const client = await mongo.client();
return client.db('my_mongodb')
.collection('things')
.findOne({ _id: id });
};
// Use local wrapper created above
const { client, isError, errors } = require('./mongo');
const insertThing = async (id) => {
const client = await mongo.client();
try {
client.db('my_mongodb')
.collection('things')
.insertOne({ _id: id })
} catch (err) {
// duplicate key error
if (isError(err, errors.duplicateKey)) {
console.info(`already got ${id}, skipping.`);
} else {
// something else happened
console.error(error);
}
}
};