ratelimit-flex 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +274 -0
  4. package/dist/cjs/index.d.ts +32 -0
  5. package/dist/cjs/index.d.ts.map +1 -0
  6. package/dist/cjs/index.js +73 -0
  7. package/dist/cjs/index.js.map +1 -0
  8. package/dist/cjs/middleware/express.d.ts +18 -0
  9. package/dist/cjs/middleware/express.d.ts.map +1 -0
  10. package/dist/cjs/middleware/express.js +61 -0
  11. package/dist/cjs/middleware/express.js.map +1 -0
  12. package/dist/cjs/middleware/fastify.d.ts +21 -0
  13. package/dist/cjs/middleware/fastify.d.ts.map +1 -0
  14. package/dist/cjs/middleware/fastify.js +66 -0
  15. package/dist/cjs/middleware/fastify.js.map +1 -0
  16. package/dist/cjs/middleware/index.d.ts +4 -0
  17. package/dist/cjs/middleware/index.d.ts.map +1 -0
  18. package/dist/cjs/middleware/index.js +9 -0
  19. package/dist/cjs/middleware/index.js.map +1 -0
  20. package/dist/cjs/middleware/merge-options.d.ts +16 -0
  21. package/dist/cjs/middleware/merge-options.d.ts.map +1 -0
  22. package/dist/cjs/middleware/merge-options.js +71 -0
  23. package/dist/cjs/middleware/merge-options.js.map +1 -0
  24. package/dist/cjs/package.json +1 -0
  25. package/dist/cjs/stores/index.d.ts +4 -0
  26. package/dist/cjs/stores/index.d.ts.map +1 -0
  27. package/dist/cjs/stores/index.js +11 -0
  28. package/dist/cjs/stores/index.js.map +1 -0
  29. package/dist/cjs/stores/memory-store.d.ts +74 -0
  30. package/dist/cjs/stores/memory-store.d.ts.map +1 -0
  31. package/dist/cjs/stores/memory-store.js +259 -0
  32. package/dist/cjs/stores/memory-store.js.map +1 -0
  33. package/dist/cjs/stores/redis-store.d.ts +113 -0
  34. package/dist/cjs/stores/redis-store.d.ts.map +1 -0
  35. package/dist/cjs/stores/redis-store.js +452 -0
  36. package/dist/cjs/stores/redis-store.js.map +1 -0
  37. package/dist/cjs/strategies/defaults.d.ts +28 -0
  38. package/dist/cjs/strategies/defaults.d.ts.map +1 -0
  39. package/dist/cjs/strategies/defaults.js +31 -0
  40. package/dist/cjs/strategies/defaults.js.map +1 -0
  41. package/dist/cjs/strategies/index.d.ts +4 -0
  42. package/dist/cjs/strategies/index.d.ts.map +1 -0
  43. package/dist/cjs/strategies/index.js +13 -0
  44. package/dist/cjs/strategies/index.js.map +1 -0
  45. package/dist/cjs/strategies/rate-limit-engine.d.ts +42 -0
  46. package/dist/cjs/strategies/rate-limit-engine.d.ts.map +1 -0
  47. package/dist/cjs/strategies/rate-limit-engine.js +128 -0
  48. package/dist/cjs/strategies/rate-limit-engine.js.map +1 -0
  49. package/dist/cjs/types/index.d.ts +93 -0
  50. package/dist/cjs/types/index.d.ts.map +1 -0
  51. package/dist/cjs/types/index.js +14 -0
  52. package/dist/cjs/types/index.js.map +1 -0
  53. package/dist/cjs/utils/index.d.ts +3 -0
  54. package/dist/cjs/utils/index.d.ts.map +1 -0
  55. package/dist/cjs/utils/index.js +4 -0
  56. package/dist/cjs/utils/index.js.map +1 -0
  57. package/dist/index.d.ts +32 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +43 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/middleware/express.d.ts +18 -0
  62. package/dist/middleware/express.d.ts.map +1 -0
  63. package/dist/middleware/express.js +58 -0
  64. package/dist/middleware/express.js.map +1 -0
  65. package/dist/middleware/fastify.d.ts +21 -0
  66. package/dist/middleware/fastify.d.ts.map +1 -0
  67. package/dist/middleware/fastify.js +60 -0
  68. package/dist/middleware/fastify.js.map +1 -0
  69. package/dist/middleware/index.d.ts +4 -0
  70. package/dist/middleware/index.d.ts.map +1 -0
  71. package/dist/middleware/index.js +4 -0
  72. package/dist/middleware/index.js.map +1 -0
  73. package/dist/middleware/merge-options.d.ts +16 -0
  74. package/dist/middleware/merge-options.d.ts.map +1 -0
  75. package/dist/middleware/merge-options.js +64 -0
  76. package/dist/middleware/merge-options.js.map +1 -0
  77. package/dist/stores/index.d.ts +4 -0
  78. package/dist/stores/index.d.ts.map +1 -0
  79. package/dist/stores/index.js +4 -0
  80. package/dist/stores/index.js.map +1 -0
  81. package/dist/stores/memory-store.d.ts +74 -0
  82. package/dist/stores/memory-store.d.ts.map +1 -0
  83. package/dist/stores/memory-store.js +255 -0
  84. package/dist/stores/memory-store.js.map +1 -0
  85. package/dist/stores/redis-store.d.ts +113 -0
  86. package/dist/stores/redis-store.d.ts.map +1 -0
  87. package/dist/stores/redis-store.js +413 -0
  88. package/dist/stores/redis-store.js.map +1 -0
  89. package/dist/strategies/defaults.d.ts +28 -0
  90. package/dist/strategies/defaults.d.ts.map +1 -0
  91. package/dist/strategies/defaults.js +28 -0
  92. package/dist/strategies/defaults.js.map +1 -0
  93. package/dist/strategies/index.d.ts +4 -0
  94. package/dist/strategies/index.d.ts.map +1 -0
  95. package/dist/strategies/index.js +4 -0
  96. package/dist/strategies/index.js.map +1 -0
  97. package/dist/strategies/rate-limit-engine.d.ts +42 -0
  98. package/dist/strategies/rate-limit-engine.d.ts.map +1 -0
  99. package/dist/strategies/rate-limit-engine.js +122 -0
  100. package/dist/strategies/rate-limit-engine.js.map +1 -0
  101. package/dist/types/index.d.ts +93 -0
  102. package/dist/types/index.d.ts.map +1 -0
  103. package/dist/types/index.js +11 -0
  104. package/dist/types/index.js.map +1 -0
  105. package/dist/utils/index.d.ts +3 -0
  106. package/dist/utils/index.d.ts.map +1 -0
  107. package/dist/utils/index.js +3 -0
  108. package/dist/utils/index.js.map +1 -0
  109. package/package.json +90 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ ## [1.0.0] - 2026-03-27
