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
@@ -0,0 +1,452 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.RedisStore = void 0;
37
+ exports.adaptIoRedisClient = adaptIoRedisClient;
38
+ exports.adaptNodeRedisClient = adaptNodeRedisClient;
39
+ const index_js_1 = require("../types/index.js");
40
+ const DEFAULT_PREFIX = 'rlf:';
41
+ /** Sliding window: ZSET prune + ZADD + ZCARD. KEYS[1]=zset, ARGV: now, windowMs, maxRequests, member */
42
+ const LUA_SLIDING_INCR = `
43
+ local zkey = KEYS[1]
44
+ local now = tonumber(ARGV[1])
45
+ local window_ms = tonumber(ARGV[2])
46
+ local max_requests = tonumber(ARGV[3])
47
+ local member = ARGV[4]
48
+
49
+ redis.call('ZREMRANGEBYSCORE', zkey, '-inf', now - window_ms)
50
+ redis.call('ZADD', zkey, now, member)
51
+ local count = tonumber(redis.call('ZCARD', zkey))
52
+ redis.call('PEXPIRE', zkey, window_ms)
53
+
54
+ local blocked = 0
55
+ if count > max_requests then blocked = 1 end
56
+
57
+ local oldest_score = now
58
+ if count > 0 then
59
+ local r = redis.call('ZRANGE', zkey, 0, 0, 'WITHSCORES')
60
+ if r[2] ~= nil then
61
+ oldest_score = tonumber(r[2])
62
+ end
63
+ end
64
+ local reset_at = oldest_score + window_ms
65
+
66
+ return { count, blocked, reset_at }
67
+ `;
68
+ const LUA_SLIDING_DECR = `
69
+ redis.call('ZPOPMAX', KEYS[1])
70
+ return 1
71
+ `;
72
+ /** Fixed window: atomic INCR + PEXPIRE on first hit. KEYS[1]=counter, ARGV: windowMs, maxRequests, now */
73
+ const LUA_FIXED_INCR = `
74
+ local k = KEYS[1]
75
+ local window_ms = tonumber(ARGV[1])
76
+ local max_requests = tonumber(ARGV[2])
77
+ local now = tonumber(ARGV[3])
78
+
79
+ local current = tonumber(redis.call('INCR', k))
80
+ if current == 1 then
81
+ redis.call('PEXPIRE', k, window_ms)
82
+ end
83
+
84
+ local pttl = tonumber(redis.call('PTTL', k))
85
+ if pttl < 0 then pttl = window_ms end
86
+ local reset_at = now + pttl
87
+
88
+ local blocked = 0
89
+ if current > max_requests then blocked = 1 end
90
+
91
+ return { current, blocked, reset_at }
92
+ `;
93
+ const LUA_FIXED_DECR = `
94
+ local k = KEYS[1]
95
+ local v = tonumber(redis.call('GET', k) or '0')
96
+ if v > 0 then
97
+ redis.call('DECR', k)
98
+ end
99
+ return v
100
+ `;
101
+ /** Token bucket: HSET tokens + last_refill. KEYS[1]=hash, ARGV: now, tpi, interval_ms, bucket_size */
102
+ const LUA_BUCKET_INCR = `
103
+ local key = KEYS[1]
104
+ local now = tonumber(ARGV[1])
105
+ local tokens_per_interval = tonumber(ARGV[2])
106
+ local interval_ms = tonumber(ARGV[3])
107
+ local bucket_size = tonumber(ARGV[4])
108
+
109
+ local tokens_s = redis.call('HGET', key, 'tokens')
110
+ local last_s = redis.call('HGET', key, 'last_refill')
111
+
112
+ local tokens
113
+ local last_refill
114
+
115
+ if tokens_s == false then
116
+ tokens = bucket_size
117
+ last_refill = now
118
+ else
119
+ tokens = tonumber(tokens_s)
120
+ last_refill = tonumber(last_s)
121
+ end
122
+
123
+ local elapsed = now - last_refill
124
+ local intervals = math.floor(elapsed / interval_ms)
125
+ if intervals > 0 then
126
+ tokens = math.min(bucket_size, tokens + intervals * tokens_per_interval)
127
+ last_refill = last_refill + intervals * interval_ms
128
+ end
129
+
130
+ if tokens >= 1 then
131
+ tokens = tokens - 1
132
+ redis.call('HSET', key, 'tokens', tostring(tokens), 'last_refill', tostring(last_refill))
133
+ redis.call('PEXPIRE', key, interval_ms * 10)
134
+ local remaining = tokens
135
+ local total_hits = bucket_size - remaining
136
+ local next_tick = last_refill + interval_ms
137
+ return { 1, remaining, total_hits, 0, next_tick }
138
+ end
139
+
140
+ redis.call('HSET', key, 'tokens', tostring(tokens), 'last_refill', tostring(last_refill))
141
+ redis.call('PEXPIRE', key, interval_ms * 10)
142
+ local next_refill = last_refill + interval_ms
143
+ return { 0, tokens, bucket_size, 1, next_refill }
144
+ `;
145
+ const LUA_BUCKET_DECR = `
146
+ local key = KEYS[1]
147
+ local bucket_size = tonumber(ARGV[1])
148
+ local tokens_s = redis.call('HGET', key, 'tokens')
149
+ local tokens
150
+ if tokens_s == false then
151
+ return 0
152
+ end
153
+ tokens = tonumber(tokens_s)
154
+ tokens = math.min(bucket_size, tokens + 1)
155
+ redis.call('HSET', key, 'tokens', tostring(tokens))
156
+ return 1
157
+ `;
158
+ const LUA_DEL = `
159
+ return redis.call('DEL', unpack(KEYS))
160
+ `;
161
+ /**
162
+ * Wrap an **ioredis** client instance to satisfy {@link RedisLikeClient} without adding a compile-time dependency.
163
+ */
164
+ function adaptIoRedisClient(client) {
165
+ return {
166
+ get: (k) => client.get(k),
167
+ set: (k, v, ...rest) => client.set(k, v, ...rest),
168
+ eval: (script, numKeys, ...rest) => client.eval(script, numKeys, ...rest.map((a) => String(a))),
169
+ del: client.del?.bind(client),
170
+ quit: client.quit?.bind(client),
171
+ disconnect: client.disconnect ? async () => await client.disconnect() : undefined,
172
+ };
173
+ }
174
+ /**
175
+ * Wrap **node-redis** v4+ clients (`eval(script, { keys, arguments })`).
176
+ * Does not add a `redis` package dependency — pass your connected client instance.
177
+ */
178
+ function adaptNodeRedisClient(client) {
179
+ return {
180
+ get: async (k) => (await client.get(k)) ?? null,
181
+ set: (k, v, ...rest) => client.set(k, v, ...rest),
182
+ eval: (script, numKeys, ...rest) => {
183
+ const keys = rest.slice(0, numKeys);
184
+ const args = rest.slice(numKeys);
185
+ return client.eval(script, { keys, arguments: args });
186
+ },
187
+ del: client.del?.bind(client),
188
+ quit: client.quit?.bind(client),
189
+ disconnect: client.disconnect ? async () => await client.disconnect() : undefined,
190
+ };
191
+ }
192
+ /**
193
+ * Redis-backed {@link RateLimitStore} using Lua for atomicity.
194
+ *
195
+ * Pass either `client` (recommended) or `url` (loads optional peer `ioredis` at runtime).
196
+ */
197
+ class RedisStore {
198
+ constructor(options) {
199
+ this.client = null;
200
+ /** Connection created from `url` — closed on {@link RedisStore.shutdown}. */
201
+ this.ownedRedis = null;
202
+ if (options.url && options.client) {
203
+ throw new Error('RedisStore: pass either "url" or "client", not both');
204
+ }
205
+ if (!options.url && !options.client) {
206
+ throw new Error('RedisStore: pass "url" or "client"');
207
+ }
208
+ this.strategy = options.strategy;
209
+ this.keyPrefix = options.keyPrefix ?? DEFAULT_PREFIX;
210
+ this.onWarn =
211
+ options.onWarn ?? ((msg, err) => console.warn(`[ratelimit-flex] ${msg}`, err ?? ''));
212
+ if (options.strategy === index_js_1.RateLimitStrategy.TOKEN_BUCKET) {
213
+ this.windowMs = 0;
214
+ this.maxRequests = 0;
215
+ this.tokensPerInterval = options.tokensPerInterval;
216
+ this.refillIntervalMs = options.interval;
217
+ this.bucketSize = options.bucketSize;
218
+ }
219
+ else {
220
+ this.windowMs = options.windowMs;
221
+ this.maxRequests = options.maxRequests;
222
+ this.tokensPerInterval = 0;
223
+ this.refillIntervalMs = 0;
224
+ this.bucketSize = 0;
225
+ }
226
+ if (options.client) {
227
+ this.clientPromise = Promise.resolve(options.client);
228
+ }
229
+ else {
230
+ this.clientPromise = this.connectFromUrl(options.url);
231
+ }
232
+ }
233
+ async connectFromUrl(url) {
234
+ try {
235
+ // @ts-expect-error - ioredis is an optional peer dependency
236
+ const mod = (await Promise.resolve().then(() => __importStar(require('ioredis'))));
237
+ const Redis = mod.default;
238
+ const raw = new Redis(url);
239
+ this.ownedRedis = raw;
240
+ return adaptIoRedisClient(raw);
241
+ }
242
+ catch (err) {
243
+ this.onWarn('Failed to load optional peer "ioredis". Install it or pass a pre-configured "client".', err);
244
+ throw err;
245
+ }
246
+ }
247
+ warn(message, error) {
248
+ this.onWarn(message, error);
249
+ }
250
+ async getClient() {
251
+ if (this.client) {
252
+ return this.client;
253
+ }
254
+ const c = await this.clientPromise;
255
+ this.client = c;
256
+ return c;
257
+ }
258
+ redisKey(kind, key) {
259
+ return `${this.keyPrefix}${kind}:${key}`;
260
+ }
261
+ async evalScript(script, keys, args) {
262
+ try {
263
+ const r = await this.getClient();
264
+ const flat = [...keys.map(String), ...args.map(String)];
265
+ return await r.eval(script, keys.length, ...flat);
266
+ }
267
+ catch (err) {
268
+ this.warn('Redis EVAL failed', err);
269
+ return null;
270
+ }
271
+ }
272
+ async delKeys(...keys) {
273
+ if (keys.length === 0) {
274
+ return;
275
+ }
276
+ try {
277
+ const r = await this.getClient();
278
+ if (r.del) {
279
+ await r.del(...keys);
280
+ return;
281
+ }
282
+ await r.eval(LUA_DEL, keys.length, ...keys.map(String));
283
+ }
284
+ catch (err) {
285
+ this.warn('Redis DEL failed', err);
286
+ }
287
+ }
288
+ failOpenResult() {
289
+ const now = Date.now();
290
+ if (this.strategy === index_js_1.RateLimitStrategy.TOKEN_BUCKET) {
291
+ return {
292
+ totalHits: 0,
293
+ remaining: this.bucketSize,
294
+ resetTime: new Date(now + this.refillIntervalMs),
295
+ isBlocked: false,
296
+ };
297
+ }
298
+ return {
299
+ totalHits: 0,
300
+ remaining: this.maxRequests,
301
+ resetTime: new Date(now + this.windowMs),
302
+ isBlocked: false,
303
+ };
304
+ }
305
+ /** @inheritdoc */
306
+ async increment(key) {
307
+ switch (this.strategy) {
308
+ case index_js_1.RateLimitStrategy.SLIDING_WINDOW:
309
+ return this.incrSliding(key);
310
+ case index_js_1.RateLimitStrategy.FIXED_WINDOW:
311
+ return this.incrFixed(key);
312
+ case index_js_1.RateLimitStrategy.TOKEN_BUCKET:
313
+ return this.incrBucket(key);
314
+ default: {
315
+ const _ = this.strategy;
316
+ return Promise.reject(new Error(`Unsupported strategy: ${String(_)}`));
317
+ }
318
+ }
319
+ }
320
+ async incrSliding(key) {
321
+ const now = Date.now();
322
+ const member = `${now}:${Math.random().toString(36).slice(2)}`;
323
+ const rk = this.redisKey('sw', key);
324
+ const raw = await this.evalScript(LUA_SLIDING_INCR, [rk], [now, this.windowMs, this.maxRequests, member]);
325
+ if (raw === null || !Array.isArray(raw) || raw.length < 3) {
326
+ return this.failOpenResult();
327
+ }
328
+ const count = Number(raw[0]);
329
+ const blocked = Number(raw[1]) === 1;
330
+ const resetMs = Number(raw[2]);
331
+ if (Number.isNaN(count) || Number.isNaN(resetMs)) {
332
+ return this.failOpenResult();
333
+ }
334
+ const remaining = blocked ? 0 : Math.max(0, this.maxRequests - count);
335
+ return {
336
+ totalHits: count,
337
+ remaining,
338
+ resetTime: new Date(resetMs),
339
+ isBlocked: blocked,
340
+ };
341
+ }
342
+ async incrFixed(key) {
343
+ const now = Date.now();
344
+ const rk = this.redisKey('fw', key);
345
+ const raw = await this.evalScript(LUA_FIXED_INCR, [rk], [this.windowMs, this.maxRequests, now]);
346
+ if (raw === null || !Array.isArray(raw) || raw.length < 3) {
347
+ return this.failOpenResult();
348
+ }
349
+ const current = Number(raw[0]);
350
+ const blocked = Number(raw[1]) === 1;
351
+ const resetMs = Number(raw[2]);
352
+ if (Number.isNaN(current) || Number.isNaN(resetMs)) {
353
+ return this.failOpenResult();
354
+ }
355
+ const remaining = blocked ? 0 : Math.max(0, this.maxRequests - current);
356
+ return {
357
+ totalHits: current,
358
+ remaining,
359
+ resetTime: new Date(resetMs),
360
+ isBlocked: blocked,
361
+ };
362
+ }
363
+ async incrBucket(key) {
364
+ const now = Date.now();
365
+ const rk = this.redisKey('tb', key);
366
+ const raw = await this.evalScript(LUA_BUCKET_INCR, [rk], [now, this.tokensPerInterval, this.refillIntervalMs, this.bucketSize]);
367
+ if (raw === null || !Array.isArray(raw) || raw.length < 5) {
368
+ return this.failOpenResult();
369
+ }
370
+ const remaining = Number(raw[1]);
371
+ const totalHits = Number(raw[2]);
372
+ const blocked = Number(raw[3]) === 1;
373
+ const nextMs = Number(raw[4]);
374
+ if (Number.isNaN(remaining) || Number.isNaN(totalHits) || Number.isNaN(nextMs)) {
375
+ return this.failOpenResult();
376
+ }
377
+ return {
378
+ totalHits,
379
+ remaining,
380
+ resetTime: new Date(nextMs),
381
+ isBlocked: blocked,
382
+ };
383
+ }
384
+ /** @inheritdoc */
385
+ async decrement(key) {
386
+ try {
387
+ switch (this.strategy) {
388
+ case index_js_1.RateLimitStrategy.SLIDING_WINDOW: {
389
+ const rk = this.redisKey('sw', key);
390
+ await this.evalScript(LUA_SLIDING_DECR, [rk], []);
391
+ break;
392
+ }
393
+ case index_js_1.RateLimitStrategy.FIXED_WINDOW: {
394
+ const rk = this.redisKey('fw', key);
395
+ await this.evalScript(LUA_FIXED_DECR, [rk], []);
396
+ break;
397
+ }
398
+ case index_js_1.RateLimitStrategy.TOKEN_BUCKET: {
399
+ const rk = this.redisKey('tb', key);
400
+ await this.evalScript(LUA_BUCKET_DECR, [rk], [this.bucketSize]);
401
+ break;
402
+ }
403
+ default:
404
+ break;
405
+ }
406
+ }
407
+ catch (err) {
408
+ this.warn('Redis decrement failed', err);
409
+ }
410
+ }
411
+ /** @inheritdoc */
412
+ async reset(key) {
413
+ const keys = [];
414
+ switch (this.strategy) {
415
+ case index_js_1.RateLimitStrategy.SLIDING_WINDOW:
416
+ keys.push(this.redisKey('sw', key));
417
+ break;
418
+ case index_js_1.RateLimitStrategy.FIXED_WINDOW:
419
+ keys.push(this.redisKey('fw', key));
420
+ break;
421
+ case index_js_1.RateLimitStrategy.TOKEN_BUCKET:
422
+ keys.push(this.redisKey('tb', key));
423
+ break;
424
+ default:
425
+ break;
426
+ }
427
+ await this.delKeys(...keys);
428
+ }
429
+ /** @inheritdoc */
430
+ async shutdown() {
431
+ this.client = null;
432
+ const owned = this.ownedRedis;
433
+ this.ownedRedis = null;
434
+ if (!owned) {
435
+ return Promise.resolve();
436
+ }
437
+ try {
438
+ if (typeof owned.quit === 'function') {
439
+ await owned.quit();
440
+ }
441
+ else if (typeof owned.disconnect === 'function') {
442
+ await owned.disconnect();
443
+ }
444
+ }
445
+ catch (err) {
446
+ this.warn('Redis shutdown (quit/disconnect) failed', err);
447
+ }
448
+ return Promise.resolve();
449
+ }
450
+ }
451
+ exports.RedisStore = RedisStore;
452
+ //# sourceMappingURL=redis-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-store.js","sourceRoot":"","sources":["../../../src/stores/redis-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { RateLimitStrategy } from '../types/index.js';
2
+ /**
3
+ * Sensible defaults for sliding-window rate limiting (no {@link RateLimitOptionsBase.store} — pass a store or use {@link createRateLimiter}).
4
+ */
5
+ export declare const slidingWindowDefaults: {
6
+ readonly strategy: RateLimitStrategy.SLIDING_WINDOW;
7
+ readonly windowMs: 60000;
8
+ readonly maxRequests: 100;
9
+ };
10
+ /**
11
+ * Sensible defaults for fixed-window rate limiting.
12
+ */
13
+ export declare const fixedWindowDefaults: {
14
+ readonly strategy: RateLimitStrategy.FIXED_WINDOW;
15
+ readonly windowMs: 60000;
16
+ readonly maxRequests: 100;
17
+ };
18
+ /**
19
+ * Sensible defaults for token-bucket rate limiting.
20
+ * Use {@link TokenBucketRateLimitOptions.bucketSize} for burst capacity (not `maxRequests`).
21
+ */
22
+ export declare const tokenBucketDefaults: {
23
+ readonly strategy: RateLimitStrategy.TOKEN_BUCKET;
24
+ readonly tokensPerInterval: 10;
25
+ readonly interval: 60000;
26
+ readonly bucketSize: 100;
27
+ };
28
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/strategies/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAIxB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tokenBucketDefaults = exports.fixedWindowDefaults = exports.slidingWindowDefaults = void 0;
4
+ const index_js_1 = require("../types/index.js");
5
+ /**
6
+ * Sensible defaults for sliding-window rate limiting (no {@link RateLimitOptionsBase.store} — pass a store or use {@link createRateLimiter}).
7
+ */
8
+ exports.slidingWindowDefaults = {
9
+ strategy: index_js_1.RateLimitStrategy.SLIDING_WINDOW,
10
+ windowMs: 60000,
11
+ maxRequests: 100,
12
+ };
13
+ /**
14
+ * Sensible defaults for fixed-window rate limiting.
15
+ */
16
+ exports.fixedWindowDefaults = {
17
+ strategy: index_js_1.RateLimitStrategy.FIXED_WINDOW,
18
+ windowMs: 60000,
19
+ maxRequests: 100,
20
+ };
21
+ /**
22
+ * Sensible defaults for token-bucket rate limiting.
23
+ * Use {@link TokenBucketRateLimitOptions.bucketSize} for burst capacity (not `maxRequests`).
24
+ */
25
+ exports.tokenBucketDefaults = {
26
+ strategy: index_js_1.RateLimitStrategy.TOKEN_BUCKET,
27
+ tokensPerInterval: 10,
28
+ interval: 60000,
29
+ bucketSize: 100,
30
+ };
31
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../src/strategies/defaults.ts"],"names":[],"mappings":";;;AAAA,gDAAsD;AAEtD;;GAEG;AACU,QAAA,qBAAqB,GAAG;IACnC,QAAQ,EAAE,4BAAiB,CAAC,cAAc;IAC1C,QAAQ,EAAE,KAAM;IAChB,WAAW,EAAE,GAAG;CACR,CAAC;AAEX;;GAEG;AACU,QAAA,mBAAmB,GAAG;IACjC,QAAQ,EAAE,4BAAiB,CAAC,YAAY;IACxC,QAAQ,EAAE,KAAM;IAChB,WAAW,EAAE,GAAG;CACR,CAAC;AAEX;;;GAGG;AACU,QAAA,mBAAmB,GAAG;IACjC,QAAQ,EAAE,4BAAiB,CAAC,YAAY;IACxC,iBAAiB,EAAE,EAAE;IACrB,QAAQ,EAAE,KAAM;IAChB,UAAU,EAAE,GAAG;CACP,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Rate limiting strategies (sliding window, token bucket, etc.) */
2
+ export { RateLimitEngine, createRateLimiter, defaultKeyGenerator, type RateLimitConsumeResult, type RateLimiterConfigInput, } from './rate-limit-engine.js';
3
+ export { fixedWindowDefaults, slidingWindowDefaults, tokenBucketDefaults } from './defaults.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/strategies/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ /** Rate limiting strategies (sliding window, token bucket, etc.) */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.tokenBucketDefaults = exports.slidingWindowDefaults = exports.fixedWindowDefaults = exports.defaultKeyGenerator = exports.createRateLimiter = exports.RateLimitEngine = void 0;
5
+ var rate_limit_engine_js_1 = require("./rate-limit-engine.js");
6
+ Object.defineProperty(exports, "RateLimitEngine", { enumerable: true, get: function () { return rate_limit_engine_js_1.RateLimitEngine; } });
7
+ Object.defineProperty(exports, "createRateLimiter", { enumerable: true, get: function () { return rate_limit_engine_js_1.createRateLimiter; } });
8
+ Object.defineProperty(exports, "defaultKeyGenerator", { enumerable: true, get: function () { return rate_limit_engine_js_1.defaultKeyGenerator; } });
9
+ var defaults_js_1 = require("./defaults.js");
10
+ Object.defineProperty(exports, "fixedWindowDefaults", { enumerable: true, get: function () { return defaults_js_1.fixedWindowDefaults; } });
11
+ Object.defineProperty(exports, "slidingWindowDefaults", { enumerable: true, get: function () { return defaults_js_1.slidingWindowDefaults; } });
12
+ Object.defineProperty(exports, "tokenBucketDefaults", { enumerable: true, get: function () { return defaults_js_1.tokenBucketDefaults; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/strategies/index.ts"],"names":[],"mappings":";AAAA,oEAAoE;;;AAEpE,+DAMgC;AAL9B,uHAAA,eAAe,OAAA;AACf,yHAAA,iBAAiB,OAAA;AACjB,2HAAA,mBAAmB,OAAA;AAIrB,6CAAgG;AAAvF,kHAAA,mBAAmB,OAAA;AAAE,oHAAA,qBAAqB,OAAA;AAAE,kHAAA,mBAAmB,OAAA"}
@@ -0,0 +1,42 @@
1
+ import type { RateLimitOptions, RateLimitResult, RateLimitStore, TokenBucketRateLimitOptions, WindowRateLimitOptions } from '../types/index.js';
2
+ /** Result of {@link RateLimitEngine.consume} including standard rate-limit headers. */
3
+ export interface RateLimitConsumeResult extends RateLimitResult {
4
+ headers: Record<string, string>;
5
+ }
6
+ /** Options for {@link createRateLimiter}: `store` is optional — a {@link MemoryStore} is created when omitted. */
7
+ export type RateLimiterConfigInput = (Omit<WindowRateLimitOptions, 'store'> & {
8
+ store?: RateLimitStore;
9
+ }) | (Omit<TokenBucketRateLimitOptions, 'store'> & {
10
+ store?: RateLimitStore;
11
+ });
12
+ /**
13
+ * Default key extractor: uses `req.ip`, then `socket.remoteAddress`, else `"unknown"`.
14
+ * Strings are returned as-is so you can pass a precomputed key.
15
+ */
16
+ export declare function defaultKeyGenerator(req: unknown): string;
17
+ /**
18
+ * Build a {@link RateLimitEngine} with optional in-memory store when `store` is omitted.
19
+ */
20
+ export declare function createRateLimiter(options: RateLimiterConfigInput): RateLimitEngine;
21
+ /**
22
+ * Orchestrates key extraction, store increments, header generation, and limit callbacks.
23
+ */
24
+ export declare class RateLimitEngine {
25
+ private readonly options;
26
+ constructor(options: RateLimitOptions);
27
+ /**
28
+ * Applies rate limiting for an incoming request-like value.
29
+ * Uses {@link RateLimitOptionsBase.keyGenerator} (or {@link defaultKeyGenerator}) to derive the storage key.
30
+ */
31
+ consume(req: unknown): Promise<RateLimitConsumeResult>;
32
+ /**
33
+ * Rate limit using a precomputed storage key (skips `keyGenerator`).
34
+ * Pass the same `req` for `onLimitReached` / `skip` callbacks when applicable.
35
+ */
36
+ consumeWithKey(key: string, req?: unknown): Promise<RateLimitConsumeResult>;
37
+ private getLimit;
38
+ private buildPassthroughResult;
39
+ private buildHeaders;
40
+ private composeHeaders;
41
+ }
42
+ //# sourceMappingURL=rate-limit-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-engine.d.ts","sourceRoot":"","sources":["../../../src/strategies/rate-limit-engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,2BAA2B,EAC3B,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAG3B,uFAAuF;AACvF,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,kHAAkH;AAClH,MAAM,MAAM,sBAAsB,GAC9B,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,GACpE,CAAC,IAAI,CAAC,2BAA2B,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,CAAC;AAE9E;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAkBxD;AAuBD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAElF;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;gBAE/B,OAAO,EAAE,gBAAgB;IAIrC;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAK5D;;;OAGG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,OAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAetF,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,cAAc;CAuBvB"}