mongoose-bread
Version:
A pagination and softdelete library for mongoose
106 lines (93 loc) • 2.98 kB
JavaScript
const parseLeanFactory = require("./parseLeanFactory");
const toBreadErrorFactory = require("./toBreadErrorFactory");
/**
* Factory function to create Model.edit() method
* @param {import('../index').MongooseBreadOptions} pluginOptions Config of mongoose-bread plugin
*/
function editFactory(pluginOptions) {
const { runUpdateTransaction } = pluginOptions;
const { docs, acknowledged, modifiedCount } = pluginOptions.customLabels;
const toBreadResult = ([result, _docs]) => ({
[docs]: _docs,
[acknowledged]: result.acknowledged ?? true,
[modifiedCount]: result.modifiedCount ?? result.nModified,
});
const toBreadError = toBreadErrorFactory({
[docs]: [],
[acknowledged]: false,
[modifiedCount]: 0,
});
function runWithTransaction(Model, options) {
const { query, payload, projection, populate, select, sort, lean, limit } =
options;
const parseLean = parseLeanFactory(options);
const updateWithSession = (session) => {
session.startTransaction();
return Promise.all([
Promise.resolve(session),
Model.updateMany(query, payload, { session }),
]);
};
const fetchDocs = ([session, updateResult]) => {
return Promise.all([
Promise.resolve(session),
Promise.resolve(updateResult),
Model.find(query, projection)
.session(session)
.populate(populate)
.select(select)
.sort(sort)
.lean(lean)
.limit(limit)
.orFail()
.then(parseLean),
]);
};
const commitTransaction = ([session, updateResult, _docs]) => {
return Promise.all([
Promise.resolve(session),
Promise.resolve(updateResult),
Promise.resolve(_docs),
session.commitTransaction(),
]);
};
const endSession = ([session, updateResult, _docs]) => {
session.endSession();
return [updateResult, _docs];
};
return Model.startSession()
.then(updateWithSession)
.then(fetchDocs)
.then(commitTransaction)
.then(endSession)
.then(toBreadResult)
.catch(toBreadError);
} // end runWithTransaction
function runRaw(Model, options) {
const { query, payload, projection, populate, select, sort, lean, limit } =
options;
const parseLean = parseLeanFactory(options);
const mergeUpdateAndDocs = (result) =>
Promise.all([
Promise.resolve(result),
Model.find(query, projection)
.populate(populate)
.select(select)
.sort(sort)
.lean(lean)
.limit(limit)
.orFail()
.then(parseLean),
]);
return Model.updateMany(query, payload)
.then(mergeUpdateAndDocs)
.then(toBreadResult)
.catch(toBreadError);
}
return function edit(options) {
return runUpdateTransaction
? runWithTransaction(this, options)
: runRaw(this, options);
};
}
module.exports = editFactory;