feat(mw): Rate limit#3463
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughA new ChangesRate limit middleware integration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This is now possible because we dropped Node 20 in v28 ( #3242 ) and `require(ESM)` is available since 22.12 without flags. So we can do dynamic module import without async. Could benefit in #3463 A semi-breaking change to `Integration::create()` is postponed until next major. ⌛ Mocking peers in tests requires a rework (in progress) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Peer dependency loading is now synchronous, simplifying server startup flow. * Middleware setup for cookies and uploads now runs synchronously during initialization. * `Integration` TypeScript configuration is optional; prefer `new Integration(...)` over the deprecated `Integration.create()`. * **Tests** * Updated integration and peer-helper tests to reflect synchronous initialization/loader behavior. * Adjusted and streamlined mocks for peers used in tests. * **Documentation** * Updated the README “End-to-End Type Safety” example and added a `v28.6.0` changelog entry. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
There was a problem hiding this comment.
ℹ️ One minor suggestion inline.
Reviewed changes — adds express-rate-limit as an optional peer dependency with a createRateLimitMiddleware() wrapper and useRateLimit() shorthand on EndpointsFactory.
- Add
express-rate-limitoptional peer — declared inpackage.jsonwithoptional: true. - New
createRateLimitMiddleware()— wrapsexpress-rate-limitviaExpressMiddleware, overriding its handler to throwcreateHttpError(429)and exposingrateLimitinfo on the context. - Add
EndpointsFactory#useRateLimit()shorthand — mirrors the existinguseCookies()/useCache()pattern. - Tests — middleware creation, config forwarding, success, rate-limit-exceeded, and context-population tests via
testMiddleware; factory shorthand test inendpoints-factory.spec.ts.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@express-zod-api/src/rate-limit-middleware.ts`:
- Around line 23-24: The provider function at line 23-24 in the
rate-limit-middleware.ts file hardcodes the property name as `req.rateLimit`,
but it should instead use the configurable requestPropertyName value that is
read on line 17. When a user customizes requestPropertyName to a different
value, the hardcoded access to req.rateLimit will be undefined while the actual
rate limit info resides at the custom property name. Change the provider
function to dynamically access the rate limit property using the
requestPropertyName config value instead of the hardcoded string "rateLimit".
In `@express-zod-api/tests/endpoints-factory.spec.ts`:
- Around line 18-24: The test defines a custom vi.mock for ../src/peer-helpers
with a loadPeer function that only handles the "express-rate-limit" module and
throws errors for other peers, making the test brittle when multiple peer-backed
middleware paths execute in the same file. Replace this local mock with the
shared peer mock that handles multiple peer dependencies, so that any peer
module resolution in this test suite works correctly without brittle error
handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d7fae9f2-99c3-4f94-934c-4cd582a42285
⛔ Files ignored due to path filters (2)
express-zod-api/tests/__snapshots__/index.spec.ts.snapis excluded by!**/*.snappnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
express-zod-api/package.jsonexpress-zod-api/src/endpoints-factory.tsexpress-zod-api/src/index.tsexpress-zod-api/src/rate-limit-middleware.tsexpress-zod-api/tests/endpoints-factory.spec.tsexpress-zod-api/tests/peers-mock.tsexpress-zod-api/tests/rate-limit-middleware.spec.ts
There was a problem hiding this comment.
Reviewed changes — two commits since the prior Pullfrog review fix the hardcoded requestPropertyName bug and simplify the return type annotation on createRateLimitMiddleware.
- Respect
requestPropertyNameoption — provider now readsreq[options?.requestPropertyName ?? "rateLimit"]instead of hardcodedreq.rateLimit, matching the configured express-rate-limit property name. - Simplified return type — removed explicit
ExpressMiddleware<Request, Response, …>annotation in favor of TypeScript inference, eliminating unused imports (Request,Response,RateLimitInfo). - Prior JSDoc feedback addressed — JSDoc block with
@desc,@requires,@param, and@examplewas added in a prior commit.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — two commits since the prior Pullfrog review rename the local variable for clarity and expose getKey/resetKey limiter API methods on the middleware context for programmatic rate limit management.
- Renamed
handler→limiter— the variable IS the rate limiter instance; the new name accurately reflects what it holds. - Exposed
getKeyandresetKeyon context — the provider now spreadslimiterApi({ getKey, resetKey }extracted from the limiter) before thereq.rateLimitinfo, giving endpoint handlers programmatic access to query/reset rate limit state. The type assertionRateLimitInfo & typeof limiterApiaccurately describes the merged object.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
ℹ️ One minor suggestion on the CHANGELOG punctuation.
Reviewed changes — adds the CHANGELOG entry and README section for rate limiting, plus import cleanups in the Cookies and Caching examples.
- CHANGELOG
v28.7.0entry — documents rate limiting support with nested bullets covering the peer dependency, the new method/shorthand, 429 behavior, and context properties. - README "Rate limiting" section — inserted after Caching with a
useRateLimit()example showingbuildVoidandrateLimitdestructuring, matching existing section style. - README import cleanups — removed
createCookieMiddlewarefrom the Cookies section import andcreateCacheMiddlewarefrom the Caching section import, since both examples now use factory shorthands.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — adds rate limiting to the example/ app, updates the README with a new "Rate limiting" section, and refreshes the AGENTS.md peers-mock description.
- Example factory updated —
keyAndTokenAuthenticatedEndpointsFactorynow chains.useRateLimit()before.addMiddleware(), demonstrating the new shorthand in practice. - Example tests extended — the existing PATCH test now validates rate limit response headers (
X-RateLimit-Limit,X-RateLimit-Remaining); a newRate limitingdescribe block sends enough requests to trigger a 429 and asserts the error response body and headers. - README expanded — new "Rate limiting" section with
useRateLimit()example andrateLimitcontext destructuring; TOC renumbered; import cleanups in Cookies and Caching sections. - AGENTS.md updated —
express-rate-limitadded to thepeers-mock.tsentry point description. - Dev dependency added —
express-rate-limitpinned inexpress-zod-api/package.jsondevDependenciesfor testing.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Using well-known solution as an optional peer. Hybrid integration approach as a NativeMiddleware in order to provide flexibility on the factory level, recognizing the possibility of different needs across public/private or commercial/free endpoints of the same APIs.
Summary by CodeRabbit
429handling, including rate-limit details on the middleware context.useRateLimit) to attach rate limiting to endpoints.express-rate-limitas an optional peer dependency (and added it for development).