Skip to content

Commit

Permalink
Merge pull request #11927 from Automattic/vkarpov15/gh-11426
Browse files Browse the repository at this point in the history
feat: add `skipMiddlewareFunction()` and `overwriteMiddlewareResult()` for skipping and modifying middleware results
  • Loading branch information
vkarpov15 authored Jun 17, 2022
2 parents 6db2e4a + ebc0b88 commit 96edf20
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
38 changes: 38 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require('./driver').set(require('./drivers/node-mongodb-native'));

const Document = require('./document');
const EventEmitter = require('events').EventEmitter;
const Kareem = require('kareem');
const Schema = require('./schema');
const SchemaType = require('./schematype');
const SchemaTypes = require('./schema/index');
Expand Down Expand Up @@ -1223,6 +1224,43 @@ Mongoose.prototype._promiseOrCallback = function(callback, fn, ee) {
return promiseOrCallback(callback, fn, ee, this.Promise);
};

/**
* Use this function in `pre()` middleware to skip calling the wrapped function.
*
* ####Example:
*
* schema.pre('save', function() {
* // Will skip executing `save()`, but will execute post hooks as if
* // `save()` had executed with the result `{ matchedCount: 0 }`
* return mongoose.skipMiddlewareFunction({ matchedCount: 0 });
* });
*
* @method skipMiddlewareFunction
* @param {any} result
* @api public
*/

Mongoose.prototype.skipMiddlewareFunction = Kareem.skipWrappedFunction;

/**
* Use this function in `post()` middleware to replace the result
*
* ####Example:
*
* schema.post('find', function(res) {
* // Normally you have to modify `res` in place. But with
* // `overwriteMiddlewarResult()`, you can make `find()` return a
* // completely different value.
* return mongoose.overwriteMiddlewareResult(res.filter(doc => !doc.isDeleted));
* });
*
* @method overwriteMiddlewareResult
* @param {any} result
* @api public
*/

Mongoose.prototype.overwriteMiddlewareResult = Kareem.overwriteResult;

/*!
* The exports object is an instance of Mongoose.
*
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"license": "MIT",
"dependencies": {
"bson": "^4.6.2",
"kareem": "2.3.5",
"kareem": "2.4.1",
"mongodb": "4.7.0",
"mpath": "0.9.0",
"mquery": "4.0.3",
Expand Down
43 changes: 42 additions & 1 deletion test/query.middleware.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,6 @@ describe('query middleware', function() {
});
const Model = db.model('Test', schema);


await Model.find();
assert.equal(called, 1);

Expand All @@ -655,4 +654,46 @@ describe('query middleware', function() {
await Model.aggregate([{ $match: { name: 'test' } }]);
assert.equal(called, 3);
});

it('allows skipping the wrapped function with `skipMiddlewareFunction()` (gh-11426)', async function() {
const schema = Schema({ name: String });
const now = Date.now();

schema.pre('find', function(next) {
next(mongoose.skipMiddlewareFunction([{ name: 'from cache' }]));
});
schema.post('find', function(res) {
res.forEach(doc => {
doc.loadedAt = now;
});
});
const Test = db.model('Test', schema);

const res = await Test.find();
assert.equal(res.length, 1);
assert.strictEqual(res[0].name, 'from cache');
assert.strictEqual(res[0].loadedAt, now);
});

it('allows overwriting result with `overwriteMiddlewareResult()` (gh-11426)', async function() {
const schema = Schema({ name: String });

schema.post('updateOne', function() {
return mongoose.overwriteMiddlewareResult({ answer: 42 });
});
schema.post('updateOne', function(res) {
assert.strictEqual(res.answer, 42);
res.secondMiddlewareRan = true;
});
const Test = db.model('Test', schema);

const { _id } = await Test.create({ name: 'test' });
const res = await Test.updateOne({ _id }, { name: 'changed' });
assert.equal(res.answer, 42);
assert.strictEqual(res.modifiedCount, undefined);
assert.strictEqual(res.secondMiddlewareRan, true);

const doc = await Test.findById(_id);
assert.equal(doc.name, 'changed');
});
});

0 comments on commit 96edf20

Please sign in to comment.