Skip to content

Commit 01c1d87

Browse files
committed
feat: add skipMiddlewareFunction() and overwriteMiddlewareResult() for skipping and modifying middleware results
Fix #11426 Fix #8393
1 parent 40626d1 commit 01c1d87

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

lib/index.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require('./driver').set(require('./drivers/node-mongodb-native'));
88

99
const Document = require('./document');
1010
const EventEmitter = require('events').EventEmitter;
11+
const Kareem = require('kareem');
1112
const Schema = require('./schema');
1213
const SchemaType = require('./schematype');
1314
const SchemaTypes = require('./schema/index');
@@ -1185,6 +1186,43 @@ Mongoose.prototype._promiseOrCallback = function(callback, fn, ee) {
11851186
return promiseOrCallback(callback, fn, ee, this.Promise);
11861187
};
11871188

1189+
/**
1190+
* Use this function in `pre()` middleware to skip calling the wrapped function.
1191+
*
1192+
* ####Example:
1193+
*
1194+
* schema.pre('save', function() {
1195+
* // Will skip executing `save()`, but will execute post hooks as if
1196+
* // `save()` had executed with the result `{ matchedCount: 0 }`
1197+
* return mongoose.skipMiddlewareFunction({ matchedCount: 0 });
1198+
* });
1199+
*
1200+
* @method skipMiddlewareFunction
1201+
* @param {any} result
1202+
* @api public
1203+
*/
1204+
1205+
Mongoose.prototype.skipMiddlewareFunction = Kareem.skipWrappedFunction;
1206+
1207+
/**
1208+
* Use this function in `post()` middleware to replace the result
1209+
*
1210+
* ####Example:
1211+
*
1212+
* schema.post('find', function(res) {
1213+
* // Normally you have to modify `res` in place. But with
1214+
* // `overwriteMiddlewarResult()`, you can make `find()` return a
1215+
* // completely different value.
1216+
* return mongoose.overwriteMiddlewareResult(res.filter(doc => !doc.isDeleted));
1217+
* });
1218+
*
1219+
* @method overwriteMiddlewareResult
1220+
* @param {any} result
1221+
* @api public
1222+
*/
1223+
1224+
Mongoose.prototype.overwriteMiddlewareResult = Kareem.overwriteResult;
1225+
11881226
/*!
11891227
* The exports object is an instance of Mongoose.
11901228
*

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"license": "MIT",
2121
"dependencies": {
2222
"bson": "^4.6.2",
23-
"kareem": "2.3.5",
23+
"kareem": "2.4.0",
2424
"mongodb": "4.7.0",
2525
"mpath": "0.9.0",
2626
"mquery": "4.0.3",

test/query.middleware.test.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,6 @@ describe('query middleware', function() {
636636
});
637637
const Model = db.model('Test', schema);
638638

639-
640639
await Model.find();
641640
assert.equal(called, 1);
642641

@@ -655,4 +654,38 @@ describe('query middleware', function() {
655654
await Model.aggregate([{ $match: { name: 'test' } }]);
656655
assert.equal(called, 3);
657656
});
657+
658+
it('allows skipping the wrapped function with `skipMiddlewareFunction()` (gh-11426)', async function() {
659+
const schema = Schema({ name: String });
660+
661+
schema.pre('updateOne', function(next) {
662+
next(mongoose.skipMiddlewareFunction({ answer: 42 }));
663+
});
664+
const Test = db.model('Test', schema);
665+
666+
const { _id } = await Test.create({ name: 'test' });
667+
const res = await Test.updateOne({ _id }, { name: 'changed' });
668+
assert.equal(res.answer, 42);
669+
assert.strictEqual(res.modifiedCount, undefined);
670+
671+
const doc = await Test.findById(_id);
672+
assert.equal(doc.name, 'test');
673+
});
674+
675+
it('allows overwriting result with `overwriteMiddlewareResult()` (gh-11426)', async function() {
676+
const schema = Schema({ name: String });
677+
678+
schema.post('updateOne', function() {
679+
return mongoose.overwriteMiddlewareResult({ answer: 42 });
680+
});
681+
const Test = db.model('Test', schema);
682+
683+
const { _id } = await Test.create({ name: 'test' });
684+
const res = await Test.updateOne({ _id }, { name: 'changed' });
685+
assert.equal(res.answer, 42);
686+
assert.strictEqual(res.modifiedCount, undefined);
687+
688+
const doc = await Test.findById(_id);
689+
assert.equal(doc.name, 'changed');
690+
});
658691
});

0 commit comments

Comments
 (0)