6
+
7
+ ### Added
8
+ - Initial public release of `ratelimit-flex`.
9
+ - Rate limiting strategies: sliding window, fixed window, and token bucket.
10
+ - Express middleware and Fastify plugin integrations.
11
+ - `MemoryStore` and Redis-backed `RedisStore`.
12
+ - TypeScript-first API with documented defaults and strategy options.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ratelimit-flex contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # ratelimit-flex
2
+
3
+ [![npm version](https://img.shields.io/npm/v/ratelimit-flex.svg)](https://www.npmjs.com/package/ratelimit-flex)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
5
+ ![Tests](https://img.shields.io/badge/tests-vitest%20passing-brightgreen)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-First-3178C6?logo=typescript&logoColor=white)
7
+
8
+ Flexible, TypeScript-first rate limiting for Node.js APIs with first-class Express and Fastify support.
9
+
10
+ **Key features**
11
+ - Multiple strategies: sliding window, token bucket, fixed window
12
+ - Works with Express and Fastify
13
+ - Pluggable stores: in-memory and Redis
14
+ - Strong TypeScript types and clean public API
15
+ - Supports custom keys, skip logic, callbacks, and custom responses
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install ratelimit-flex
21
+ ```
22
+
23
+ ```bash
24
+ yarn add ratelimit-flex
25
+ ```
26
+
27
+ ```bash
28
+ pnpm add ratelimit-flex
29
+ ```
30
+
31
+ **Note:** The published package targets **Node.js 18+**. Continuous integration and local development use **Node.js 20.12+** because Vitest 4 depends on APIs that are not available on Node 18.
32
+
33
+ ## Quick Start (Express)
34
+
35
+ ```ts
36
+ import express from 'express';
37
+ import rateLimit from 'ratelimit-flex';
38
+ const app = express();
39
+ app.use(rateLimit({ maxRequests: 100, windowMs: 60_000 }));
40
+ app.get('/health', (_req, res) => res.json({ ok: true }));
41
+ ```
42
+
43
+ ## Strategies
44
+
45
+ ### Sliding Window
46
+ Most accurate for per-window fairness because each request is counted against a moving window, not a fixed boundary. Use this as your default for user-facing APIs where consistency matters more than minimal memory usage.
47
+
48
+ ### Token Bucket
49
+ Great when you want to allow short bursts while still enforcing a long-term average rate. Useful for APIs where occasional spikes are expected (mobile reconnects, batchy clients, webhook retries).
50
+
51
+ ### Fixed Window
52
+ Simplest and most memory-efficient approach. Best for straightforward rate limiting where slight boundary effects are acceptable (for example, internal tools or low-risk endpoints).
53
+
54
+ ## API Reference
55
+
56
+ ### Exports
57
+
58
+ ```ts
59
+ import rateLimit, {
60
+ expressRateLimiter,
61
+ fastifyRateLimiter,
62
+ createRateLimiter,
63
+ createRateLimitEngine,
64
+ MemoryStore,
65
+ RedisStore,
66
+ RateLimitEngine,
67
+ RateLimitStrategy,
68
+ slidingWindowDefaults,
69
+ fixedWindowDefaults,
70
+ tokenBucketDefaults,
71
+ } from 'ratelimit-flex';
72
+ ```
73
+
74
+ - Default export: `expressRateLimiter`
75
+ - Named exports include all of the above plus all types from `types/index.ts`
76
+ - `createRateLimitEngine(options)`: factory that returns a `RateLimitEngine` instance (for advanced use cases)
77
+
78
+ ### `RateLimitOptions`
79
+
80
+ | Option | Type | Default | Description |
81
+ |---|---|---|---|
82
+ | `strategy` | `RateLimitStrategy` | `SLIDING_WINDOW` | Strategy to use: `SLIDING_WINDOW`, `TOKEN_BUCKET`, or `FIXED_WINDOW` |
83
+ | `store` | `RateLimitStore` | `MemoryStore` (when omitted in middleware helpers) | Backing store for counters/token state |
84
+ | `keyGenerator` | `(req: unknown) => string` | framework IP-based fallback | Builds the rate-limit key (user, API key, tenant, etc.) |
85
+ | `onLimitReached` | `(req, result) => void \| Promise<void>` | `undefined` | Called when a request is blocked |
86
+ | `skip` | `(req: unknown) => boolean` | `undefined` | Skip rate limiting entirely for matching requests |
87
+ | `headers` | `boolean` | `true` | Adds `X-RateLimit-*` and `Retry-After` headers |
88
+ | `statusCode` | `number` | `429` | HTTP status code used when blocked |
89
+ | `message` | `string \| object` | `"Too many requests"` | Error payload wrapped as `{ error: message }` |
90
+ | `skipFailedRequests` | `boolean` | `false` | Decrement usage for failed responses (`>= 400`) |
91
+ | `skipSuccessfulRequests` | `boolean` | `false` | Decrement usage for successful responses (`< 400`) |
92
+ | `windowMs` | `number` | `60000` | Window length for sliding/fixed window strategies |
93
+ | `maxRequests` | `number` | `100` | Max requests per window for sliding/fixed window |
94
+ | `tokensPerInterval` | `number` | `10` | Tokens refilled per interval (token bucket) |
95
+ | `interval` | `number` | `60000` | Refill interval in ms (token bucket) |
96
+ | `bucketSize` | `number` | `100` | Max bucket capacity (token bucket burst size) |
97
+
98
+ ### Defaults
99
+
100
+ - `slidingWindowDefaults`: `{ strategy: SLIDING_WINDOW, windowMs: 60000, maxRequests: 100 }`
101
+ - `fixedWindowDefaults`: `{ strategy: FIXED_WINDOW, windowMs: 60000, maxRequests: 100 }`
102
+ - `tokenBucketDefaults`: `{ strategy: TOKEN_BUCKET, tokensPerInterval: 10, interval: 60000, bucketSize: 100 }`
103
+
104
+ ### Convenience Factory: `createRateLimiter(options)`
105
+
106
+ `createRateLimiter` returns an object with both `.express` and `.fastify` properties:
107
+
108
+ ```ts
109
+ const limiter = createRateLimiter({ maxRequests: 100 });
110
+ app.use(limiter.express); // Express
111
+ await app.register(limiter.fastify); // Fastify
112
+ ```
113
+
114
+ **Note**: This function requires `fastify-plugin` as a peer dependency (already listed). For best type-safety and clarity, prefer direct imports (`expressRateLimiter` or `fastifyRateLimiter`) when you already know your framework.
115
+
116
+ ## Examples
117
+
118
+ ### Basic Express usage
119
+
120
+ ```ts
121
+ import express from 'express';
122
+ import { expressRateLimiter } from 'ratelimit-flex';
123
+
124
+ const app = express();
125
+ app.use(
126
+ expressRateLimiter({
127
+ strategy: 'SLIDING_WINDOW',
128
+ windowMs: 60_000,
129
+ maxRequests: 100,
130
+ }),
131
+ );
132
+ ```
133
+
134
+ ### Basic Fastify usage
135
+
136
+ ```ts
137
+ import Fastify from 'fastify';
138
+ import { fastifyRateLimiter, RateLimitStrategy } from 'ratelimit-flex';
139
+
140
+ const app = Fastify();
141
+ await app.register(fastifyRateLimiter, {
142
+ strategy: RateLimitStrategy.SLIDING_WINDOW,
143
+ windowMs: 60_000,
144
+ maxRequests: 100,
145
+ });
146
+ ```
147
+
148
+ ### Per-user rate limiting by API key
149
+
150
+ ```ts
151
+ import { expressRateLimiter } from 'ratelimit-flex';
152
+
153
+ app.use(
154
+ expressRateLimiter({
155
+ maxRequests: 60,
156
+ windowMs: 60_000,
157
+ keyGenerator: (req) =>
158
+ String((req as import('express').Request).header('x-api-key') ?? 'anonymous'),
159
+ }),
160
+ );
161
+ ```
162
+
163
+ ### Token bucket for API endpoints
164
+
165
+ ```ts
166
+ import { expressRateLimiter, RateLimitStrategy } from 'ratelimit-flex';
167
+
168
+ app.use(
169
+ '/api',
170
+ expressRateLimiter({
171
+ strategy: RateLimitStrategy.TOKEN_BUCKET,
172
+ tokensPerInterval: 20,
173
+ interval: 60_000,
174
+ bucketSize: 60,
175
+ }),
176
+ );
177
+ ```
178
+
179
+ ### Using RedisStore for distributed systems
180
+
181
+ ```ts
182
+ import { expressRateLimiter, RedisStore, RateLimitStrategy } from 'ratelimit-flex';
183
+
184
+ const store = new RedisStore({
185
+ strategy: RateLimitStrategy.SLIDING_WINDOW,
186
+ windowMs: 60_000,
187
+ maxRequests: 100,
188
+ url: process.env.REDIS_URL!,
189
+ });
190
+
191
+ app.use(expressRateLimiter({ strategy: RateLimitStrategy.SLIDING_WINDOW, store }));
192
+ ```
193
+
194
+ ### Custom error responses
195
+
196
+ ```ts
197
+ app.use(
198
+ expressRateLimiter({
199
+ maxRequests: 20,
200
+ windowMs: 60_000,
201
+ statusCode: 429,
202
+ message: { code: 'RATE_LIMITED', detail: 'Please retry shortly.' },
203
+ }),
204
+ );
205
+ ```
206
+
207
+ ### Skipping certain routes
208
+
209
+ ```ts
210
+ app.use(
211
+ expressRateLimiter({
212
+ maxRequests: 100,
213
+ windowMs: 60_000,
214
+ skip: (req) => String((req as { path?: string }).path ?? '').startsWith('/health'),
215
+ }),
216
+ );
217
+ ```
218
+
219
+ ### Multiple rate limiters (global + per-endpoint)
220
+
221
+ ```ts
222
+ import { expressRateLimiter } from 'ratelimit-flex';
223
+
224
+ app.use(expressRateLimiter({ maxRequests: 100, windowMs: 60_000 })); // global
225
+ app.use('/login', expressRateLimiter({ maxRequests: 10, windowMs: 60_000 })); // strict endpoint
226
+ ```
227
+
228
+ ## Stores
229
+
230
+ | Store | Best for | Pros | Trade-offs |
231
+ |---|---|---|---|
232
+ | `MemoryStore` | Single-instance apps, local development | Zero setup, fastest, no external dependencies | Not shared across multiple app instances/processes |
233
+ | `RedisStore` | Multi-instance/distributed deployments | Shared counters across nodes, atomic operations via Lua scripts | Requires Redis and network round-trips |
234
+
235
+ ## Writing Custom Stores
236
+
237
+ Implement the `RateLimitStore` interface:
238
+
239
+ ```ts
240
+ export interface RateLimitStore {
241
+ increment(key: string): Promise<{
242
+ totalHits: number;
243
+ remaining: number;
244
+ resetTime: Date;
245
+ isBlocked: boolean;
246
+ }>;
247
+ decrement(key: string): Promise<void>;
248
+ reset(key: string): Promise<void>;
249
+ shutdown(): Promise<void>;
250
+ }
251
+ ```
252
+
253
+ Use your custom store by passing `store` in options:
254
+
255
+ ```ts
256
+ app.use(expressRateLimiter({ store: myCustomStore, maxRequests: 100, windowMs: 60_000 }));
257
+ ```
258
+
259
+ ## Contributing
260
+
261
+ Contributions are welcome.
262
+
263
+ 1. Fork the repository
264
+ 2. Create a feature branch
265
+ 3. Add or update tests
266
+ 4. Run checks locally:
267
+ - `npm test`
268
+ - `npm run build`
269
+ - `npm run lint`
270
+ 5. Open a pull request with context and rationale
271
+
272
+ ## License
273
+
274
+ MIT
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ratelimit-flex — flexible rate limiting for Node.js
3
+ */
4
+ import { expressRateLimiter } from './middleware/express.js';
5
+ import { fastifyRateLimiter } from './middleware/fastify.js';
6
+ import type { RateLimitOptions } from './types/index.js';
7
+ export declare const VERSION = "0.1.0";
8
+ export { expressRateLimiter, fastifyRateLimiter };
9
+ export { RateLimitEngine, createRateLimiter as createRateLimitEngine, defaultKeyGenerator, type RateLimitConsumeResult, type RateLimiterConfigInput, } from './strategies/rate-limit-engine.js';
10
+ export { MemoryStore } from './stores/memory-store.js';
11
+ export { RedisStore } from './stores/redis-store.js';
12
+ export { fixedWindowDefaults, slidingWindowDefaults, tokenBucketDefaults } from './strategies/defaults.js';
13
+ export * from './types/index.js';
14
+ export { RateLimitStrategy } from './types/index.js';
15
+ /**
16
+ * Convenience factory that returns both Express middleware and Fastify plugin.
17
+ *
18
+ * Usage:
19
+ * ```ts
20
+ * const limiter = createRateLimiter({ maxRequests: 100 });
21
+ * app.use(limiter.express); // Express
22
+ * await app.register(limiter.fastify); // Fastify
23
+ * ```
24
+ *
25
+ * Prefer importing `expressRateLimiter` or `fastifyRateLimiter` directly when framework is known.
26
+ */
27
+ export declare function createRateLimiter(options: Partial<RateLimitOptions>): {
28
+ express: import("express").RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
29
+ fastify: typeof fastifyRateLimiter;
30
+ };
31
+ export default expressRateLimiter;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;AAGlD,OAAO,EACL,eAAe,EACf,iBAAiB,IAAI,qBAAqB,EAC1C,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG3G,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC;;aActC,OAAO,kBAAkB;EAEtD;AAGD,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * ratelimit-flex — flexible rate limiting for Node.js
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ var __importDefault = (this && this.__importDefault) || function (mod) {
20
+ return (mod && mod.__esModule) ? mod : { "default": mod };
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.RateLimitStrategy = exports.tokenBucketDefaults = exports.slidingWindowDefaults = exports.fixedWindowDefaults = exports.RedisStore = exports.MemoryStore = exports.defaultKeyGenerator = exports.createRateLimitEngine = exports.RateLimitEngine = exports.fastifyRateLimiter = exports.expressRateLimiter = exports.VERSION = void 0;
24
+ exports.createRateLimiter = createRateLimiter;
25
+ const express_js_1 = require("./middleware/express.js");
26
+ Object.defineProperty(exports, "expressRateLimiter", { enumerable: true, get: function () { return express_js_1.expressRateLimiter; } });
27
+ const fastify_js_1 = require("./middleware/fastify.js");
28
+ Object.defineProperty(exports, "fastifyRateLimiter", { enumerable: true, get: function () { return fastify_js_1.fastifyRateLimiter; } });
29
+ const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
30
+ exports.VERSION = '0.1.0';
31
+ // Core engine and stores
32
+ var rate_limit_engine_js_1 = require("./strategies/rate-limit-engine.js");
33
+ Object.defineProperty(exports, "RateLimitEngine", { enumerable: true, get: function () { return rate_limit_engine_js_1.RateLimitEngine; } });
34
+ Object.defineProperty(exports, "createRateLimitEngine", { enumerable: true, get: function () { return rate_limit_engine_js_1.createRateLimiter; } });
35
+ Object.defineProperty(exports, "defaultKeyGenerator", { enumerable: true, get: function () { return rate_limit_engine_js_1.defaultKeyGenerator; } });
36
+ var memory_store_js_1 = require("./stores/memory-store.js");
37
+ Object.defineProperty(exports, "MemoryStore", { enumerable: true, get: function () { return memory_store_js_1.MemoryStore; } });
38
+ var redis_store_js_1 = require("./stores/redis-store.js");
39
+ Object.defineProperty(exports, "RedisStore", { enumerable: true, get: function () { return redis_store_js_1.RedisStore; } });
40
+ // Built-in defaults
41
+ var defaults_js_1 = require("./strategies/defaults.js");
42
+ Object.defineProperty(exports, "fixedWindowDefaults", { enumerable: true, get: function () { return defaults_js_1.fixedWindowDefaults; } });
43
+ Object.defineProperty(exports, "slidingWindowDefaults", { enumerable: true, get: function () { return defaults_js_1.slidingWindowDefaults; } });
44
+ Object.defineProperty(exports, "tokenBucketDefaults", { enumerable: true, get: function () { return defaults_js_1.tokenBucketDefaults; } });
45
+ // Shared types and enums
46
+ __exportStar(require("./types/index.js"), exports);
47
+ var index_js_1 = require("./types/index.js");
48
+ Object.defineProperty(exports, "RateLimitStrategy", { enumerable: true, get: function () { return index_js_1.RateLimitStrategy; } });
49
+ /**
50
+ * Convenience factory that returns both Express middleware and Fastify plugin.
51
+ *
52
+ * Usage:
53
+ * ```ts
54
+ * const limiter = createRateLimiter({ maxRequests: 100 });
55
+ * app.use(limiter.express); // Express
56
+ * await app.register(limiter.fastify); // Fastify
57
+ * ```
58
+ *
59
+ * Prefer importing `expressRateLimiter` or `fastifyRateLimiter` directly when framework is known.
60
+ */
61
+ function createRateLimiter(options) {
62
+ const wrappedPlugin = (0, fastify_plugin_1.default)(async (fastify, pluginOpts = {}) => {
63
+ const merged = { ...options, ...pluginOpts };
64
+ return fastify_js_1.fastifyRateLimiter(fastify, merged);
65
+ }, { name: 'ratelimit-flex-wrapper' });
66
+ return {
67
+ express: (0, express_js_1.expressRateLimiter)(options),
68
+ fastify: wrappedPlugin,
69
+ };
70
+ }
71
+ // Express is the most common default integration path.
72
+ exports.default = express_js_1.expressRateLimiter;
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;AA0CH,8CAgBC;AAxDD,wDAA6D;AAQpD,mGARA,+BAAkB,OAQA;AAP3B,wDAA6D;AAOhC,mGAPpB,+BAAkB,OAOoB;AAL/C,oEAAgC;AAEnB,QAAA,OAAO,GAAG,OAAO,CAAC;AAK/B,yBAAyB;AACzB,0EAM2C;AALzC,uHAAA,eAAe,OAAA;AACf,6HAAA,iBAAiB,OAAyB;AAC1C,2HAAA,mBAAmB,OAAA;AAIrB,4DAAuD;AAA9C,8GAAA,WAAW,OAAA;AACpB,0DAAqD;AAA5C,4GAAA,UAAU,OAAA;AAEnB,oBAAoB;AACpB,wDAA2G;AAAlG,kHAAA,mBAAmB,OAAA;AAAE,oHAAA,qBAAqB,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAExE,yBAAyB;AACzB,mDAAiC;AACjC,6CAAqD;AAA5C,6GAAA,iBAAiB,OAAA;AAE1B;;;;;;;;;;;GAWG;AACH,SAAgB,iBAAiB,CAAC,OAAkC;IAClE,MAAM,aAAa,GAAG,IAAA,wBAAE,EACtB,KAAK,EAAE,OAAgB,EAAE,aAAwC,EAAE,EAAE,EAAE;QACrE,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;QAC7C,OAAQ,+BAA6F,CACnG,OAAO,EACP,MAAM,CACP,CAAC;IACJ,CAAC,EACD,EAAE,IAAI,EAAE,wBAAwB,EAAE,CACnC,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,IAAA,+BAAkB,EAAC,OAAO,CAAC;QACpC,OAAO,EAAE,aAA0C;KACpD,CAAC;AACJ,CAAC;AAED,uDAAuD;AACvD,kBAAe,+BAAkB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { RequestHandler } from 'express';
2
+ import type { RateLimitInfo, RateLimitOptions } from '../types/index.js';
3
+ declare module 'express-serve-static-core' {
4
+ interface Request {
5
+ /** Populated by {@link expressRateLimiter} after a successful consume (not blocked). */
6
+ rateLimit?: RateLimitInfo;
7
+ }
8
+ }
9
+ /**
10
+ * Express middleware factory. One {@link RateLimitEngine} and store are created per call (singleton for that middleware instance).
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * app.use(expressRateLimiter({ maxRequests: 50 }));
15
+ * ```
16
+ */
17
+ export declare function expressRateLimiter(options: Partial<RateLimitOptions>): RequestHandler;
18
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../../src/middleware/express.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,cAAc,EAAY,MAAM,SAAS,CAAC;AAE/E,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,QAAQ,2BAA2B,CAAC;IACzC,UAAU,OAAO;QACf,wFAAwF;QACxF,SAAS,CAAC,EAAE,aAAa,CAAC;KAC3B;CACF;AAQD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,cAAc,CAkDrF"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expressRateLimiter = expressRateLimiter;
4
+ const rate_limit_engine_js_1 = require("../strategies/rate-limit-engine.js");
5
+ const merge_options_js_1 = require("./merge-options.js");
6
+ function applyHeaders(res, headers) {
7
+ for (const [name, value] of Object.entries(headers)) {
8
+ res.setHeader(name, value);
9
+ }
10
+ }
11
+ /**
12
+ * Express middleware factory. One {@link RateLimitEngine} and store are created per call (singleton for that middleware instance).
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * app.use(expressRateLimiter({ maxRequests: 50 }));
17
+ * ```
18
+ */
19
+ function expressRateLimiter(options) {
20
+ const resolved = (0, merge_options_js_1.mergeRateLimiterOptions)(options);
21
+ const { onLimitReached, ...engineOptions } = resolved;
22
+ const engine = new rate_limit_engine_js_1.RateLimitEngine(engineOptions);
23
+ const keyGen = resolved.keyGenerator ?? rate_limit_engine_js_1.defaultKeyGenerator;
24
+ return async function rateLimitMiddleware(req, res, next) {
25
+ if (resolved.skip?.(req) === true) {
26
+ next();
27
+ return;
28
+ }
29
+ const key = keyGen(req);
30
+ const result = await engine.consumeWithKey(key, req);
31
+ if (resolved.headers !== false) {
32
+ applyHeaders(res, result.headers);
33
+ }
34
+ if (result.isBlocked) {
35
+ if (onLimitReached) {
36
+ await Promise.resolve(onLimitReached(req, result));
37
+ }
38
+ res
39
+ .status(resolved.statusCode ?? 429)
40
+ .json((0, merge_options_js_1.jsonErrorBody)(resolved.message ?? 'Too many requests'));
41
+ return;
42
+ }
43
+ req.rateLimit = (0, merge_options_js_1.toRateLimitInfo)(resolved, result);
44
+ const shouldDecrementFailed = resolved.skipFailedRequests === true;
45
+ const shouldDecrementSuccess = resolved.skipSuccessfulRequests === true;
46
+ if (shouldDecrementFailed || shouldDecrementSuccess) {
47
+ res.once('finish', () => {
48
+ const status = res.statusCode;
49
+ const failed = status >= 400;
50
+ const success = status < 400;
51
+ if ((shouldDecrementFailed && failed) || (shouldDecrementSuccess && success)) {
52
+ void resolved.store.decrement(key).catch(() => {
53
+ /* ignore */
54
+ });
55
+ }
56
+ });
57
+ }
58
+ next();
59
+ };
60
+ }
61
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/middleware/express.ts"],"names":[],"mappings":";;AA0BA,gDAkDC;AA3ED,6EAA0F;AAE1F,yDAA6F;AAS7F,SAAS,YAAY,CAAC,GAAa,EAAE,OAA+B;IAClE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,OAAkC;IACnE,MAAM,QAAQ,GAAG,IAAA,0CAAuB,EAAC,OAAO,CAAC,CAAC;IAClD,MAAM,EAAE,cAAc,EAAE,GAAG,aAAa,EAAE,GAAG,QAAQ,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,sCAAe,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,IAAI,0CAAmB,CAAC;IAE5D,OAAO,KAAK,UAAU,mBAAmB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QACvF,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAExB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAErD,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC/B,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;YACrD,CAAC;YACD,GAAG;iBACA,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,CAAC;iBAClC,IAAI,CAAC,IAAA,gCAAa,EAAC,QAAQ,CAAC,OAAO,IAAI,mBAAmB,CAAC,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,GAAG,IAAA,kCAAe,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAElD,MAAM,qBAAqB,GAAG,QAAQ,CAAC,kBAAkB,KAAK,IAAI,CAAC;QACnE,MAAM,sBAAsB,GAAG,QAAQ,CAAC,sBAAsB,KAAK,IAAI,CAAC;QAExE,IAAI,qBAAqB,IAAI,sBAAsB,EAAE,CAAC;YACpD,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACtB,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC;gBAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC;gBAC7B,MAAM,OAAO,GAAG,MAAM,GAAG,GAAG,CAAC;gBAC7B,IAAI,CAAC,qBAAqB,IAAI,MAAM,CAAC,IAAI,CAAC,sBAAsB,IAAI,OAAO,CAAC,EAAE,CAAC;oBAC7E,KAAK,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;wBAC5C,YAAY;oBACd,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { FastifyPluginAsync } from 'fastify';
2
+ import type { RateLimitInfo, RateLimitOptions } from '../types/index.js';
3
+ declare module 'fastify' {
4
+ interface FastifyRequest {
5
+ /** Populated by {@link fastifyRateLimiter} after a successful consume (not blocked). */
6
+ rateLimit?: RateLimitInfo;
7
+ /** Internal: storage key for optional response-based decrement. */
8
+ rateLimitKey?: string;
9
+ /** Internal: when to consider decrement on `onResponse`. */
10
+ rateLimitDecrementFlags?: {
11
+ onFailed: boolean;
12
+ onSuccess: boolean;
13
+ };
14
+ }
15
+ }
16
+ /**
17
+ * Fastify plugin (wrapped with `fastify-plugin` for correct encapsulation).
18
+ * Registers `onRequest` / `onResponse` hooks; one {@link RateLimitEngine} and store per registration.
19
+ */
20
+ export declare const fastifyRateLimiter: FastifyPluginAsync<Partial<RateLimitOptions>>;
21
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../../src/middleware/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,wFAAwF;QACxF,SAAS,CAAC,EAAE,aAAa,CAAC;QAC1B,mEAAmE;QACnE,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,4DAA4D;QAC5D,uBAAuB,CAAC,EAAE;YACxB,QAAQ,EAAE,OAAO,CAAC;YAClB,SAAS,EAAE,OAAO,CAAC;SACpB,CAAC;KACH;CACF;AA6DD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,+CAE7B,CAAC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fastifyRateLimiter = void 0;
7
+ const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8
+ const rate_limit_engine_js_1 = require("../strategies/rate-limit-engine.js");
9
+ const merge_options_js_1 = require("./merge-options.js");
10
+ const plugin = async (fastify, options) => {
11
+ const resolved = (0, merge_options_js_1.mergeRateLimiterOptions)(options);
12
+ const { onLimitReached, ...engineOptions } = resolved;
13
+ const engine = new rate_limit_engine_js_1.RateLimitEngine(engineOptions);
14
+ const keyGen = resolved.keyGenerator ?? rate_limit_engine_js_1.defaultKeyGenerator;
15
+ fastify.addHook('onRequest', async (request, reply) => {
16
+ if (resolved.skip?.(request) === true) {
17
+ return;
18
+ }
19
+ const key = keyGen(request);
20
+ const result = await engine.consumeWithKey(key, request);
21
+ if (resolved.headers !== false) {
22
+ for (const [name, value] of Object.entries(result.headers)) {
23
+ reply.header(name, value);
24
+ }
25
+ }
26
+ if (result.isBlocked) {
27
+ if (onLimitReached) {
28
+ await Promise.resolve(onLimitReached(request, result));
29
+ }
30
+ await reply
31
+ .status(resolved.statusCode ?? 429)
32
+ .send((0, merge_options_js_1.jsonErrorBody)(resolved.message ?? 'Too many requests'));
33
+ return;
34
+ }
35
+ request.rateLimit = (0, merge_options_js_1.toRateLimitInfo)(resolved, result);
36
+ const onFailed = resolved.skipFailedRequests === true;
37
+ const onSuccess = resolved.skipSuccessfulRequests === true;
38
+ if (onFailed || onSuccess) {
39
+ request.rateLimitKey = key;
40
+ request.rateLimitDecrementFlags = { onFailed, onSuccess };
41
+ }
42
+ });
43
+ fastify.addHook('onResponse', async (request, reply) => {
44
+ const key = request.rateLimitKey;
45
+ const flags = request.rateLimitDecrementFlags;
46
+ if (!key || !flags) {
47
+ return;
48
+ }
49
+ const status = reply.statusCode;
50
+ const failed = status >= 400;
51
+ const success = status < 400;
52
+ if ((flags.onFailed && failed) || (flags.onSuccess && success)) {
53
+ void resolved.store.decrement(key).catch(() => {
54
+ /* ignore */
55
+ });
56
+ }
57
+ });
58
+ };
59
+ /**
60
+ * Fastify plugin (wrapped with `fastify-plugin` for correct encapsulation).
61
+ * Registers `onRequest` / `onResponse` hooks; one {@link RateLimitEngine} and store per registration.
62
+ */
63
+ exports.fastifyRateLimiter = (0, fastify_plugin_1.default)(plugin, {
64
+ name: 'ratelimit-flex',
65
+ });
66
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../../src/middleware/fastify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Framework middleware adapters (Express, Fastify, etc.) */
2
+ export { expressRateLimiter } from './express.js';
3
+ export { fastifyRateLimiter } from './fastify.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /** Framework middleware adapters (Express, Fastify, etc.) */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.fastifyRateLimiter = exports.expressRateLimiter = void 0;
5
+ var express_js_1 = require("./express.js");
6
+ Object.defineProperty(exports, "expressRateLimiter", { enumerable: true, get: function () { return express_js_1.expressRateLimiter; } });
7
+ var fastify_js_1 = require("./fastify.js");
8
+ Object.defineProperty(exports, "fastifyRateLimiter", { enumerable: true, get: function () { return fastify_js_1.fastifyRateLimiter; } });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":";AAAA,6DAA6D;;;AAE7D,2CAAkD;AAAzC,gHAAA,kBAAkB,OAAA;AAC3B,2CAAkD;AAAzC,gHAAA,kBAAkB,OAAA"}
@@ -0,0 +1,16 @@
1
+ import type { RateLimitInfo, RateLimitOptions, RateLimitResult } from '../types/index.js';
2
+ export declare const baseDefaults: {
3
+ readonly headers: true;
4
+ readonly statusCode: 429;
5
+ readonly message: "Too many requests";
6
+ readonly skipFailedRequests: false;
7
+ readonly skipSuccessfulRequests: false;
8
+ };
9
+ export declare function getLimit(opts: RateLimitOptions): number;
10
+ /**
11
+ * Merge partial options with strategy defaults and ensure a {@link MemoryStore} when `store` is omitted.
12
+ */
13
+ export declare function mergeRateLimiterOptions(options: Partial<RateLimitOptions>): RateLimitOptions;
14
+ export declare function toRateLimitInfo(opts: RateLimitOptions, result: RateLimitResult): RateLimitInfo;
15
+ export declare function jsonErrorBody(message: string | object): object;
16
+ //# sourceMappingURL=merge-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-options.d.ts","sourceRoot":"","sources":["../../../src/middleware/merge-options.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG1F,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX,wBAAgB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAKvD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAwC5F;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,eAAe,GAAG,aAAa,CAO9F;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE9D"}