Skip to content

Support middleware skip option for cursors and custom hooks#16348

Merged
AbdelrahmanHafez merged 4 commits into
Automattic:masterfrom
AbdelrahmanHafez:feat/skip-middleware-cursors-statics
Jun 29, 2026
Merged

Support middleware skip option for cursors and custom hooks#16348
AbdelrahmanHafez merged 4 commits into
Automattic:masterfrom
AbdelrahmanHafez:feat/skip-middleware-cursors-statics

Conversation

@AbdelrahmanHafez

@AbdelrahmanHafez AbdelrahmanHafez commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

re #8768, builds on top of mongoosejs/kareem#46

We left some parts uncovered in #15883, namely statics, methods, and cursors (aggregation, and query).

This PR:

  • Applies the existing middleware skip option to query cursors, including both pre find hooks and per-document post find hooks.
  • Applies the skip option to aggregate cursors for pre aggregate hooks. Aggregate cursors still don't run post aggregate hooks, so the cursor-specific TS type only exposes middleware: false and { pre: false }.
  • Strips the Mongoose-only middleware option before passing cursor options to the MongoDB driver.
  • Adds support for skipping middleware on custom statics and methods by reading middleware from the final plain options object.
  • Documents the cursor behavior and the recommended custom static/method signature.

For now this pins kareem to the fork commit that adds wrapper getOptions support for custom statics/methods. Once the Kareem change lands and is released, we can switch this back to a normal version range.

A design decision that was made is how we pass the middleware option to statics/methods, I chose to pass them to the last arg if it's POJO, and the docs now have examples with a pattern where users define the last arg as options, following the same pattern as the other mongoose operations.

Comment thread lib/helpers/buildMiddlewareFilter.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extends the existing middleware skip option so users can selectively skip user-defined hooks when using query cursors, aggregation cursors, and custom statics/methods, while ensuring the Mongoose-only option is not forwarded to the MongoDB driver.

Changes:

  • Add middleware filtering support to query cursors (pre('find') + per-document post('find')) and aggregation cursors (pre('aggregate') only), and strip middleware before calling the MongoDB driver.
  • Enable per-call hook skipping for custom statics and methods by reading middleware from the trailing plain-object options argument via Kareem wrapper getOptions.
  • Update TypeScript types, docs, and add runtime + type-level tests; pin kareem to a fork commit needed for wrapper getOptions.

Reviewed changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
types/middlewares.d.ts Update middleware function return typing to Kareem.OverwriteResult.
types/index.d.ts Update overwriteMiddlewareResult() return type to Kareem.OverwriteResult.
types/aggregate.d.ts Add cursor-specific options/types for aggregate cursors, including middleware skipping semantics.
test/types/model.skip.middleware.test.ts Extend TS type tests to cover cursor middleware options and new aggregate cursor types.
test/model.skip.middleware.test.js Add runtime tests for cursor middleware skipping, option parsing behavior, and custom statics/methods skipping.
package.json Pin kareem dependency to a fork commit that supports wrapper getOptions.
lib/query.js Document cursor hook behavior and cursor-level middleware option.
lib/helpers/model/applyStaticHooks.js Add Kareem wrapper getOptions for custom statics to support per-call hook skipping.
lib/helpers/model/applyHooks.js Add Kareem wrapper getOptions for custom document methods to support per-call hook skipping.
lib/helpers/buildMiddlewareFilter.js Tighten skip detection to only treat strict false as “skip”.
lib/cursor/queryCursor.js Apply middleware filtering to cursor execPre/execPost('find') and strip middleware before driver call.
lib/cursor/aggregationCursor.js Apply middleware filtering to execPre('aggregate') and strip middleware before driver calls.
lib/aggregate.js Document aggregate cursor middleware behavior and plumb cursor-level middleware into aggregate options.
docs/middleware.md Document cursor behavior and recommended custom static/method signature for options.

Comment thread lib/cursor/queryCursor.js
Comment on lines 614 to +617
function _nextDoc(ctx, doc, pop, callback) {
const postFilter = buildMiddlewareFilter(ctx.query.options, 'post');
if (ctx.query._mongooseOptions.lean) {
return ctx.model.hooks.execPost('find', ctx.query, [[doc]]).then(() => callback(null, doc), err => callback(err));
return ctx.model.hooks.execPost('find', ctx.query, [[doc]], { filter: postFilter }).then(() => callback(null, doc), err => callback(err));
Comment thread lib/query.js
Comment on lines +5333 to +5334
* The `.cursor()` function triggers pre find hooks before opening the cursor
* and post find hooks for each document.
Comment thread package.json
Comment thread lib/query.js
Comment thread types/index.d.ts
@AbdelrahmanHafez AbdelrahmanHafez merged commit acd201c into Automattic:master Jun 29, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants