@fluixi/api 0.0.0-stage → 0.1.0-alpha.2

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -2
  3. package/dist/client.cjs +103 -0
  4. package/dist/client.d.ts +95 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +87 -0
  7. package/dist/client.mjs +82 -0
  8. package/dist/errors.cjs +63 -0
  9. package/dist/errors.d.ts +47 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +55 -0
  12. package/dist/errors.mjs +42 -0
  13. package/dist/index.cjs +667 -0
  14. package/dist/index.d.ts +34 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +26 -0
  17. package/dist/index.mjs +5442 -0
  18. package/dist/input.cjs +91 -0
  19. package/dist/input.d.ts +15 -0
  20. package/dist/input.d.ts.map +1 -0
  21. package/dist/input.js +73 -0
  22. package/dist/input.mjs +68 -0
  23. package/dist/middleware.cjs +41 -0
  24. package/dist/middleware.d.ts +9 -0
  25. package/dist/middleware.d.ts.map +1 -0
  26. package/dist/middleware.js +19 -0
  27. package/dist/middleware.mjs +20 -0
  28. package/dist/openapi.cjs +282 -0
  29. package/dist/openapi.d.ts +60 -0
  30. package/dist/openapi.d.ts.map +1 -0
  31. package/dist/openapi.js +312 -0
  32. package/dist/openapi.mjs +259 -0
  33. package/dist/rate-limit.cjs +158 -0
  34. package/dist/rate-limit.d.ts +69 -0
  35. package/dist/rate-limit.d.ts.map +1 -0
  36. package/dist/rate-limit.js +121 -0
  37. package/dist/rate-limit.mjs +4935 -0
  38. package/dist/route.cjs +192 -0
  39. package/dist/route.d.ts +97 -0
  40. package/dist/route.d.ts.map +1 -0
  41. package/dist/route.js +98 -0
  42. package/dist/route.mjs +169 -0
  43. package/dist/security.cjs +222 -0
  44. package/dist/security.d.ts +64 -0
  45. package/dist/security.d.ts.map +1 -0
  46. package/dist/security.js +135 -0
  47. package/dist/security.mjs +4997 -0
  48. package/dist/standard-schema.cjs +18 -0
  49. package/dist/standard-schema.d.ts +39 -0
  50. package/dist/standard-schema.d.ts.map +1 -0
  51. package/dist/standard-schema.js +6 -0
  52. package/dist/standard-schema.mjs +0 -0
  53. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  54. package/package.json +54 -3
@@ -0,0 +1,4935 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
28
+
29
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/BlockedKeys/BlockedKeys.js
30
+ var require_BlockedKeys = __commonJS({
31
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/BlockedKeys/BlockedKeys.js"(exports, module) {
32
+ "use strict";
33
+ module.exports = class BlockedKeys {
34
+ constructor() {
35
+ this._keys = /* @__PURE__ */ new Map();
36
+ }
37
+ collectExpired() {
38
+ const now = Date.now();
39
+ for (const [key, expire] of this._keys) {
40
+ if (expire <= now) {
41
+ this._keys.delete(key);
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Add new blocked key
47
+ *
48
+ * @param key String
49
+ * @param sec Number
50
+ */
51
+ add(key, sec) {
52
+ this.addMs(key, sec * 1e3);
53
+ }
54
+ /**
55
+ * Add new blocked key for ms
56
+ *
57
+ * @param key String
58
+ * @param ms Number
59
+ */
60
+ addMs(key, ms) {
61
+ this._keys.set(key, Date.now() + ms);
62
+ if (this._keys.size > 999) {
63
+ this.collectExpired();
64
+ }
65
+ }
66
+ /**
67
+ * 0 means not blocked
68
+ *
69
+ * @param key
70
+ * @returns {number}
71
+ */
72
+ msBeforeExpire(key) {
73
+ const expire = this._keys.get(key);
74
+ const now = Date.now();
75
+ if (expire && expire >= now) {
76
+ return expire - now;
77
+ }
78
+ return 0;
79
+ }
80
+ /**
81
+ * If key is not given, delete all data in memory
82
+ *
83
+ * @param {string|undefined} key
84
+ */
85
+ delete(key) {
86
+ if (key) {
87
+ this._keys.delete(key);
88
+ } else {
89
+ this._keys.clear();
90
+ }
91
+ }
92
+ };
93
+ }
94
+ });
95
+
96
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/BlockedKeys/index.js
97
+ var require_BlockedKeys2 = __commonJS({
98
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/BlockedKeys/index.js"(exports, module) {
99
+ "use strict";
100
+ var BlockedKeys = require_BlockedKeys();
101
+ module.exports = BlockedKeys;
102
+ }
103
+ });
104
+
105
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRes.js
106
+ var require_RateLimiterRes = __commonJS({
107
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRes.js"(exports, module) {
108
+ "use strict";
109
+ module.exports = class RateLimiterRes {
110
+ constructor(remainingPoints, msBeforeNext, consumedPoints, isFirstInDuration) {
111
+ this.remainingPoints = typeof remainingPoints === "undefined" ? 0 : remainingPoints;
112
+ this.msBeforeNext = typeof msBeforeNext === "undefined" ? 0 : msBeforeNext;
113
+ this.consumedPoints = typeof consumedPoints === "undefined" ? 0 : consumedPoints;
114
+ this.isFirstInDuration = typeof isFirstInDuration === "undefined" ? false : isFirstInDuration;
115
+ }
116
+ get msBeforeNext() {
117
+ return this._msBeforeNext;
118
+ }
119
+ set msBeforeNext(ms) {
120
+ this._msBeforeNext = ms;
121
+ return this;
122
+ }
123
+ get remainingPoints() {
124
+ return this._remainingPoints;
125
+ }
126
+ set remainingPoints(p) {
127
+ this._remainingPoints = p;
128
+ return this;
129
+ }
130
+ get consumedPoints() {
131
+ return this._consumedPoints;
132
+ }
133
+ set consumedPoints(p) {
134
+ this._consumedPoints = p;
135
+ return this;
136
+ }
137
+ get isFirstInDuration() {
138
+ return this._isFirstInDuration;
139
+ }
140
+ set isFirstInDuration(value) {
141
+ this._isFirstInDuration = Boolean(value);
142
+ }
143
+ _getDecoratedProperties() {
144
+ return {
145
+ remainingPoints: this.remainingPoints,
146
+ msBeforeNext: this.msBeforeNext,
147
+ consumedPoints: this.consumedPoints,
148
+ isFirstInDuration: this.isFirstInDuration
149
+ };
150
+ }
151
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
152
+ return this._getDecoratedProperties();
153
+ }
154
+ toString() {
155
+ return JSON.stringify(this._getDecoratedProperties());
156
+ }
157
+ toJSON() {
158
+ return this._getDecoratedProperties();
159
+ }
160
+ };
161
+ }
162
+ });
163
+
164
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterAbstract.js
165
+ var require_RateLimiterAbstract = __commonJS({
166
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterAbstract.js"(exports, module) {
167
+ "use strict";
168
+ module.exports = class RateLimiterAbstract {
169
+ /**
170
+ *
171
+ * @param opts Object {
172
+ * points: <required>, // Number of points (must be a number, can be negative)
173
+ * duration: <required>, // Per seconds (must be a non-negative number, 0 = never expires)
174
+ * blockDuration: 0, // Block if consumed more than points in current duration for blockDuration seconds
175
+ * execEvenly: false, // Execute allowed actions evenly over duration
176
+ * execEvenlyMinDelayMs: duration * 1000 / points, // ms, works with execEvenly=true option
177
+ * keyPrefix: 'rlflx',
178
+ * }
179
+ */
180
+ constructor(opts = {}) {
181
+ this.points = opts.points;
182
+ this.duration = opts.duration;
183
+ this.blockDuration = opts.blockDuration;
184
+ this.execEvenly = opts.execEvenly;
185
+ this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs;
186
+ this.keyPrefix = opts.keyPrefix;
187
+ }
188
+ get points() {
189
+ return this._points;
190
+ }
191
+ set points(value) {
192
+ if (Number.isFinite(value)) {
193
+ this._points = value;
194
+ } else {
195
+ throw new Error("points must be set and must be a finite number");
196
+ }
197
+ }
198
+ get duration() {
199
+ return this._duration;
200
+ }
201
+ set duration(value) {
202
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
203
+ this._duration = value;
204
+ } else {
205
+ throw new Error("duration must be set and must be a finite, non-negative number");
206
+ }
207
+ }
208
+ get msDuration() {
209
+ return this.duration * 1e3;
210
+ }
211
+ get blockDuration() {
212
+ return this._blockDuration;
213
+ }
214
+ set blockDuration(value) {
215
+ this._blockDuration = typeof value === "undefined" ? 0 : value;
216
+ }
217
+ get msBlockDuration() {
218
+ return this.blockDuration * 1e3;
219
+ }
220
+ get execEvenly() {
221
+ return this._execEvenly;
222
+ }
223
+ set execEvenly(value) {
224
+ this._execEvenly = typeof value === "undefined" ? false : Boolean(value);
225
+ }
226
+ get execEvenlyMinDelayMs() {
227
+ return this._execEvenlyMinDelayMs === void 0 ? this._getExecEvenlyMinDelayMsDefault() : this._execEvenlyMinDelayMs;
228
+ }
229
+ set execEvenlyMinDelayMs(value) {
230
+ this._execEvenlyMinDelayMs = value;
231
+ }
232
+ _getExecEvenlyMinDelayMsDefault() {
233
+ return this.points > 0 ? Math.ceil(this.msDuration / this.points) : 0;
234
+ }
235
+ get keyPrefix() {
236
+ return this._keyPrefix;
237
+ }
238
+ set keyPrefix(value) {
239
+ if (typeof value === "undefined") {
240
+ value = "rlflx";
241
+ }
242
+ if (typeof value !== "string") {
243
+ throw new Error("keyPrefix must be string");
244
+ }
245
+ this._keyPrefix = value;
246
+ }
247
+ _getKeySecDuration(options = {}) {
248
+ return options && options.customDuration >= 0 ? options.customDuration : this.duration;
249
+ }
250
+ getKey(key) {
251
+ return this.keyPrefix.length > 0 ? `${this.keyPrefix}:${key}` : key;
252
+ }
253
+ parseKey(rlKey) {
254
+ return this.keyPrefix.length > 0 ? rlKey.substring(this.keyPrefix.length + 1) : rlKey;
255
+ }
256
+ consume() {
257
+ throw new Error("You have to implement the method 'consume'!");
258
+ }
259
+ penalty() {
260
+ throw new Error("You have to implement the method 'penalty'!");
261
+ }
262
+ reward() {
263
+ throw new Error("You have to implement the method 'reward'!");
264
+ }
265
+ get() {
266
+ throw new Error("You have to implement the method 'get'!");
267
+ }
268
+ set() {
269
+ throw new Error("You have to implement the method 'set'!");
270
+ }
271
+ block() {
272
+ throw new Error("You have to implement the method 'block'!");
273
+ }
274
+ delete() {
275
+ throw new Error("You have to implement the method 'delete'!");
276
+ }
277
+ };
278
+ }
279
+ });
280
+
281
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterCompatibleAbstract.js
282
+ var require_RateLimiterCompatibleAbstract = __commonJS({
283
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterCompatibleAbstract.js"(exports, module) {
284
+ "use strict";
285
+ module.exports = class RateLimiterCompatibleAbstract {
286
+ get keyPrefix() {
287
+ throw new Error("You have to implement the getter 'keyPrefix'!");
288
+ }
289
+ get blockDuration() {
290
+ throw new Error("You have to implement the getter 'blockDuration'!");
291
+ }
292
+ set blockDuration(value) {
293
+ throw new Error("You have to implement the setter 'blockDuration'!");
294
+ }
295
+ get execEvenly() {
296
+ throw new Error("You have to implement the getter 'execEvenly'!");
297
+ }
298
+ set execEvenly(value) {
299
+ throw new Error("You have to implement the setter 'execEvenly'!");
300
+ }
301
+ consume() {
302
+ throw new Error("You have to implement the method 'consume'!");
303
+ }
304
+ penalty() {
305
+ throw new Error("You have to implement the method 'penalty'!");
306
+ }
307
+ reward() {
308
+ throw new Error("You have to implement the method 'reward'!");
309
+ }
310
+ get() {
311
+ throw new Error("You have to implement the method 'get'!");
312
+ }
313
+ set() {
314
+ throw new Error("You have to implement the method 'set'!");
315
+ }
316
+ block() {
317
+ throw new Error("You have to implement the method 'block'!");
318
+ }
319
+ delete() {
320
+ throw new Error("You have to implement the method 'delete'!");
321
+ }
322
+ };
323
+ }
324
+ });
325
+
326
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/helper/isRateLimiterCompatible.js
327
+ var require_isRateLimiterCompatible = __commonJS({
328
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/helper/isRateLimiterCompatible.js"(exports, module) {
329
+ "use strict";
330
+ var RateLimiterAbstract = require_RateLimiterAbstract();
331
+ var RateLimiterCompatibleAbstract = require_RateLimiterCompatibleAbstract();
332
+ module.exports = function isRateLimiterCompatible(obj) {
333
+ return obj instanceof RateLimiterAbstract || obj instanceof RateLimiterCompatibleAbstract;
334
+ };
335
+ }
336
+ });
337
+
338
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterInsuredAbstract.js
339
+ var require_RateLimiterInsuredAbstract = __commonJS({
340
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterInsuredAbstract.js"(exports, module) {
341
+ "use strict";
342
+ var RateLimiterAbstract = require_RateLimiterAbstract();
343
+ var RateLimiterRes2 = require_RateLimiterRes();
344
+ var isRateLimiterCompatible = require_isRateLimiterCompatible();
345
+ module.exports = class RateLimiterInsuredAbstract extends RateLimiterAbstract {
346
+ constructor(opts = {}) {
347
+ super(opts);
348
+ this.insuranceLimiter = opts.insuranceLimiter;
349
+ }
350
+ get insuranceLimiter() {
351
+ return this._insuranceLimiter;
352
+ }
353
+ set insuranceLimiter(value) {
354
+ if (typeof value !== "undefined" && !isRateLimiterCompatible(value)) {
355
+ throw new Error("insuranceLimiter must be instance of RateLimiterAbstract or RateLimiterCompatibleAbstract");
356
+ }
357
+ this._insuranceLimiter = value;
358
+ if (this._insuranceLimiter) {
359
+ this._insuranceLimiter.blockDuration = this.blockDuration;
360
+ this._insuranceLimiter.execEvenly = this.execEvenly;
361
+ }
362
+ }
363
+ _handleError(err, funcName, resolve, reject, params) {
364
+ if (err instanceof RateLimiterRes2) {
365
+ reject(err);
366
+ } else if (!isRateLimiterCompatible(this.insuranceLimiter)) {
367
+ reject(err);
368
+ } else {
369
+ this.insuranceLimiter[funcName](...params).then((res) => {
370
+ resolve(res);
371
+ }).catch((res) => {
372
+ reject(res);
373
+ });
374
+ }
375
+ }
376
+ _operation(funcName, params) {
377
+ const promise = this[funcName](...params);
378
+ return new Promise((resolve, reject) => {
379
+ return promise.then((res) => {
380
+ resolve(res);
381
+ }).catch((err) => {
382
+ if (funcName.startsWith("_")) {
383
+ funcName = funcName.slice(1);
384
+ }
385
+ this._handleError(err, funcName, resolve, reject, params);
386
+ });
387
+ });
388
+ }
389
+ consume(key, pointsToConsume = 1, options = {}) {
390
+ return this._operation("_consume", [key, pointsToConsume, options]);
391
+ }
392
+ penalty(key, points = 1, options = {}) {
393
+ return this._operation("_penalty", [key, points, options]);
394
+ }
395
+ reward(key, points = 1, options = {}) {
396
+ return this._operation("_reward", [key, points, options]);
397
+ }
398
+ get(key, options = {}) {
399
+ return this._operation("_get", [key, options]);
400
+ }
401
+ set(key, points, secDuration, options = {}) {
402
+ return this._operation("_set", [key, points, secDuration, options]);
403
+ }
404
+ block(key, secDuration, options = {}) {
405
+ return this._operation("_block", [key, secDuration, options]);
406
+ }
407
+ delete(key, options = {}) {
408
+ return this._operation("_delete", [key, options]);
409
+ }
410
+ _consume() {
411
+ throw new Error("You have to implement the method '_consume'!");
412
+ }
413
+ _penalty() {
414
+ throw new Error("You have to implement the method '_penalty'!");
415
+ }
416
+ _reward() {
417
+ throw new Error("You have to implement the method '_reward'!");
418
+ }
419
+ _get() {
420
+ throw new Error("You have to implement the method '_get'!");
421
+ }
422
+ _set() {
423
+ throw new Error("You have to implement the method '_set'!");
424
+ }
425
+ _block() {
426
+ throw new Error("You have to implement the method '_block'!");
427
+ }
428
+ _delete() {
429
+ throw new Error("You have to implement the method '_delete'!");
430
+ }
431
+ };
432
+ }
433
+ });
434
+
435
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterStoreAbstract.js
436
+ var require_RateLimiterStoreAbstract = __commonJS({
437
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterStoreAbstract.js"(exports, module) {
438
+ "use strict";
439
+ var BlockedKeys = require_BlockedKeys2();
440
+ var RateLimiterRes2 = require_RateLimiterRes();
441
+ var RateLimiterInsuredAbstract = require_RateLimiterInsuredAbstract();
442
+ module.exports = class RateLimiterStoreAbstract extends RateLimiterInsuredAbstract {
443
+ /**
444
+ *
445
+ * @param opts Object Defaults {
446
+ * ... see other in RateLimiterAbstract
447
+ *
448
+ * inMemoryBlockOnConsumed: 40, // Number of points when key is blocked
449
+ * inMemoryBlockDuration: 10, // Block duration in seconds
450
+ * insuranceLimiter: RateLimiterAbstract
451
+ * }
452
+ */
453
+ constructor(opts = {}) {
454
+ super(opts);
455
+ this.inMemoryBlockOnConsumed = opts.inMemoryBlockOnConsumed;
456
+ this.inMemoryBlockDuration = opts.inMemoryBlockDuration;
457
+ this._inMemoryBlockedKeys = new BlockedKeys();
458
+ }
459
+ get client() {
460
+ return this._client;
461
+ }
462
+ set client(value) {
463
+ if (typeof value === "undefined") {
464
+ throw new Error("storeClient is not set");
465
+ }
466
+ this._client = value;
467
+ }
468
+ /**
469
+ * Have to be launched after consume
470
+ * It blocks key and execute evenly depending on result from store
471
+ *
472
+ * It uses _getRateLimiterRes function to prepare RateLimiterRes from store result
473
+ *
474
+ * @param resolve
475
+ * @param reject
476
+ * @param rlKey
477
+ * @param changedPoints
478
+ * @param storeResult
479
+ * @param {Object} options
480
+ * @private
481
+ */
482
+ _afterConsume(resolve, reject, rlKey, changedPoints, storeResult, options = {}) {
483
+ const res = this._getRateLimiterRes(rlKey, changedPoints, storeResult);
484
+ if (this.inMemoryBlockOnConsumed > 0 && !(this.inMemoryBlockDuration > 0) && res.consumedPoints >= this.inMemoryBlockOnConsumed) {
485
+ this._inMemoryBlockedKeys.addMs(rlKey, res.msBeforeNext);
486
+ if (res.consumedPoints > this.points) {
487
+ return reject(res);
488
+ } else {
489
+ return resolve(res);
490
+ }
491
+ } else if (res.consumedPoints > this.points) {
492
+ let blockPromise = Promise.resolve();
493
+ if (this.blockDuration > 0 && res.consumedPoints <= this.points + changedPoints) {
494
+ res.msBeforeNext = this.msBlockDuration;
495
+ blockPromise = this._block(rlKey, res.consumedPoints, this.msBlockDuration, options);
496
+ }
497
+ if (this.inMemoryBlockOnConsumed > 0 && res.consumedPoints >= this.inMemoryBlockOnConsumed) {
498
+ this._inMemoryBlockedKeys.add(rlKey, this.inMemoryBlockDuration);
499
+ res.msBeforeNext = this.msInMemoryBlockDuration;
500
+ }
501
+ blockPromise.then(() => {
502
+ reject(res);
503
+ }).catch((err) => {
504
+ reject(err);
505
+ });
506
+ } else if (this.execEvenly && this.points > 0 && res.msBeforeNext > 0 && !res.isFirstInDuration) {
507
+ let delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
508
+ if (delay < this.execEvenlyMinDelayMs) {
509
+ delay = res.consumedPoints * this.execEvenlyMinDelayMs;
510
+ }
511
+ res.msBeforeNext = Math.max(res.msBeforeNext - delay, 0);
512
+ setTimeout(resolve, delay, res);
513
+ } else {
514
+ resolve(res);
515
+ }
516
+ }
517
+ getInMemoryBlockMsBeforeExpire(rlKey) {
518
+ if (this.inMemoryBlockOnConsumed > 0) {
519
+ return this._inMemoryBlockedKeys.msBeforeExpire(rlKey);
520
+ }
521
+ return 0;
522
+ }
523
+ get inMemoryBlockOnConsumed() {
524
+ return this._inMemoryBlockOnConsumed;
525
+ }
526
+ set inMemoryBlockOnConsumed(value) {
527
+ this._inMemoryBlockOnConsumed = value ? parseInt(value) : 0;
528
+ if (this.inMemoryBlockOnConsumed > 0 && this.points > this.inMemoryBlockOnConsumed) {
529
+ throw new Error('inMemoryBlockOnConsumed option must be greater or equal "points" option');
530
+ }
531
+ }
532
+ get inMemoryBlockDuration() {
533
+ return this._inMemoryBlockDuration;
534
+ }
535
+ set inMemoryBlockDuration(value) {
536
+ this._inMemoryBlockDuration = value ? parseInt(value) : 0;
537
+ if (this.inMemoryBlockDuration > 0 && this.inMemoryBlockOnConsumed === 0) {
538
+ throw new Error("inMemoryBlockOnConsumed option must be set up");
539
+ }
540
+ }
541
+ get msInMemoryBlockDuration() {
542
+ return this._inMemoryBlockDuration * 1e3;
543
+ }
544
+ /**
545
+ * Block any key for secDuration seconds
546
+ *
547
+ * @param key
548
+ * @param secDuration
549
+ * @param {Object} options
550
+ *
551
+ * @return Promise<RateLimiterRes>
552
+ */
553
+ block(key, secDuration, options = {}) {
554
+ const msDuration = secDuration * 1e3;
555
+ return this._block(this.getKey(key), this.points + 1, msDuration, options);
556
+ }
557
+ /**
558
+ * Set points by key for any duration
559
+ *
560
+ * @param key
561
+ * @param points
562
+ * @param secDuration
563
+ * @param {Object} options
564
+ *
565
+ * @return Promise<RateLimiterRes>
566
+ */
567
+ set(key, points, secDuration, options = {}) {
568
+ const msDuration = (secDuration >= 0 ? secDuration : this.duration) * 1e3;
569
+ return this._set(this.getKey(key), points, msDuration, options);
570
+ }
571
+ /**
572
+ *
573
+ * @param key
574
+ * @param pointsToConsume
575
+ * @param {Object} options
576
+ * @returns Promise<RateLimiterRes>
577
+ */
578
+ _consume(key, pointsToConsume = 1, options = {}) {
579
+ return new Promise((resolve, reject) => {
580
+ const rlKey = this.getKey(key);
581
+ const inMemoryBlockMsBeforeExpire = this.getInMemoryBlockMsBeforeExpire(rlKey);
582
+ if (inMemoryBlockMsBeforeExpire > 0) {
583
+ return reject(new RateLimiterRes2(0, inMemoryBlockMsBeforeExpire));
584
+ }
585
+ this._upsert(rlKey, pointsToConsume, this._getKeySecDuration(options) * 1e3, false, options).then((res) => {
586
+ this._afterConsume(resolve, reject, rlKey, pointsToConsume, res);
587
+ }).catch((err) => reject(err));
588
+ });
589
+ }
590
+ /**
591
+ *
592
+ * @param key
593
+ * @param points
594
+ * @param {Object} options
595
+ * @returns Promise<RateLimiterRes>
596
+ */
597
+ _penalty(key, points = 1, options = {}) {
598
+ const rlKey = this.getKey(key);
599
+ return new Promise((resolve, reject) => {
600
+ this._upsert(rlKey, points, this._getKeySecDuration(options) * 1e3, false, options).then((res) => {
601
+ resolve(this._getRateLimiterRes(rlKey, points, res));
602
+ }).catch((res) => reject(res));
603
+ });
604
+ }
605
+ /**
606
+ *
607
+ * @param key
608
+ * @param points
609
+ * @param {Object} options
610
+ * @returns Promise<RateLimiterRes>
611
+ */
612
+ _reward(key, points = 1, options = {}) {
613
+ const rlKey = this.getKey(key);
614
+ return new Promise((resolve, reject) => {
615
+ this._upsert(rlKey, -points, this._getKeySecDuration(options) * 1e3, false, options).then((res) => {
616
+ resolve(this._getRateLimiterRes(rlKey, -points, res));
617
+ }).catch((res) => reject(res));
618
+ });
619
+ }
620
+ /**
621
+ *
622
+ * @param key
623
+ * @param {Object} options
624
+ * @returns Promise<RateLimiterRes>|null
625
+ */
626
+ get(key, options = {}) {
627
+ const rlKey = this.getKey(key);
628
+ return new Promise((resolve, reject) => {
629
+ this._get(rlKey, options).then((res) => {
630
+ if (res === null || typeof res === "undefined") {
631
+ resolve(null);
632
+ } else {
633
+ resolve(this._getRateLimiterRes(rlKey, 0, res));
634
+ }
635
+ }).catch((err) => {
636
+ this._handleError(err, "get", resolve, reject, [key, options]);
637
+ });
638
+ });
639
+ }
640
+ /**
641
+ *
642
+ * @param key
643
+ * @param {Object} options
644
+ * @returns Promise<boolean>
645
+ */
646
+ delete(key, options = {}) {
647
+ const rlKey = this.getKey(key);
648
+ return new Promise((resolve, reject) => {
649
+ this._delete(rlKey, options).then((res) => {
650
+ this._inMemoryBlockedKeys.delete(rlKey);
651
+ resolve(res);
652
+ }).catch((err) => {
653
+ this._handleError(err, "delete", resolve, reject, [key, options]);
654
+ });
655
+ });
656
+ }
657
+ /**
658
+ * Cleanup keys no-matter expired or not.
659
+ */
660
+ deleteInMemoryBlockedAll() {
661
+ this._inMemoryBlockedKeys.delete();
662
+ }
663
+ /**
664
+ * Get RateLimiterRes object filled depending on storeResult, which specific for exact store
665
+ *
666
+ * @param rlKey
667
+ * @param changedPoints
668
+ * @param storeResult
669
+ * @private
670
+ */
671
+ _getRateLimiterRes(rlKey, changedPoints, storeResult) {
672
+ throw new Error("You have to implement the method '_getRateLimiterRes'!");
673
+ }
674
+ /**
675
+ * Block key for this.msBlockDuration milliseconds
676
+ * Usually, it just prolongs lifetime of key
677
+ *
678
+ * @param rlKey
679
+ * @param initPoints
680
+ * @param msDuration
681
+ * @param {Object} options
682
+ *
683
+ * @return Promise<any>
684
+ */
685
+ _block(rlKey, initPoints, msDuration, options = {}) {
686
+ return new Promise((resolve, reject) => {
687
+ this._upsert(rlKey, initPoints, msDuration, true, options).then(() => {
688
+ resolve(new RateLimiterRes2(0, msDuration > 0 ? msDuration : -1, initPoints));
689
+ }).catch((err) => {
690
+ this._handleError(err, "block", resolve, reject, [this.parseKey(rlKey), msDuration / 1e3, options]);
691
+ });
692
+ });
693
+ }
694
+ /**
695
+ * @param rlKey
696
+ * @param points
697
+ * @param msDuration
698
+ * @param {Object} options
699
+ *
700
+ * @return Promise<any>
701
+ */
702
+ _set(rlKey, points, msDuration, options = {}) {
703
+ return new Promise((resolve, reject) => {
704
+ this._upsert(rlKey, points, msDuration, true, options).then(() => {
705
+ resolve(new RateLimiterRes2(0, msDuration > 0 ? msDuration : -1, points));
706
+ }).catch((err) => {
707
+ this._handleError(err, "set", resolve, reject, [this.parseKey(rlKey), points, msDuration / 1e3, options]);
708
+ });
709
+ });
710
+ }
711
+ /**
712
+ * Have to be implemented in every limiter
713
+ * Resolve with raw result from Store OR null if rlKey is not set
714
+ * or Reject with error
715
+ *
716
+ * @param rlKey
717
+ * @param {Object} options
718
+ * @private
719
+ *
720
+ * @return Promise<any>
721
+ */
722
+ _get(rlKey, options = {}) {
723
+ throw new Error("You have to implement the method '_get'!");
724
+ }
725
+ /**
726
+ * Have to be implemented
727
+ * Resolve with true OR false if rlKey doesn't exist
728
+ * or Reject with error
729
+ *
730
+ * @param rlKey
731
+ * @param {Object} options
732
+ * @private
733
+ *
734
+ * @return Promise<any>
735
+ */
736
+ _delete(rlKey, options = {}) {
737
+ throw new Error("You have to implement the method '_delete'!");
738
+ }
739
+ /**
740
+ * Have to be implemented
741
+ * Resolve with object used for {@link _getRateLimiterRes} to generate {@link RateLimiterRes}
742
+ *
743
+ * @param {string} rlKey
744
+ * @param {number} points
745
+ * @param {number} msDuration
746
+ * @param {boolean} forceExpire
747
+ * @param {Object} options
748
+ * @abstract
749
+ *
750
+ * @return Promise<Object>
751
+ */
752
+ _upsert(rlKey, points, msDuration, forceExpire = false, options = {}) {
753
+ throw new Error("You have to implement the method '_upsert'!");
754
+ }
755
+ };
756
+ }
757
+ });
758
+
759
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRedis.js
760
+ var require_RateLimiterRedis = __commonJS({
761
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRedis.js"(exports, module) {
762
+ "use strict";
763
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
764
+ var RateLimiterRes2 = require_RateLimiterRes();
765
+ var incrTtlLuaScript = `redis.call('set', KEYS[1], 0, 'EX', ARGV[2], 'NX') local consumed = redis.call('incrby', KEYS[1], ARGV[1]) local ttl = redis.call('pttl', KEYS[1]) if ttl == -1 then redis.call('expire', KEYS[1], ARGV[2]) ttl = 1000 * ARGV[2] end return {consumed, ttl} `;
766
+ var RateLimiterRedis = class extends RateLimiterStoreAbstract {
767
+ /**
768
+ *
769
+ * @param {Object} opts
770
+ * Defaults {
771
+ * ... see other in RateLimiterStoreAbstract
772
+ *
773
+ * redis: RedisClient
774
+ * rejectIfRedisNotReady: boolean = false - reject / invoke insuranceLimiter immediately when redis connection is not "ready"
775
+ * }
776
+ */
777
+ constructor(opts) {
778
+ super(opts);
779
+ this.client = opts.storeClient;
780
+ this._rejectIfRedisNotReady = !!opts.rejectIfRedisNotReady;
781
+ this._incrTtlLuaScript = opts.customIncrTtlLuaScript || incrTtlLuaScript;
782
+ this.useRedisPackage = opts.useRedisPackage || this.client.constructor.name === "Commander" || false;
783
+ this.useRedis3AndLowerPackage = opts.useRedis3AndLowerPackage;
784
+ if (typeof this.client.defineCommand === "function") {
785
+ this.client.defineCommand("rlflxIncr", {
786
+ numberOfKeys: 1,
787
+ lua: this._incrTtlLuaScript
788
+ });
789
+ }
790
+ }
791
+ /**
792
+ * Prevent actual redis call if redis connection is not ready
793
+ * Because of different connection state checks for ioredis and node-redis, only this clients would be actually checked.
794
+ * For any other clients all the requests would be passed directly to redis client
795
+ * @param {String} rlKey
796
+ * @param {Boolean} isReadonly
797
+ * @return {boolean}
798
+ * @private
799
+ */
800
+ _isRedisReady(rlKey, isReadonly) {
801
+ if (!this._rejectIfRedisNotReady) {
802
+ return true;
803
+ }
804
+ if (this.client.status) {
805
+ return this.client.status === "ready";
806
+ }
807
+ if (typeof this.client.isReady === "function") {
808
+ return this.client.isReady();
809
+ }
810
+ if (typeof this.client.isReady === "boolean") {
811
+ return this.client.isReady === true;
812
+ }
813
+ if (this.client._slots && typeof this.client._slots.getClient === "function") {
814
+ if (typeof this.client.isOpen === "boolean" && this.client.isOpen !== true) {
815
+ return false;
816
+ }
817
+ try {
818
+ const slotClient = this.client._slots.getClient(rlKey, isReadonly);
819
+ return slotClient && slotClient.isReady === true;
820
+ } catch (error) {
821
+ return false;
822
+ }
823
+ }
824
+ return true;
825
+ }
826
+ _getRateLimiterRes(rlKey, changedPoints, result) {
827
+ let [consumed, resTtlMs] = result;
828
+ if (Array.isArray(consumed)) {
829
+ [, consumed] = consumed;
830
+ [, resTtlMs] = resTtlMs;
831
+ }
832
+ const res = new RateLimiterRes2();
833
+ res.consumedPoints = parseInt(consumed);
834
+ res.isFirstInDuration = res.consumedPoints === changedPoints;
835
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
836
+ res.msBeforeNext = resTtlMs;
837
+ return res;
838
+ }
839
+ async _upsert(rlKey, points, msDuration, forceExpire = false) {
840
+ if (typeof points == "string") {
841
+ if (!RegExp("^[1-9][0-9]*$").test(points)) {
842
+ throw new Error("Consuming string different than integer values is not supported by this package");
843
+ }
844
+ } else if (!Number.isInteger(points)) {
845
+ throw new Error("Consuming decimal number of points is not supported by this package");
846
+ }
847
+ if (!this._isRedisReady(rlKey, false)) {
848
+ throw new Error("Redis connection is not ready");
849
+ }
850
+ const secDuration = Math.floor(msDuration / 1e3);
851
+ const multi = this.client.multi();
852
+ if (forceExpire) {
853
+ if (secDuration > 0) {
854
+ if (!this.useRedisPackage && !this.useRedis3AndLowerPackage) {
855
+ multi.set(rlKey, points, "EX", secDuration);
856
+ } else {
857
+ multi.set(rlKey, points, { EX: secDuration });
858
+ }
859
+ } else {
860
+ multi.set(rlKey, points);
861
+ }
862
+ if (!this.useRedisPackage && !this.useRedis3AndLowerPackage) {
863
+ return multi.pttl(rlKey).exec(true);
864
+ }
865
+ return multi.pTTL(rlKey).exec(true);
866
+ }
867
+ if (secDuration > 0) {
868
+ if (!this.useRedisPackage && !this.useRedis3AndLowerPackage) {
869
+ return this.client.rlflxIncr(
870
+ [rlKey].concat([String(points), String(secDuration), String(this.points), String(this.duration)])
871
+ );
872
+ }
873
+ if (this.useRedis3AndLowerPackage) {
874
+ return new Promise((resolve, reject) => {
875
+ const incrCallback = function(err, result) {
876
+ if (err) {
877
+ return reject(err);
878
+ }
879
+ return resolve(result);
880
+ };
881
+ if (typeof this.client.rlflxIncr === "function") {
882
+ this.client.rlflxIncr(rlKey, points, secDuration, this.points, this.duration, incrCallback);
883
+ } else {
884
+ this.client.eval(this._incrTtlLuaScript, 1, rlKey, points, secDuration, this.points, this.duration, incrCallback);
885
+ }
886
+ });
887
+ } else {
888
+ return this.client.eval(this._incrTtlLuaScript, {
889
+ keys: [rlKey],
890
+ arguments: [String(points), String(secDuration), String(this.points), String(this.duration)]
891
+ });
892
+ }
893
+ } else {
894
+ if (!this.useRedisPackage && !this.useRedis3AndLowerPackage) {
895
+ return multi.incrby(rlKey, points).pttl(rlKey).exec(true);
896
+ }
897
+ return multi.incrBy(rlKey, points).pTTL(rlKey).exec(true);
898
+ }
899
+ }
900
+ async _get(rlKey) {
901
+ if (!this._isRedisReady(rlKey, true)) {
902
+ throw new Error("Redis connection is not ready");
903
+ }
904
+ if (!this.useRedisPackage && !this.useRedis3AndLowerPackage) {
905
+ return this.client.multi().get(rlKey).pttl(rlKey).exec().then((result) => {
906
+ const [[, points]] = result;
907
+ if (points === null) return null;
908
+ return result;
909
+ });
910
+ }
911
+ return this.client.multi().get(rlKey).pTTL(rlKey).exec(true).then((result) => {
912
+ const [points] = result;
913
+ if (points === null) return null;
914
+ return result;
915
+ });
916
+ }
917
+ _delete(rlKey) {
918
+ return this.client.del(rlKey).then((result) => result > 0);
919
+ }
920
+ };
921
+ module.exports = RateLimiterRedis;
922
+ }
923
+ });
924
+
925
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRedisNonAtomic.js
926
+ var require_RateLimiterRedisNonAtomic = __commonJS({
927
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterRedisNonAtomic.js"(exports, module) {
928
+ "use strict";
929
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
930
+ var RateLimiterRes2 = require_RateLimiterRes();
931
+ var RateLimiterRedisNonAtomic = class extends RateLimiterStoreAbstract {
932
+ constructor(opts) {
933
+ super(opts);
934
+ this.client = opts.storeClient;
935
+ this._rejectIfRedisNotReady = !!opts.rejectIfRedisNotReady;
936
+ this.useRedisPackage = opts.useRedisPackage || this.client.constructor.name === "Commander" || false;
937
+ }
938
+ _isRedisReady(rlKey, isReadonly) {
939
+ if (!this._rejectIfRedisNotReady) {
940
+ return true;
941
+ }
942
+ if (this.client.status) {
943
+ return this.client.status === "ready";
944
+ }
945
+ if (typeof this.client.isReady === "function") {
946
+ return this.client.isReady();
947
+ }
948
+ if (typeof this.client.isReady === "boolean") {
949
+ return this.client.isReady === true;
950
+ }
951
+ if (this.client._slots && typeof this.client._slots.getClient === "function") {
952
+ if (typeof this.client.isOpen === "boolean" && this.client.isOpen !== true) {
953
+ return false;
954
+ }
955
+ try {
956
+ const slotClient = this.client._slots.getClient(rlKey, isReadonly);
957
+ return slotClient && slotClient.isReady === true;
958
+ } catch (error) {
959
+ return false;
960
+ }
961
+ }
962
+ return true;
963
+ }
964
+ _getRateLimiterRes(rlKey, changedPoints, result) {
965
+ let [consumed, resTtlMs] = result;
966
+ if (Array.isArray(consumed)) {
967
+ [, consumed] = consumed;
968
+ [, resTtlMs] = resTtlMs;
969
+ }
970
+ const res = new RateLimiterRes2();
971
+ res.consumedPoints = parseInt(consumed);
972
+ res.isFirstInDuration = res.consumedPoints === changedPoints;
973
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
974
+ res.msBeforeNext = resTtlMs;
975
+ return res;
976
+ }
977
+ _parseStoreResult(result) {
978
+ let points;
979
+ let ttlMs;
980
+ if (Array.isArray(result[0])) {
981
+ [, points] = result[0];
982
+ [, ttlMs] = result[1];
983
+ } else {
984
+ [points, ttlMs] = result;
985
+ }
986
+ return {
987
+ points: parseInt(points, 10),
988
+ ttlMs
989
+ };
990
+ }
991
+ _execMulti(multi) {
992
+ return multi.exec();
993
+ }
994
+ _setKey(rlKey, points, secDuration) {
995
+ const multi = this.client.multi();
996
+ if (secDuration > 0) {
997
+ if (!this.useRedisPackage) {
998
+ multi.set(rlKey, points, "EX", secDuration);
999
+ } else {
1000
+ multi.set(rlKey, points, { EX: secDuration });
1001
+ }
1002
+ } else {
1003
+ multi.set(rlKey, points);
1004
+ }
1005
+ return this._execMulti(multi);
1006
+ }
1007
+ _setKeyWithTtlMs(rlKey, points, ttlMs) {
1008
+ const multi = this.client.multi();
1009
+ multi.set(rlKey, points);
1010
+ if (ttlMs > 0) {
1011
+ if (!this.useRedisPackage) {
1012
+ multi.pexpire(rlKey, ttlMs);
1013
+ } else {
1014
+ multi.pExpire(rlKey, ttlMs);
1015
+ }
1016
+ }
1017
+ return this._execMulti(multi);
1018
+ }
1019
+ async _upsert(rlKey, points, msDuration, forceExpire = false) {
1020
+ if (typeof points == "string") {
1021
+ if (!RegExp("^[1-9][0-9]*$").test(points)) {
1022
+ throw new Error("Consuming string different than integer values is not supported by this package");
1023
+ }
1024
+ } else if (!Number.isInteger(points)) {
1025
+ throw new Error("Consuming decimal number of points is not supported by this package");
1026
+ }
1027
+ if (!this._isRedisReady(rlKey, false)) {
1028
+ throw new Error("Redis connection is not ready");
1029
+ }
1030
+ const parsedPoints = typeof points === "string" ? parseInt(points, 10) : points;
1031
+ const secDuration = Math.floor(msDuration / 1e3);
1032
+ if (forceExpire) {
1033
+ await this._setKey(rlKey, parsedPoints, secDuration);
1034
+ return [parsedPoints, secDuration > 0 ? secDuration * 1e3 : -1];
1035
+ }
1036
+ const currentResult = await this._get(rlKey);
1037
+ const hasCurrent = currentResult !== null;
1038
+ const current = hasCurrent ? this._parseStoreResult(currentResult) : { points: 0, ttlMs: -1 };
1039
+ const newPoints = current.points + parsedPoints;
1040
+ if (secDuration > 0) {
1041
+ if (!hasCurrent) {
1042
+ await this._setKey(rlKey, newPoints, secDuration);
1043
+ return [newPoints, secDuration * 1e3];
1044
+ }
1045
+ if (current.ttlMs <= 0) {
1046
+ await this._setKey(rlKey, newPoints, secDuration);
1047
+ return [newPoints, secDuration * 1e3];
1048
+ }
1049
+ await this._setKeyWithTtlMs(rlKey, newPoints, current.ttlMs);
1050
+ return [newPoints, current.ttlMs];
1051
+ }
1052
+ await this._setKey(rlKey, newPoints, 0);
1053
+ return [newPoints, -1];
1054
+ }
1055
+ async _get(rlKey) {
1056
+ if (!this._isRedisReady(rlKey, true)) {
1057
+ throw new Error("Redis connection is not ready");
1058
+ }
1059
+ const multi = this.client.multi().get(rlKey);
1060
+ if (!this.useRedisPackage) {
1061
+ multi.pttl(rlKey);
1062
+ } else {
1063
+ multi.pTTL(rlKey);
1064
+ }
1065
+ return this._execMulti(multi).then((result) => {
1066
+ if (Array.isArray(result[0])) {
1067
+ const [, points2] = result[0];
1068
+ if (points2 === null) return null;
1069
+ return result;
1070
+ }
1071
+ const [points] = result;
1072
+ if (points === null) return null;
1073
+ return result;
1074
+ });
1075
+ }
1076
+ _delete(rlKey) {
1077
+ return this.client.del(rlKey).then((result) => result > 0);
1078
+ }
1079
+ };
1080
+ module.exports = RateLimiterRedisNonAtomic;
1081
+ }
1082
+ });
1083
+
1084
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMongo.js
1085
+ var require_RateLimiterMongo = __commonJS({
1086
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMongo.js"(exports, module) {
1087
+ "use strict";
1088
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
1089
+ var RateLimiterRes2 = require_RateLimiterRes();
1090
+ var RateLimiterMongo = class _RateLimiterMongo extends RateLimiterStoreAbstract {
1091
+ /**
1092
+ *
1093
+ * @param {Object} opts
1094
+ * Defaults {
1095
+ * indexKeyPrefix: {attr1: 1, attr2: 1}
1096
+ * ... see other in RateLimiterStoreAbstract
1097
+ *
1098
+ * mongo: MongoClient
1099
+ * }
1100
+ */
1101
+ constructor(opts) {
1102
+ super(opts);
1103
+ this.dbName = opts.dbName;
1104
+ this.tableName = opts.tableName;
1105
+ this.indexKeyPrefix = opts.indexKeyPrefix;
1106
+ this.disableIndexesCreation = opts.disableIndexesCreation;
1107
+ if (opts.mongo) {
1108
+ this.client = opts.mongo;
1109
+ } else {
1110
+ this.client = opts.storeClient;
1111
+ }
1112
+ if (typeof this.client.then === "function") {
1113
+ this.client.then((conn) => {
1114
+ this.client = conn;
1115
+ this._initCollection();
1116
+ });
1117
+ } else {
1118
+ this._initCollection();
1119
+ }
1120
+ }
1121
+ get dbName() {
1122
+ return this._dbName;
1123
+ }
1124
+ set dbName(value) {
1125
+ this._dbName = typeof value === "undefined" ? _RateLimiterMongo.getDbName() : value;
1126
+ }
1127
+ static getDbName() {
1128
+ return "node-rate-limiter-flexible";
1129
+ }
1130
+ get tableName() {
1131
+ return this._tableName;
1132
+ }
1133
+ set tableName(value) {
1134
+ this._tableName = typeof value === "undefined" ? this.keyPrefix : value;
1135
+ }
1136
+ get client() {
1137
+ return this._client;
1138
+ }
1139
+ set client(value) {
1140
+ if (typeof value === "undefined") {
1141
+ throw new Error("mongo is not set");
1142
+ }
1143
+ this._client = value;
1144
+ }
1145
+ get indexKeyPrefix() {
1146
+ return this._indexKeyPrefix;
1147
+ }
1148
+ set indexKeyPrefix(obj) {
1149
+ this._indexKeyPrefix = obj || {};
1150
+ }
1151
+ get disableIndexesCreation() {
1152
+ return this._disableIndexesCreation;
1153
+ }
1154
+ set disableIndexesCreation(value) {
1155
+ this._disableIndexesCreation = !!value;
1156
+ }
1157
+ async createIndexes() {
1158
+ const db = typeof this.client.db === "function" ? this.client.db(this.dbName) : this.client;
1159
+ const collection = db.collection(this.tableName);
1160
+ await collection.createIndex({ expire: -1 }, { expireAfterSeconds: 0 });
1161
+ await collection.createIndex(Object.assign({}, this.indexKeyPrefix, { key: 1 }), { unique: true });
1162
+ }
1163
+ _initCollection() {
1164
+ const db = typeof this.client.db === "function" ? this.client.db(this.dbName) : this.client;
1165
+ const collection = db.collection(this.tableName);
1166
+ if (!this.disableIndexesCreation) {
1167
+ this.createIndexes().catch((err) => {
1168
+ console.error(`Cannot create indexes for mongo collection ${this.tableName}`, err);
1169
+ });
1170
+ }
1171
+ this._collection = collection;
1172
+ }
1173
+ _getRateLimiterRes(rlKey, changedPoints, result) {
1174
+ const res = new RateLimiterRes2();
1175
+ let doc;
1176
+ if (typeof result.value === "undefined") {
1177
+ doc = result;
1178
+ } else {
1179
+ doc = result.value;
1180
+ }
1181
+ res.isFirstInDuration = doc.points === changedPoints;
1182
+ res.consumedPoints = doc.points;
1183
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
1184
+ res.msBeforeNext = doc.expire !== null ? Math.max(new Date(doc.expire).getTime() - Date.now(), 0) : -1;
1185
+ return res;
1186
+ }
1187
+ _upsert(key, points, msDuration, forceExpire = false, options = {}) {
1188
+ if (!this._collection) {
1189
+ return Promise.reject(Error("Mongo connection is not established"));
1190
+ }
1191
+ const docAttrs = options.attrs || {};
1192
+ let where;
1193
+ let upsertData;
1194
+ if (forceExpire) {
1195
+ where = { key };
1196
+ where = Object.assign(where, docAttrs);
1197
+ upsertData = {
1198
+ $set: {
1199
+ key,
1200
+ points,
1201
+ expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null
1202
+ }
1203
+ };
1204
+ upsertData.$set = Object.assign(upsertData.$set, docAttrs);
1205
+ } else {
1206
+ where = {
1207
+ $or: [
1208
+ { expire: { $gt: /* @__PURE__ */ new Date() } },
1209
+ { expire: { $eq: null } }
1210
+ ],
1211
+ key
1212
+ };
1213
+ where = Object.assign(where, docAttrs);
1214
+ upsertData = {
1215
+ $setOnInsert: {
1216
+ key,
1217
+ expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null
1218
+ },
1219
+ $inc: { points }
1220
+ };
1221
+ upsertData.$setOnInsert = Object.assign(upsertData.$setOnInsert, docAttrs);
1222
+ }
1223
+ const upsertOptions = {
1224
+ upsert: true,
1225
+ returnDocument: "after"
1226
+ };
1227
+ return new Promise((resolve, reject) => {
1228
+ this._collection.findOneAndUpdate(
1229
+ where,
1230
+ upsertData,
1231
+ upsertOptions
1232
+ ).then((res) => {
1233
+ resolve(res);
1234
+ }).catch((errUpsert) => {
1235
+ if (errUpsert && errUpsert.code === 11e3) {
1236
+ const replaceWhere = Object.assign({
1237
+ // try to replace OLD limit doc
1238
+ $or: [
1239
+ { expire: { $lte: /* @__PURE__ */ new Date() } },
1240
+ { expire: { $eq: null } }
1241
+ ],
1242
+ key
1243
+ }, docAttrs);
1244
+ const replaceTo = {
1245
+ $set: Object.assign({
1246
+ key,
1247
+ points,
1248
+ expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null
1249
+ }, docAttrs)
1250
+ };
1251
+ this._collection.findOneAndUpdate(
1252
+ replaceWhere,
1253
+ replaceTo,
1254
+ upsertOptions
1255
+ ).then((res) => {
1256
+ resolve(res);
1257
+ }).catch((errReplace) => {
1258
+ if (errReplace && errReplace.code === 11e3) {
1259
+ this._upsert(key, points, msDuration, forceExpire).then((res) => resolve(res)).catch((err) => reject(err));
1260
+ } else {
1261
+ reject(errReplace);
1262
+ }
1263
+ });
1264
+ } else {
1265
+ reject(errUpsert);
1266
+ }
1267
+ });
1268
+ });
1269
+ }
1270
+ _get(rlKey, options = {}) {
1271
+ if (!this._collection) {
1272
+ return Promise.reject(Error("Mongo connection is not established"));
1273
+ }
1274
+ const docAttrs = options.attrs || {};
1275
+ const where = Object.assign({
1276
+ key: rlKey,
1277
+ $or: [
1278
+ { expire: { $gt: /* @__PURE__ */ new Date() } },
1279
+ { expire: { $eq: null } }
1280
+ ]
1281
+ }, docAttrs);
1282
+ return this._collection.findOne(where);
1283
+ }
1284
+ _delete(rlKey, options = {}) {
1285
+ if (!this._collection) {
1286
+ return Promise.reject(Error("Mongo connection is not established"));
1287
+ }
1288
+ const docAttrs = options.attrs || {};
1289
+ const where = Object.assign({ key: rlKey }, docAttrs);
1290
+ return this._collection.deleteOne(where).then((res) => res.deletedCount > 0);
1291
+ }
1292
+ };
1293
+ module.exports = RateLimiterMongo;
1294
+ }
1295
+ });
1296
+
1297
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMySQL.js
1298
+ var require_RateLimiterMySQL = __commonJS({
1299
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMySQL.js"(exports, module) {
1300
+ "use strict";
1301
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
1302
+ var RateLimiterRes2 = require_RateLimiterRes();
1303
+ var RateLimiterMySQL = class extends RateLimiterStoreAbstract {
1304
+ /**
1305
+ * @callback callback
1306
+ * @param {Object} err
1307
+ *
1308
+ * @param {Object} opts
1309
+ * @param {callback} cb
1310
+ * Defaults {
1311
+ * ... see other in RateLimiterStoreAbstract
1312
+ *
1313
+ * storeClient: anySqlClient,
1314
+ * storeType: 'knex', // required only for Knex instance
1315
+ * dbName: 'string',
1316
+ * tableName: 'string',
1317
+ * }
1318
+ */
1319
+ constructor(opts, cb = null) {
1320
+ super(opts);
1321
+ this.client = opts.storeClient;
1322
+ this.clientType = opts.storeType;
1323
+ this.dbName = opts.dbName;
1324
+ this.tableName = opts.tableName;
1325
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout;
1326
+ this.tableCreated = opts.tableCreated;
1327
+ if (!this.tableCreated) {
1328
+ this._createDbAndTable().then(() => {
1329
+ this.tableCreated = true;
1330
+ if (this.clearExpiredByTimeout) {
1331
+ this._clearExpiredHourAgo();
1332
+ }
1333
+ if (typeof cb === "function") {
1334
+ cb();
1335
+ }
1336
+ }).catch((err) => {
1337
+ if (typeof cb === "function") {
1338
+ cb(err);
1339
+ } else {
1340
+ throw err;
1341
+ }
1342
+ });
1343
+ } else {
1344
+ if (this.clearExpiredByTimeout) {
1345
+ this._clearExpiredHourAgo();
1346
+ }
1347
+ if (typeof cb === "function") {
1348
+ cb();
1349
+ }
1350
+ }
1351
+ }
1352
+ clearExpired(expire) {
1353
+ return new Promise((resolve) => {
1354
+ this._getConnection().then((conn) => {
1355
+ conn.query(`DELETE FROM ??.?? WHERE expire < ?`, [this.dbName, this.tableName, expire], () => {
1356
+ this._releaseConnection(conn);
1357
+ resolve();
1358
+ });
1359
+ }).catch(() => {
1360
+ resolve();
1361
+ });
1362
+ });
1363
+ }
1364
+ _clearExpiredHourAgo() {
1365
+ if (this._clearExpiredTimeoutId) {
1366
+ clearTimeout(this._clearExpiredTimeoutId);
1367
+ }
1368
+ this._clearExpiredTimeoutId = setTimeout(() => {
1369
+ this.clearExpired(Date.now() - 36e5).then(() => {
1370
+ this._clearExpiredHourAgo();
1371
+ });
1372
+ }, 3e5);
1373
+ this._clearExpiredTimeoutId.unref();
1374
+ }
1375
+ /**
1376
+ *
1377
+ * @return Promise<any>
1378
+ * @private
1379
+ */
1380
+ _getConnection() {
1381
+ switch (this.clientType) {
1382
+ case "pool":
1383
+ return new Promise((resolve, reject) => {
1384
+ this.client.getConnection((errConn, conn) => {
1385
+ if (errConn) {
1386
+ return reject(errConn);
1387
+ }
1388
+ resolve(conn);
1389
+ });
1390
+ });
1391
+ case "sequelize":
1392
+ return this._getSequelizeConnectionManager().getConnection();
1393
+ case "knex":
1394
+ return this.client.client.acquireConnection();
1395
+ default:
1396
+ return Promise.resolve(this.client);
1397
+ }
1398
+ }
1399
+ _releaseConnection(conn) {
1400
+ switch (this.clientType) {
1401
+ case "pool":
1402
+ return conn.release();
1403
+ case "sequelize":
1404
+ return this._getSequelizeConnectionManager().releaseConnection(conn);
1405
+ case "knex":
1406
+ return this.client.client.releaseConnection(conn);
1407
+ default:
1408
+ return true;
1409
+ }
1410
+ }
1411
+ _getSequelizeConnectionManager() {
1412
+ let connectionManager;
1413
+ let originalError;
1414
+ try {
1415
+ connectionManager = this.client.connectionManager;
1416
+ } catch (err) {
1417
+ originalError = err;
1418
+ }
1419
+ if (connectionManager) {
1420
+ return connectionManager;
1421
+ }
1422
+ if (this.client.dialect && this.client.dialect.connectionManager) {
1423
+ return this.client.dialect.connectionManager;
1424
+ }
1425
+ if (originalError) {
1426
+ throw originalError;
1427
+ }
1428
+ throw new Error("Sequelize connection manager is not available");
1429
+ }
1430
+ /**
1431
+ *
1432
+ * @returns {Promise<any>}
1433
+ * @private
1434
+ */
1435
+ _createDbAndTable() {
1436
+ return new Promise((resolve, reject) => {
1437
+ this._getConnection().then((conn) => {
1438
+ conn.query(`CREATE DATABASE IF NOT EXISTS \`${this.dbName}\`;`, (errDb) => {
1439
+ if (errDb) {
1440
+ this._releaseConnection(conn);
1441
+ return reject(errDb);
1442
+ }
1443
+ conn.query(this._getCreateTableStmt(), (err) => {
1444
+ if (err) {
1445
+ this._releaseConnection(conn);
1446
+ return reject(err);
1447
+ }
1448
+ this._releaseConnection(conn);
1449
+ resolve();
1450
+ });
1451
+ });
1452
+ }).catch((err) => {
1453
+ reject(err);
1454
+ });
1455
+ });
1456
+ }
1457
+ _getCreateTableStmt() {
1458
+ return `CREATE TABLE IF NOT EXISTS \`${this.dbName}\`.\`${this.tableName}\` (\`key\` VARCHAR(255) CHARACTER SET utf8 NOT NULL,\`points\` INT(9) NOT NULL default 0,\`expire\` BIGINT UNSIGNED,PRIMARY KEY (\`key\`)) ENGINE = INNODB;`;
1459
+ }
1460
+ get clientType() {
1461
+ return this._clientType;
1462
+ }
1463
+ set clientType(value) {
1464
+ if (typeof value === "undefined") {
1465
+ if (this.client.constructor.name === "Connection") {
1466
+ value = "connection";
1467
+ } else if (this.client.constructor.name === "Pool") {
1468
+ value = "pool";
1469
+ } else if (this.client.constructor.name === "Sequelize") {
1470
+ value = "sequelize";
1471
+ } else {
1472
+ throw new Error("storeType is not defined");
1473
+ }
1474
+ }
1475
+ this._clientType = value.toLowerCase();
1476
+ }
1477
+ get dbName() {
1478
+ return this._dbName;
1479
+ }
1480
+ set dbName(value) {
1481
+ this._dbName = typeof value === "undefined" ? "rtlmtrflx" : value;
1482
+ }
1483
+ get tableName() {
1484
+ return this._tableName;
1485
+ }
1486
+ set tableName(value) {
1487
+ this._tableName = typeof value === "undefined" ? this.keyPrefix : value;
1488
+ }
1489
+ get tableCreated() {
1490
+ return this._tableCreated;
1491
+ }
1492
+ set tableCreated(value) {
1493
+ this._tableCreated = typeof value === "undefined" ? false : !!value;
1494
+ }
1495
+ get clearExpiredByTimeout() {
1496
+ return this._clearExpiredByTimeout;
1497
+ }
1498
+ set clearExpiredByTimeout(value) {
1499
+ this._clearExpiredByTimeout = typeof value === "undefined" ? true : Boolean(value);
1500
+ }
1501
+ _getRateLimiterRes(rlKey, changedPoints, result) {
1502
+ const res = new RateLimiterRes2();
1503
+ const [row] = result;
1504
+ res.isFirstInDuration = changedPoints === row.points;
1505
+ res.consumedPoints = res.isFirstInDuration ? changedPoints : row.points;
1506
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
1507
+ res.msBeforeNext = row.expire ? Math.max(row.expire - Date.now(), 0) : -1;
1508
+ return res;
1509
+ }
1510
+ _upsertTransaction(conn, key, points, msDuration, forceExpire) {
1511
+ return new Promise((resolve, reject) => {
1512
+ conn.query("BEGIN", (errBegin) => {
1513
+ if (errBegin) {
1514
+ conn.rollback();
1515
+ return reject(errBegin);
1516
+ }
1517
+ const dateNow = Date.now();
1518
+ const newExpire = msDuration > 0 ? dateNow + msDuration : null;
1519
+ let q;
1520
+ let values;
1521
+ if (forceExpire) {
1522
+ q = `INSERT INTO ??.?? VALUES (?, ?, ?)
1523
+ ON DUPLICATE KEY UPDATE
1524
+ points = ?,
1525
+ expire = ?;`;
1526
+ values = [
1527
+ this.dbName,
1528
+ this.tableName,
1529
+ key,
1530
+ points,
1531
+ newExpire,
1532
+ points,
1533
+ newExpire
1534
+ ];
1535
+ } else {
1536
+ q = `INSERT INTO ??.?? VALUES (?, ?, ?)
1537
+ ON DUPLICATE KEY UPDATE
1538
+ points = IF(expire <= ?, ?, points + (?)),
1539
+ expire = IF(expire <= ?, ?, expire);`;
1540
+ values = [
1541
+ this.dbName,
1542
+ this.tableName,
1543
+ key,
1544
+ points,
1545
+ newExpire,
1546
+ dateNow,
1547
+ points,
1548
+ points,
1549
+ dateNow,
1550
+ newExpire
1551
+ ];
1552
+ }
1553
+ conn.query(q, values, (errUpsert) => {
1554
+ if (errUpsert) {
1555
+ conn.rollback();
1556
+ return reject(errUpsert);
1557
+ }
1558
+ conn.query("SELECT points, expire FROM ??.?? WHERE `key` = ?;", [this.dbName, this.tableName, key], (errSelect, res) => {
1559
+ if (errSelect) {
1560
+ conn.rollback();
1561
+ return reject(errSelect);
1562
+ }
1563
+ conn.query("COMMIT", (err) => {
1564
+ if (err) {
1565
+ conn.rollback();
1566
+ return reject(err);
1567
+ }
1568
+ resolve(res);
1569
+ });
1570
+ });
1571
+ });
1572
+ });
1573
+ });
1574
+ }
1575
+ _upsert(key, points, msDuration, forceExpire = false) {
1576
+ if (!this.tableCreated) {
1577
+ return Promise.reject(Error("Table is not created yet"));
1578
+ }
1579
+ return new Promise((resolve, reject) => {
1580
+ this._getConnection().then((conn) => {
1581
+ this._upsertTransaction(conn, key, points, msDuration, forceExpire).then((res) => {
1582
+ resolve(res);
1583
+ this._releaseConnection(conn);
1584
+ }).catch((err) => {
1585
+ reject(err);
1586
+ this._releaseConnection(conn);
1587
+ });
1588
+ }).catch((err) => {
1589
+ reject(err);
1590
+ });
1591
+ });
1592
+ }
1593
+ _get(rlKey) {
1594
+ if (!this.tableCreated) {
1595
+ return Promise.reject(Error("Table is not created yet"));
1596
+ }
1597
+ return new Promise((resolve, reject) => {
1598
+ this._getConnection().then((conn) => {
1599
+ conn.query(
1600
+ "SELECT points, expire FROM ??.?? WHERE `key` = ? AND (`expire` > ? OR `expire` IS NULL)",
1601
+ [this.dbName, this.tableName, rlKey, Date.now()],
1602
+ (err, res) => {
1603
+ if (err) {
1604
+ reject(err);
1605
+ } else if (res.length === 0) {
1606
+ resolve(null);
1607
+ } else {
1608
+ resolve(res);
1609
+ }
1610
+ this._releaseConnection(conn);
1611
+ }
1612
+ // eslint-disable-line
1613
+ );
1614
+ }).catch((err) => {
1615
+ reject(err);
1616
+ });
1617
+ });
1618
+ }
1619
+ _delete(rlKey) {
1620
+ if (!this.tableCreated) {
1621
+ return Promise.reject(Error("Table is not created yet"));
1622
+ }
1623
+ return new Promise((resolve, reject) => {
1624
+ this._getConnection().then((conn) => {
1625
+ conn.query(
1626
+ "DELETE FROM ??.?? WHERE `key` = ?",
1627
+ [this.dbName, this.tableName, rlKey],
1628
+ (err, res) => {
1629
+ if (err) {
1630
+ reject(err);
1631
+ } else {
1632
+ resolve(res.affectedRows > 0);
1633
+ }
1634
+ this._releaseConnection(conn);
1635
+ }
1636
+ // eslint-disable-line
1637
+ );
1638
+ }).catch((err) => {
1639
+ reject(err);
1640
+ });
1641
+ });
1642
+ }
1643
+ };
1644
+ module.exports = RateLimiterMySQL;
1645
+ }
1646
+ });
1647
+
1648
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterPostgres.js
1649
+ var require_RateLimiterPostgres = __commonJS({
1650
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterPostgres.js"(exports, module) {
1651
+ "use strict";
1652
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
1653
+ var RateLimiterRes2 = require_RateLimiterRes();
1654
+ var RateLimiterPostgres2 = class extends RateLimiterStoreAbstract {
1655
+ /**
1656
+ * @callback callback
1657
+ * @param {Object} err
1658
+ *
1659
+ * @param {Object} opts
1660
+ * @param {callback} cb
1661
+ * Defaults {
1662
+ * ... see other in RateLimiterStoreAbstract
1663
+ *
1664
+ * storeClient: postgresClient,
1665
+ * storeType: 'knex', // required only for Knex instance
1666
+ * tableName: 'string',
1667
+ * schemaName: 'string', // optional
1668
+ * }
1669
+ */
1670
+ constructor(opts, cb = null) {
1671
+ super(opts);
1672
+ this.client = opts.storeClient;
1673
+ this.clientType = opts.storeType;
1674
+ this.tableName = opts.tableName;
1675
+ this.schemaName = opts.schemaName;
1676
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout;
1677
+ this.tableCreated = opts.tableCreated;
1678
+ if (!this.tableCreated) {
1679
+ this._createTable().then(() => {
1680
+ this.tableCreated = true;
1681
+ if (this.clearExpiredByTimeout) {
1682
+ this._clearExpiredHourAgo();
1683
+ }
1684
+ if (typeof cb === "function") {
1685
+ cb();
1686
+ }
1687
+ }).catch((err) => {
1688
+ if (typeof cb === "function") {
1689
+ cb(err);
1690
+ } else {
1691
+ throw err;
1692
+ }
1693
+ });
1694
+ } else {
1695
+ if (this.clearExpiredByTimeout) {
1696
+ this._clearExpiredHourAgo();
1697
+ }
1698
+ if (typeof cb === "function") {
1699
+ cb();
1700
+ }
1701
+ }
1702
+ }
1703
+ _getTableIdentifier() {
1704
+ return this.schemaName ? `"${this.schemaName}"."${this.tableName}"` : `"${this.tableName}"`;
1705
+ }
1706
+ clearExpired(expire) {
1707
+ return new Promise((resolve) => {
1708
+ const q = {
1709
+ name: "rlflx-clear-expired",
1710
+ text: `DELETE FROM ${this._getTableIdentifier()} WHERE expire < $1`,
1711
+ values: [expire]
1712
+ };
1713
+ this._query(q).then(() => {
1714
+ resolve();
1715
+ }).catch(() => {
1716
+ resolve();
1717
+ });
1718
+ });
1719
+ }
1720
+ /**
1721
+ * Delete all rows expired 1 hour ago once per 5 minutes
1722
+ *
1723
+ * @private
1724
+ */
1725
+ _clearExpiredHourAgo() {
1726
+ if (this._clearExpiredTimeoutId) {
1727
+ clearTimeout(this._clearExpiredTimeoutId);
1728
+ }
1729
+ this._clearExpiredTimeoutId = setTimeout(() => {
1730
+ this.clearExpired(Date.now() - 36e5).then(() => {
1731
+ this._clearExpiredHourAgo();
1732
+ });
1733
+ }, 3e5);
1734
+ this._clearExpiredTimeoutId.unref();
1735
+ }
1736
+ /**
1737
+ *
1738
+ * @return Promise<any>
1739
+ * @private
1740
+ */
1741
+ _getConnection() {
1742
+ switch (this.clientType) {
1743
+ case "pool":
1744
+ return Promise.resolve(this.client);
1745
+ case "sequelize":
1746
+ return this._getSequelizeConnectionManager().getConnection();
1747
+ case "knex":
1748
+ return this.client.client.acquireConnection();
1749
+ case "typeorm":
1750
+ return Promise.resolve(this.client.driver.master);
1751
+ default:
1752
+ return Promise.resolve(this.client);
1753
+ }
1754
+ }
1755
+ _releaseConnection(conn) {
1756
+ switch (this.clientType) {
1757
+ case "pool":
1758
+ return true;
1759
+ case "sequelize":
1760
+ return this._getSequelizeConnectionManager().releaseConnection(conn);
1761
+ case "knex":
1762
+ return this.client.client.releaseConnection(conn);
1763
+ case "typeorm":
1764
+ return true;
1765
+ default:
1766
+ return true;
1767
+ }
1768
+ }
1769
+ _getSequelizeConnectionManager() {
1770
+ let connectionManager;
1771
+ let accessError;
1772
+ try {
1773
+ connectionManager = this.client.connectionManager;
1774
+ } catch (err) {
1775
+ accessError = err;
1776
+ }
1777
+ if (connectionManager) {
1778
+ return connectionManager;
1779
+ }
1780
+ if (this.client.dialect && this.client.dialect.connectionManager) {
1781
+ return this.client.dialect.connectionManager;
1782
+ }
1783
+ if (accessError) {
1784
+ throw accessError;
1785
+ }
1786
+ throw new Error("Sequelize connection manager is not available");
1787
+ }
1788
+ /**
1789
+ *
1790
+ * @returns {Promise<any>}
1791
+ * @private
1792
+ */
1793
+ _createTable() {
1794
+ return new Promise((resolve, reject) => {
1795
+ this._query({
1796
+ text: this._getCreateTableStmt()
1797
+ }).then(() => {
1798
+ resolve();
1799
+ }).catch((err) => {
1800
+ if (err.code === "23505") {
1801
+ resolve();
1802
+ } else {
1803
+ reject(err);
1804
+ }
1805
+ });
1806
+ });
1807
+ }
1808
+ _getCreateTableStmt() {
1809
+ return `CREATE TABLE IF NOT EXISTS ${this._getTableIdentifier()} (
1810
+ key varchar(255) PRIMARY KEY,
1811
+ points integer NOT NULL DEFAULT 0,
1812
+ expire bigint
1813
+ );`;
1814
+ }
1815
+ get clientType() {
1816
+ return this._clientType;
1817
+ }
1818
+ set clientType(value) {
1819
+ const constructorName = this.client.constructor.name;
1820
+ if (typeof value === "undefined") {
1821
+ if (constructorName === "Client") {
1822
+ value = "client";
1823
+ } else if (constructorName === "Pool" || constructorName === "BoundPool") {
1824
+ value = "pool";
1825
+ } else if (constructorName === "Sequelize") {
1826
+ value = "sequelize";
1827
+ } else {
1828
+ throw new Error("storeType is not defined");
1829
+ }
1830
+ }
1831
+ this._clientType = value.toLowerCase();
1832
+ }
1833
+ get tableName() {
1834
+ return this._tableName;
1835
+ }
1836
+ set tableName(value) {
1837
+ this._tableName = typeof value === "undefined" ? this.keyPrefix : value;
1838
+ }
1839
+ get schemaName() {
1840
+ return this._schemaName;
1841
+ }
1842
+ set schemaName(value) {
1843
+ this._schemaName = value;
1844
+ }
1845
+ get tableCreated() {
1846
+ return this._tableCreated;
1847
+ }
1848
+ set tableCreated(value) {
1849
+ this._tableCreated = typeof value === "undefined" ? false : !!value;
1850
+ }
1851
+ get clearExpiredByTimeout() {
1852
+ return this._clearExpiredByTimeout;
1853
+ }
1854
+ set clearExpiredByTimeout(value) {
1855
+ this._clearExpiredByTimeout = typeof value === "undefined" ? true : Boolean(value);
1856
+ }
1857
+ _getRateLimiterRes(rlKey, changedPoints, result) {
1858
+ const res = new RateLimiterRes2();
1859
+ const row = result.rows[0];
1860
+ res.isFirstInDuration = changedPoints === row.points;
1861
+ res.consumedPoints = res.isFirstInDuration ? changedPoints : row.points;
1862
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
1863
+ res.msBeforeNext = row.expire ? Math.max(row.expire - Date.now(), 0) : -1;
1864
+ return res;
1865
+ }
1866
+ _query(q) {
1867
+ const prefix = this.tableName.toLowerCase();
1868
+ const queryObj = { text: q.text, values: q.values };
1869
+ if (q.name) {
1870
+ queryObj.name = `${prefix}:${q.name}`;
1871
+ }
1872
+ return new Promise((resolve, reject) => {
1873
+ this._getConnection().then((conn) => {
1874
+ conn.query(queryObj).then((res) => {
1875
+ resolve(res);
1876
+ this._releaseConnection(conn);
1877
+ }).catch((err) => {
1878
+ reject(err);
1879
+ this._releaseConnection(conn);
1880
+ });
1881
+ }).catch((err) => {
1882
+ reject(err);
1883
+ });
1884
+ });
1885
+ }
1886
+ _upsert(key, points, msDuration, forceExpire = false) {
1887
+ if (!this.tableCreated) {
1888
+ return Promise.reject(Error("Table is not created yet"));
1889
+ }
1890
+ const newExpire = msDuration > 0 ? Date.now() + msDuration : null;
1891
+ const expireQ = forceExpire ? " $3 " : ` CASE
1892
+ WHEN ${this._getTableIdentifier()}.expire <= $4 THEN $3
1893
+ ELSE ${this._getTableIdentifier()}.expire
1894
+ END `;
1895
+ return this._query({
1896
+ name: forceExpire ? "rlflx-upsert-force" : "rlflx-upsert",
1897
+ text: `
1898
+ INSERT INTO ${this._getTableIdentifier()} VALUES ($1, $2, $3)
1899
+ ON CONFLICT(key) DO UPDATE SET
1900
+ points = CASE
1901
+ WHEN (${this._getTableIdentifier()}.expire <= $4 OR 1=${forceExpire ? 1 : 0}) THEN $2
1902
+ ELSE ${this._getTableIdentifier()}.points + ($2)
1903
+ END,
1904
+ expire = ${expireQ}
1905
+ RETURNING points, expire;`,
1906
+ values: [key, points, newExpire, Date.now()]
1907
+ });
1908
+ }
1909
+ _get(rlKey) {
1910
+ if (!this.tableCreated) {
1911
+ return Promise.reject(Error("Table is not created yet"));
1912
+ }
1913
+ return new Promise((resolve, reject) => {
1914
+ this._query({
1915
+ name: "rlflx-get",
1916
+ text: `
1917
+ SELECT points, expire FROM ${this._getTableIdentifier()} WHERE key = $1 AND (expire > $2 OR expire IS NULL);`,
1918
+ values: [rlKey, Date.now()]
1919
+ }).then((res) => {
1920
+ if (res.rowCount === 0) {
1921
+ res = null;
1922
+ }
1923
+ resolve(res);
1924
+ }).catch((err) => {
1925
+ reject(err);
1926
+ });
1927
+ });
1928
+ }
1929
+ _delete(rlKey) {
1930
+ if (!this.tableCreated) {
1931
+ return Promise.reject(Error("Table is not created yet"));
1932
+ }
1933
+ return this._query({
1934
+ name: "rlflx-delete",
1935
+ text: `DELETE FROM ${this._getTableIdentifier()} WHERE key = $1`,
1936
+ values: [rlKey]
1937
+ }).then((res) => res.rowCount > 0);
1938
+ }
1939
+ };
1940
+ module.exports = RateLimiterPostgres2;
1941
+ }
1942
+ });
1943
+
1944
+ // (disabled):cluster
1945
+ var require_cluster = __commonJS({
1946
+ "(disabled):cluster"() {
1947
+ "use strict";
1948
+ }
1949
+ });
1950
+
1951
+ // (disabled):crypto
1952
+ var require_crypto = __commonJS({
1953
+ "(disabled):crypto"() {
1954
+ "use strict";
1955
+ }
1956
+ });
1957
+
1958
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/MemoryStorage/Record.js
1959
+ var require_Record = __commonJS({
1960
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/MemoryStorage/Record.js"(exports, module) {
1961
+ "use strict";
1962
+ module.exports = class Record {
1963
+ /**
1964
+ *
1965
+ * @param value int
1966
+ * @param expiresAt Number|Date
1967
+ * @param timeoutId
1968
+ */
1969
+ constructor(value, expiresAt, timeoutId = null) {
1970
+ this.value = value;
1971
+ this.expiresAt = expiresAt;
1972
+ this.timeoutId = timeoutId;
1973
+ }
1974
+ get value() {
1975
+ return this._value;
1976
+ }
1977
+ set value(value) {
1978
+ this._value = parseInt(value, 10);
1979
+ }
1980
+ get expiresAt() {
1981
+ return this._expiresAt;
1982
+ }
1983
+ set expiresAt(value) {
1984
+ if (value instanceof Date) {
1985
+ this._expiresAt = value.getTime();
1986
+ } else {
1987
+ this._expiresAt = value;
1988
+ }
1989
+ }
1990
+ get timeoutId() {
1991
+ return this._timeoutId;
1992
+ }
1993
+ set timeoutId(value) {
1994
+ this._timeoutId = value;
1995
+ }
1996
+ };
1997
+ }
1998
+ });
1999
+
2000
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/MemoryStorage/MemoryStorage.js
2001
+ var require_MemoryStorage = __commonJS({
2002
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/MemoryStorage/MemoryStorage.js"(exports, module) {
2003
+ "use strict";
2004
+ var Record = require_Record();
2005
+ var RateLimiterRes2 = require_RateLimiterRes();
2006
+ module.exports = class MemoryStorage {
2007
+ constructor() {
2008
+ this._storage = /* @__PURE__ */ new Map();
2009
+ }
2010
+ incrby(key, value, durationSec) {
2011
+ const record = this._storage.get(key);
2012
+ if (record) {
2013
+ const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;
2014
+ if (!record.expiresAt || msBeforeExpires > 0) {
2015
+ record.value = record.value + value;
2016
+ return new RateLimiterRes2(0, msBeforeExpires, record.value, false);
2017
+ }
2018
+ return this.set(key, value, durationSec);
2019
+ }
2020
+ return this.set(key, value, durationSec);
2021
+ }
2022
+ set(key, value, durationSec) {
2023
+ const durationMs = durationSec * 1e3;
2024
+ const existingRecord = this._storage.get(key);
2025
+ if (existingRecord && existingRecord.timeoutId) {
2026
+ clearTimeout(existingRecord.timeoutId);
2027
+ }
2028
+ const record = new Record(
2029
+ value,
2030
+ durationMs > 0 ? Date.now() + durationMs : null
2031
+ );
2032
+ this._storage.set(key, record);
2033
+ if (durationMs > 0) {
2034
+ record.timeoutId = setTimeout(() => {
2035
+ this._storage.delete(key);
2036
+ }, durationMs);
2037
+ if (record.timeoutId.unref) {
2038
+ record.timeoutId.unref();
2039
+ }
2040
+ }
2041
+ return new RateLimiterRes2(0, durationMs === 0 ? -1 : durationMs, record.value, true);
2042
+ }
2043
+ /**
2044
+ *
2045
+ * @param key
2046
+ * @returns {*}
2047
+ */
2048
+ get(key) {
2049
+ const record = this._storage.get(key);
2050
+ if (record) {
2051
+ const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;
2052
+ return new RateLimiterRes2(0, msBeforeExpires, record.value, false);
2053
+ }
2054
+ return null;
2055
+ }
2056
+ /**
2057
+ *
2058
+ * @param key
2059
+ * @returns {boolean}
2060
+ */
2061
+ delete(key) {
2062
+ const record = this._storage.get(key);
2063
+ if (record) {
2064
+ if (record.timeoutId) {
2065
+ clearTimeout(record.timeoutId);
2066
+ }
2067
+ this._storage.delete(key);
2068
+ return true;
2069
+ }
2070
+ return false;
2071
+ }
2072
+ /**
2073
+ * @internal
2074
+ * @param key
2075
+ * @param value
2076
+ * @param expiresAt
2077
+ */
2078
+ _restoreRecord(key, value, expiresAt) {
2079
+ const now = Date.now();
2080
+ const hasExpiresAt = expiresAt !== null;
2081
+ if (hasExpiresAt && !Number.isFinite(expiresAt)) {
2082
+ return;
2083
+ }
2084
+ if (hasExpiresAt && expiresAt <= now) {
2085
+ return;
2086
+ }
2087
+ const durationMs = hasExpiresAt ? expiresAt - now : 0;
2088
+ const existingRecord = this._storage.get(key);
2089
+ if (existingRecord && existingRecord.timeoutId) {
2090
+ clearTimeout(existingRecord.timeoutId);
2091
+ }
2092
+ const record = new Record(
2093
+ value,
2094
+ expiresAt
2095
+ );
2096
+ this._storage.set(key, record);
2097
+ if (durationMs > 0) {
2098
+ record.timeoutId = setTimeout(() => {
2099
+ this._storage.delete(key);
2100
+ }, durationMs);
2101
+ if (record.timeoutId.unref) {
2102
+ record.timeoutId.unref();
2103
+ }
2104
+ }
2105
+ }
2106
+ };
2107
+ }
2108
+ });
2109
+
2110
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMemory.js
2111
+ var require_RateLimiterMemory = __commonJS({
2112
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMemory.js"(exports, module) {
2113
+ "use strict";
2114
+ var RateLimiterAbstract = require_RateLimiterAbstract();
2115
+ var MemoryStorage = require_MemoryStorage();
2116
+ var RateLimiterRes2 = require_RateLimiterRes();
2117
+ var RateLimiterMemory2 = class extends RateLimiterAbstract {
2118
+ constructor(opts = {}) {
2119
+ super(opts);
2120
+ this._memoryStorage = new MemoryStorage();
2121
+ }
2122
+ /**
2123
+ *
2124
+ * @param key
2125
+ * @param pointsToConsume
2126
+ * @param {Object} options
2127
+ * @returns {Promise<RateLimiterRes>}
2128
+ */
2129
+ consume(key, pointsToConsume = 1, options = {}) {
2130
+ return new Promise((resolve, reject) => {
2131
+ const rlKey = this.getKey(key);
2132
+ const secDuration = this._getKeySecDuration(options);
2133
+ let res = this._memoryStorage.incrby(rlKey, pointsToConsume, secDuration);
2134
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
2135
+ if (res.consumedPoints > this.points) {
2136
+ if (this.blockDuration > 0 && res.consumedPoints <= this.points + pointsToConsume) {
2137
+ res = this._memoryStorage.set(rlKey, res.consumedPoints, this.blockDuration);
2138
+ }
2139
+ reject(res);
2140
+ } else if (this.execEvenly && this.points > 0 && res.msBeforeNext > 0 && !res.isFirstInDuration) {
2141
+ let delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
2142
+ if (delay < this.execEvenlyMinDelayMs) {
2143
+ delay = res.consumedPoints * this.execEvenlyMinDelayMs;
2144
+ }
2145
+ res.msBeforeNext = Math.max(res.msBeforeNext - delay, 0);
2146
+ setTimeout(resolve, delay, res);
2147
+ } else {
2148
+ resolve(res);
2149
+ }
2150
+ });
2151
+ }
2152
+ penalty(key, points = 1, options = {}) {
2153
+ const rlKey = this.getKey(key);
2154
+ return new Promise((resolve) => {
2155
+ const secDuration = this._getKeySecDuration(options);
2156
+ const res = this._memoryStorage.incrby(rlKey, points, secDuration);
2157
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
2158
+ resolve(res);
2159
+ });
2160
+ }
2161
+ reward(key, points = 1, options = {}) {
2162
+ const rlKey = this.getKey(key);
2163
+ return new Promise((resolve) => {
2164
+ const secDuration = this._getKeySecDuration(options);
2165
+ const res = this._memoryStorage.incrby(rlKey, -points, secDuration);
2166
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
2167
+ resolve(res);
2168
+ });
2169
+ }
2170
+ /**
2171
+ * Block any key for secDuration seconds
2172
+ *
2173
+ * @param key
2174
+ * @param secDuration
2175
+ */
2176
+ block(key, secDuration) {
2177
+ const msDuration = secDuration * 1e3;
2178
+ const initPoints = this.points + 1;
2179
+ this._memoryStorage.set(this.getKey(key), initPoints, secDuration);
2180
+ return Promise.resolve(
2181
+ new RateLimiterRes2(0, msDuration === 0 ? -1 : msDuration, initPoints)
2182
+ );
2183
+ }
2184
+ set(key, points, secDuration) {
2185
+ const msDuration = (secDuration >= 0 ? secDuration : this.duration) * 1e3;
2186
+ this._memoryStorage.set(this.getKey(key), points, secDuration);
2187
+ return Promise.resolve(
2188
+ new RateLimiterRes2(0, msDuration === 0 ? -1 : msDuration, points)
2189
+ );
2190
+ }
2191
+ get(key) {
2192
+ const res = this._memoryStorage.get(this.getKey(key));
2193
+ if (res !== null) {
2194
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
2195
+ }
2196
+ return Promise.resolve(res);
2197
+ }
2198
+ delete(key) {
2199
+ return Promise.resolve(this._memoryStorage.delete(this.getKey(key)));
2200
+ }
2201
+ dump() {
2202
+ const storage = [];
2203
+ for (const [key, record] of this._memoryStorage._storage) {
2204
+ storage.push({
2205
+ key: this.parseKey(key),
2206
+ value: record.value,
2207
+ expiresAt: record.expiresAt
2208
+ });
2209
+ }
2210
+ return {
2211
+ version: 1,
2212
+ dumpedAt: Date.now(),
2213
+ storage
2214
+ };
2215
+ }
2216
+ /**
2217
+ * Restores rate-limiter state from a previously dumped snapshot.
2218
+ *
2219
+ * Each entry is classified into one of three buckets:
2220
+ * - **invalid** – the item is not an object or has a malformed schema (bad key, value or expiry type).
2221
+ * - **expired** – the item has logically expired based on current timestamp.
2222
+ * - **restored** – the item was valid and successfully loaded into storage.
2223
+ *
2224
+ * @param {Object} data - Snapshot produced by {@link dump}.
2225
+ * @param {boolean} [detailResponse=false] - When `true`, each bucket also
2226
+ * carries a `keys` array listing every affected key.
2227
+ * @returns {{ invalid, expired, restored } | undefined} Summary counts (and
2228
+ * optionally keys). Returns `undefined` when `data` fails schema checks.
2229
+ */
2230
+ restore(data, detailResponse = false) {
2231
+ if (!data || typeof data !== "object" || data.version !== 1) {
2232
+ return void 0;
2233
+ }
2234
+ const response = detailResponse ? {
2235
+ invalid: { count: 0, keys: [] },
2236
+ expired: { count: 0, keys: [] },
2237
+ restored: { count: 0, keys: [] }
2238
+ } : { invalid: 0, expired: 0, restored: 0 };
2239
+ const record = (bucket, key) => {
2240
+ if (detailResponse) {
2241
+ response[bucket].count += 1;
2242
+ response[bucket].keys.push(key);
2243
+ } else {
2244
+ response[bucket] += 1;
2245
+ }
2246
+ };
2247
+ if (!Array.isArray(data.storage)) {
2248
+ return response;
2249
+ }
2250
+ for (const item of data.storage) {
2251
+ if (!item || typeof item !== "object") {
2252
+ record("invalid", "N/A");
2253
+ continue;
2254
+ }
2255
+ const isValidKey = typeof item.key === "string" || typeof item.key === "number";
2256
+ const isValidValue = Number.isFinite(item.value);
2257
+ const isValidExpiry = item.expiresAt === null || Number.isFinite(item.expiresAt);
2258
+ if (!isValidKey || !isValidValue || !isValidExpiry) {
2259
+ record("invalid", item.key);
2260
+ continue;
2261
+ }
2262
+ if (item.expiresAt !== null && item.expiresAt <= Date.now()) {
2263
+ record("expired", item.key);
2264
+ continue;
2265
+ }
2266
+ this._memoryStorage._restoreRecord(this.getKey(item.key), item.value, item.expiresAt);
2267
+ record("restored", item.key);
2268
+ }
2269
+ return response;
2270
+ }
2271
+ };
2272
+ module.exports = RateLimiterMemory2;
2273
+ }
2274
+ });
2275
+
2276
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterCluster.js
2277
+ var require_RateLimiterCluster = __commonJS({
2278
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterCluster.js"(exports, module) {
2279
+ "use strict";
2280
+ var cluster = require_cluster();
2281
+ var crypto = require_crypto();
2282
+ var RateLimiterAbstract = require_RateLimiterAbstract();
2283
+ var RateLimiterMemory2 = require_RateLimiterMemory();
2284
+ var RateLimiterRes2 = require_RateLimiterRes();
2285
+ var channel = "rate_limiter_flexible";
2286
+ var masterInstance = null;
2287
+ var masterSendToWorker = function(worker, msg, type, res) {
2288
+ let data;
2289
+ if (res === null || res === true || res === false) {
2290
+ data = res;
2291
+ } else {
2292
+ data = {
2293
+ remainingPoints: res.remainingPoints,
2294
+ msBeforeNext: res.msBeforeNext,
2295
+ consumedPoints: res.consumedPoints,
2296
+ isFirstInDuration: res.isFirstInDuration
2297
+ };
2298
+ }
2299
+ worker.send({
2300
+ channel,
2301
+ keyPrefix: msg.keyPrefix,
2302
+ // which rate limiter exactly
2303
+ promiseId: msg.promiseId,
2304
+ type,
2305
+ data
2306
+ });
2307
+ };
2308
+ var workerWaitInit = function(payload) {
2309
+ setTimeout(() => {
2310
+ if (this._initiated) {
2311
+ process.send(payload);
2312
+ } else if (typeof this._promises[payload.promiseId] !== "undefined") {
2313
+ workerWaitInit.call(this, payload);
2314
+ }
2315
+ }, 30);
2316
+ };
2317
+ var workerSendToMaster = function(func, promiseId, key, arg, opts) {
2318
+ const payload = {
2319
+ channel,
2320
+ keyPrefix: this.keyPrefix,
2321
+ func,
2322
+ promiseId,
2323
+ data: {
2324
+ key,
2325
+ arg,
2326
+ opts
2327
+ }
2328
+ };
2329
+ if (!this._initiated) {
2330
+ workerWaitInit.call(this, payload);
2331
+ } else {
2332
+ process.send(payload);
2333
+ }
2334
+ };
2335
+ var masterProcessMsg = function(worker, msg) {
2336
+ if (!msg || msg.channel !== channel || typeof this._rateLimiters[msg.keyPrefix] === "undefined") {
2337
+ return false;
2338
+ }
2339
+ let promise;
2340
+ switch (msg.func) {
2341
+ case "consume":
2342
+ promise = this._rateLimiters[msg.keyPrefix].consume(msg.data.key, msg.data.arg, msg.data.opts);
2343
+ break;
2344
+ case "penalty":
2345
+ promise = this._rateLimiters[msg.keyPrefix].penalty(msg.data.key, msg.data.arg, msg.data.opts);
2346
+ break;
2347
+ case "reward":
2348
+ promise = this._rateLimiters[msg.keyPrefix].reward(msg.data.key, msg.data.arg, msg.data.opts);
2349
+ break;
2350
+ case "block":
2351
+ promise = this._rateLimiters[msg.keyPrefix].block(msg.data.key, msg.data.arg, msg.data.opts);
2352
+ break;
2353
+ case "get":
2354
+ promise = this._rateLimiters[msg.keyPrefix].get(msg.data.key, msg.data.opts);
2355
+ break;
2356
+ case "delete":
2357
+ promise = this._rateLimiters[msg.keyPrefix].delete(msg.data.key, msg.data.opts);
2358
+ break;
2359
+ default:
2360
+ return false;
2361
+ }
2362
+ if (promise) {
2363
+ promise.then((res) => {
2364
+ masterSendToWorker(worker, msg, "resolve", res);
2365
+ }).catch((rejRes) => {
2366
+ masterSendToWorker(worker, msg, "reject", rejRes);
2367
+ });
2368
+ }
2369
+ };
2370
+ var workerProcessMsg = function(msg) {
2371
+ if (!msg || msg.channel !== channel || msg.keyPrefix !== this.keyPrefix) {
2372
+ return false;
2373
+ }
2374
+ if (this._promises[msg.promiseId]) {
2375
+ clearTimeout(this._promises[msg.promiseId].timeoutId);
2376
+ let res;
2377
+ if (msg.data === null || msg.data === true || msg.data === false) {
2378
+ res = msg.data;
2379
+ } else {
2380
+ res = new RateLimiterRes2(
2381
+ msg.data.remainingPoints,
2382
+ msg.data.msBeforeNext,
2383
+ msg.data.consumedPoints,
2384
+ msg.data.isFirstInDuration
2385
+ // eslint-disable-line comma-dangle
2386
+ );
2387
+ }
2388
+ switch (msg.type) {
2389
+ case "resolve":
2390
+ this._promises[msg.promiseId].resolve(res);
2391
+ break;
2392
+ case "reject":
2393
+ this._promises[msg.promiseId].reject(res);
2394
+ break;
2395
+ default:
2396
+ throw new Error(`RateLimiterCluster: no such message type '${msg.type}'`);
2397
+ }
2398
+ delete this._promises[msg.promiseId];
2399
+ }
2400
+ };
2401
+ var getOpts = function() {
2402
+ return {
2403
+ points: this.points,
2404
+ duration: this.duration,
2405
+ blockDuration: this.blockDuration,
2406
+ execEvenly: this.execEvenly,
2407
+ execEvenlyMinDelayMs: this.execEvenlyMinDelayMs,
2408
+ keyPrefix: this.keyPrefix
2409
+ };
2410
+ };
2411
+ var savePromise = function(resolve, reject) {
2412
+ const hrtime = process.hrtime();
2413
+ let promiseId = hrtime[0].toString() + hrtime[1].toString();
2414
+ if (typeof this._promises[promiseId] !== "undefined") {
2415
+ promiseId += crypto.randomBytes(12).toString("base64");
2416
+ }
2417
+ this._promises[promiseId] = {
2418
+ resolve,
2419
+ reject,
2420
+ timeoutId: setTimeout(() => {
2421
+ delete this._promises[promiseId];
2422
+ reject(new Error("RateLimiterCluster timeout: no answer from master in time"));
2423
+ }, this.timeoutMs)
2424
+ };
2425
+ return promiseId;
2426
+ };
2427
+ var RateLimiterClusterMaster = class {
2428
+ constructor() {
2429
+ if (masterInstance) {
2430
+ return masterInstance;
2431
+ }
2432
+ this._rateLimiters = {};
2433
+ cluster.setMaxListeners(0);
2434
+ cluster.on("message", (worker, msg) => {
2435
+ if (msg && msg.channel === channel && msg.type === "init") {
2436
+ if (typeof this._rateLimiters[msg.opts.keyPrefix] === "undefined") {
2437
+ this._rateLimiters[msg.opts.keyPrefix] = new RateLimiterMemory2(msg.opts);
2438
+ }
2439
+ worker.send({
2440
+ channel,
2441
+ type: "init",
2442
+ keyPrefix: msg.opts.keyPrefix
2443
+ });
2444
+ } else {
2445
+ masterProcessMsg.call(this, worker, msg);
2446
+ }
2447
+ });
2448
+ masterInstance = this;
2449
+ }
2450
+ };
2451
+ var RateLimiterClusterMasterPM2 = class {
2452
+ constructor(pm2) {
2453
+ if (masterInstance) {
2454
+ return masterInstance;
2455
+ }
2456
+ this._rateLimiters = {};
2457
+ pm2.launchBus((err, pm2Bus) => {
2458
+ pm2Bus.on("process:msg", (packet) => {
2459
+ const msg = packet.raw;
2460
+ if (msg && msg.channel === channel && msg.type === "init") {
2461
+ if (typeof this._rateLimiters[msg.opts.keyPrefix] === "undefined") {
2462
+ this._rateLimiters[msg.opts.keyPrefix] = new RateLimiterMemory2(msg.opts);
2463
+ }
2464
+ pm2.sendDataToProcessId(packet.process.pm_id, {
2465
+ data: {},
2466
+ topic: channel,
2467
+ channel,
2468
+ type: "init",
2469
+ keyPrefix: msg.opts.keyPrefix
2470
+ }, (sendErr, res) => {
2471
+ if (sendErr) {
2472
+ console.log(sendErr, res);
2473
+ }
2474
+ });
2475
+ } else {
2476
+ const worker = {
2477
+ send: (msgData) => {
2478
+ const pm2Message = msgData;
2479
+ pm2Message.topic = channel;
2480
+ if (typeof pm2Message.data === "undefined") {
2481
+ pm2Message.data = {};
2482
+ }
2483
+ pm2.sendDataToProcessId(packet.process.pm_id, pm2Message, (sendErr, res) => {
2484
+ if (sendErr) {
2485
+ console.log(sendErr, res);
2486
+ }
2487
+ });
2488
+ }
2489
+ };
2490
+ masterProcessMsg.call(this, worker, msg);
2491
+ }
2492
+ });
2493
+ });
2494
+ masterInstance = this;
2495
+ }
2496
+ };
2497
+ var RateLimiterClusterWorker = class extends RateLimiterAbstract {
2498
+ get timeoutMs() {
2499
+ return this._timeoutMs;
2500
+ }
2501
+ set timeoutMs(value) {
2502
+ this._timeoutMs = typeof value === "undefined" ? 5e3 : Math.abs(parseInt(value));
2503
+ }
2504
+ constructor(opts = {}) {
2505
+ super(opts);
2506
+ process.setMaxListeners(0);
2507
+ this.timeoutMs = opts.timeoutMs;
2508
+ this._initiated = false;
2509
+ process.on("message", (msg) => {
2510
+ if (msg && msg.channel === channel && msg.type === "init" && msg.keyPrefix === this.keyPrefix) {
2511
+ this._initiated = true;
2512
+ } else {
2513
+ workerProcessMsg.call(this, msg);
2514
+ }
2515
+ });
2516
+ process.send({
2517
+ channel,
2518
+ type: "init",
2519
+ opts: getOpts.call(this)
2520
+ });
2521
+ this._promises = {};
2522
+ }
2523
+ consume(key, pointsToConsume = 1, options = {}) {
2524
+ return new Promise((resolve, reject) => {
2525
+ const promiseId = savePromise.call(this, resolve, reject);
2526
+ workerSendToMaster.call(this, "consume", promiseId, key, pointsToConsume, options);
2527
+ });
2528
+ }
2529
+ penalty(key, points = 1, options = {}) {
2530
+ return new Promise((resolve, reject) => {
2531
+ const promiseId = savePromise.call(this, resolve, reject);
2532
+ workerSendToMaster.call(this, "penalty", promiseId, key, points, options);
2533
+ });
2534
+ }
2535
+ reward(key, points = 1, options = {}) {
2536
+ return new Promise((resolve, reject) => {
2537
+ const promiseId = savePromise.call(this, resolve, reject);
2538
+ workerSendToMaster.call(this, "reward", promiseId, key, points, options);
2539
+ });
2540
+ }
2541
+ block(key, secDuration, options = {}) {
2542
+ return new Promise((resolve, reject) => {
2543
+ const promiseId = savePromise.call(this, resolve, reject);
2544
+ workerSendToMaster.call(this, "block", promiseId, key, secDuration, options);
2545
+ });
2546
+ }
2547
+ get(key, options = {}) {
2548
+ return new Promise((resolve, reject) => {
2549
+ const promiseId = savePromise.call(this, resolve, reject);
2550
+ workerSendToMaster.call(this, "get", promiseId, key, options);
2551
+ });
2552
+ }
2553
+ delete(key, options = {}) {
2554
+ return new Promise((resolve, reject) => {
2555
+ const promiseId = savePromise.call(this, resolve, reject);
2556
+ workerSendToMaster.call(this, "delete", promiseId, key, options);
2557
+ });
2558
+ }
2559
+ };
2560
+ module.exports = {
2561
+ RateLimiterClusterMaster,
2562
+ RateLimiterClusterMasterPM2,
2563
+ RateLimiterCluster: RateLimiterClusterWorker
2564
+ };
2565
+ }
2566
+ });
2567
+
2568
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMemcache.js
2569
+ var require_RateLimiterMemcache = __commonJS({
2570
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterMemcache.js"(exports, module) {
2571
+ "use strict";
2572
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
2573
+ var RateLimiterRes2 = require_RateLimiterRes();
2574
+ var RateLimiterMemcache = class extends RateLimiterStoreAbstract {
2575
+ /**
2576
+ *
2577
+ * @param {Object} opts
2578
+ * Defaults {
2579
+ * ... see other in RateLimiterStoreAbstract
2580
+ *
2581
+ * storeClient: memcacheClient
2582
+ * }
2583
+ */
2584
+ constructor(opts) {
2585
+ super(opts);
2586
+ this.client = opts.storeClient;
2587
+ }
2588
+ _getRateLimiterRes(rlKey, changedPoints, result) {
2589
+ const res = new RateLimiterRes2();
2590
+ res.consumedPoints = parseInt(result.consumedPoints);
2591
+ res.isFirstInDuration = result.consumedPoints === changedPoints;
2592
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
2593
+ res.msBeforeNext = result.msBeforeNext;
2594
+ return res;
2595
+ }
2596
+ _upsert(rlKey, points, msDuration, forceExpire = false, options = {}) {
2597
+ return new Promise((resolve, reject) => {
2598
+ const nowMs = Date.now();
2599
+ const secDuration = Math.floor(msDuration / 1e3);
2600
+ if (forceExpire) {
2601
+ this.client.set(rlKey, points, secDuration, (err) => {
2602
+ if (!err) {
2603
+ this.client.set(
2604
+ `${rlKey}_expire`,
2605
+ secDuration > 0 ? nowMs + secDuration * 1e3 : -1,
2606
+ secDuration,
2607
+ () => {
2608
+ const res = {
2609
+ consumedPoints: points,
2610
+ msBeforeNext: secDuration > 0 ? secDuration * 1e3 : -1
2611
+ };
2612
+ resolve(res);
2613
+ }
2614
+ );
2615
+ } else {
2616
+ reject(err);
2617
+ }
2618
+ });
2619
+ } else {
2620
+ this.client.incr(rlKey, points, (err, consumedPoints) => {
2621
+ if (err || consumedPoints === false) {
2622
+ this.client.add(rlKey, points, secDuration, (errAddKey, createdNew) => {
2623
+ if (errAddKey || !createdNew) {
2624
+ if (typeof options.attemptNumber === "undefined" || options.attemptNumber < 3) {
2625
+ const nextOptions = Object.assign({}, options);
2626
+ nextOptions.attemptNumber = nextOptions.attemptNumber ? nextOptions.attemptNumber + 1 : 1;
2627
+ this._upsert(rlKey, points, msDuration, forceExpire, nextOptions).then((resUpsert) => resolve(resUpsert)).catch((errUpsert) => reject(errUpsert));
2628
+ } else {
2629
+ reject(new Error("Can not add key"));
2630
+ }
2631
+ } else {
2632
+ this.client.add(
2633
+ `${rlKey}_expire`,
2634
+ secDuration > 0 ? nowMs + secDuration * 1e3 : -1,
2635
+ secDuration,
2636
+ () => {
2637
+ const res = {
2638
+ consumedPoints: points,
2639
+ msBeforeNext: secDuration > 0 ? secDuration * 1e3 : -1
2640
+ };
2641
+ resolve(res);
2642
+ }
2643
+ );
2644
+ }
2645
+ });
2646
+ } else {
2647
+ this.client.get(`${rlKey}_expire`, (errGetExpire, resGetExpireMs) => {
2648
+ if (errGetExpire) {
2649
+ reject(errGetExpire);
2650
+ } else {
2651
+ const expireMs = resGetExpireMs === false ? 0 : resGetExpireMs;
2652
+ const res = {
2653
+ consumedPoints,
2654
+ msBeforeNext: expireMs >= 0 ? Math.max(expireMs - nowMs, 0) : -1
2655
+ };
2656
+ resolve(res);
2657
+ }
2658
+ });
2659
+ }
2660
+ });
2661
+ }
2662
+ });
2663
+ }
2664
+ _get(rlKey) {
2665
+ return new Promise((resolve, reject) => {
2666
+ const nowMs = Date.now();
2667
+ this.client.get(rlKey, (err, consumedPoints) => {
2668
+ if (!consumedPoints) {
2669
+ resolve(null);
2670
+ } else {
2671
+ this.client.get(`${rlKey}_expire`, (errGetExpire, resGetExpireMs) => {
2672
+ if (errGetExpire) {
2673
+ reject(errGetExpire);
2674
+ } else {
2675
+ const expireMs = resGetExpireMs === false ? 0 : resGetExpireMs;
2676
+ const res = {
2677
+ consumedPoints,
2678
+ msBeforeNext: expireMs >= 0 ? Math.max(expireMs - nowMs, 0) : -1
2679
+ };
2680
+ resolve(res);
2681
+ }
2682
+ });
2683
+ }
2684
+ });
2685
+ });
2686
+ }
2687
+ _delete(rlKey) {
2688
+ return new Promise((resolve, reject) => {
2689
+ this.client.del(rlKey, (err, res) => {
2690
+ if (err) {
2691
+ reject(err);
2692
+ } else if (res === false) {
2693
+ resolve(res);
2694
+ } else {
2695
+ this.client.del(`${rlKey}_expire`, (errDelExpire) => {
2696
+ if (errDelExpire) {
2697
+ reject(errDelExpire);
2698
+ } else {
2699
+ resolve(res);
2700
+ }
2701
+ });
2702
+ }
2703
+ });
2704
+ });
2705
+ }
2706
+ };
2707
+ module.exports = RateLimiterMemcache;
2708
+ }
2709
+ });
2710
+
2711
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RLWrapperBlackAndWhite.js
2712
+ var require_RLWrapperBlackAndWhite = __commonJS({
2713
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RLWrapperBlackAndWhite.js"(exports, module) {
2714
+ "use strict";
2715
+ var RateLimiterRes2 = require_RateLimiterRes();
2716
+ var RateLimiterCompatibleAbstract = require_RateLimiterCompatibleAbstract();
2717
+ module.exports = class RLWrapperBlackAndWhite extends RateLimiterCompatibleAbstract {
2718
+ constructor(opts = {}) {
2719
+ super();
2720
+ this.limiter = opts.limiter;
2721
+ this.blackList = opts.blackList;
2722
+ this.whiteList = opts.whiteList;
2723
+ this.isBlackListed = opts.isBlackListed;
2724
+ this.isWhiteListed = opts.isWhiteListed;
2725
+ this.runActionAnyway = opts.runActionAnyway;
2726
+ }
2727
+ get limiter() {
2728
+ return this._limiter;
2729
+ }
2730
+ set limiter(value) {
2731
+ if (typeof value === "undefined") {
2732
+ throw new Error("limiter is not set");
2733
+ }
2734
+ this._limiter = value;
2735
+ }
2736
+ get keyPrefix() {
2737
+ return this.limiter.keyPrefix;
2738
+ }
2739
+ get blockDuration() {
2740
+ return this.limiter.blockDuration;
2741
+ }
2742
+ set blockDuration(value) {
2743
+ this.limiter.blockDuration = value;
2744
+ }
2745
+ get execEvenly() {
2746
+ return this.limiter.execEvenly;
2747
+ }
2748
+ set execEvenly(value) {
2749
+ this.limiter.execEvenly = value;
2750
+ }
2751
+ get runActionAnyway() {
2752
+ return this._runActionAnyway;
2753
+ }
2754
+ set runActionAnyway(value) {
2755
+ this._runActionAnyway = typeof value === "undefined" ? false : value;
2756
+ }
2757
+ get blackList() {
2758
+ return this._blackList;
2759
+ }
2760
+ set blackList(value) {
2761
+ this._blackList = Array.isArray(value) ? value : [];
2762
+ }
2763
+ get isBlackListed() {
2764
+ return this._isBlackListed;
2765
+ }
2766
+ set isBlackListed(func) {
2767
+ if (typeof func === "undefined") {
2768
+ func = () => false;
2769
+ }
2770
+ if (typeof func !== "function") {
2771
+ throw new Error("isBlackListed must be function");
2772
+ }
2773
+ this._isBlackListed = func;
2774
+ }
2775
+ get whiteList() {
2776
+ return this._whiteList;
2777
+ }
2778
+ set whiteList(value) {
2779
+ this._whiteList = Array.isArray(value) ? value : [];
2780
+ }
2781
+ get isWhiteListed() {
2782
+ return this._isWhiteListed;
2783
+ }
2784
+ set isWhiteListed(func) {
2785
+ if (typeof func === "undefined") {
2786
+ func = () => false;
2787
+ }
2788
+ if (typeof func !== "function") {
2789
+ throw new Error("isWhiteListed must be function");
2790
+ }
2791
+ this._isWhiteListed = func;
2792
+ }
2793
+ isBlackListedSomewhere(key) {
2794
+ return this.blackList.indexOf(key) >= 0 || this.isBlackListed(key);
2795
+ }
2796
+ isWhiteListedSomewhere(key) {
2797
+ return this.whiteList.indexOf(key) >= 0 || this.isWhiteListed(key);
2798
+ }
2799
+ getBlackRes() {
2800
+ return new RateLimiterRes2(0, Number.MAX_SAFE_INTEGER, 0, false);
2801
+ }
2802
+ getWhiteRes() {
2803
+ return new RateLimiterRes2(Number.MAX_SAFE_INTEGER, 0, 0, false);
2804
+ }
2805
+ rejectBlack() {
2806
+ return Promise.reject(this.getBlackRes());
2807
+ }
2808
+ resolveBlack() {
2809
+ return Promise.resolve(this.getBlackRes());
2810
+ }
2811
+ resolveWhite() {
2812
+ return Promise.resolve(this.getWhiteRes());
2813
+ }
2814
+ _execAction(action, key, args, rejectOnBlack = false) {
2815
+ let res;
2816
+ if (this.isWhiteListedSomewhere(key)) {
2817
+ res = this.resolveWhite();
2818
+ } else if (this.isBlackListedSomewhere(key)) {
2819
+ res = rejectOnBlack ? this.rejectBlack() : this.resolveBlack();
2820
+ }
2821
+ if (typeof res === "undefined") {
2822
+ return this.limiter[action](key, ...args);
2823
+ }
2824
+ if (this.runActionAnyway) {
2825
+ this.limiter[action](key, ...args).catch(() => {
2826
+ });
2827
+ }
2828
+ return res;
2829
+ }
2830
+ consume(key, pointsToConsume = 1, options = {}) {
2831
+ return this._execAction("consume", key, [pointsToConsume, options], true);
2832
+ }
2833
+ block(key, secDuration, options = {}) {
2834
+ return this._execAction("block", key, [secDuration, options]);
2835
+ }
2836
+ penalty(key, points = 1, options = {}) {
2837
+ return this._execAction("penalty", key, [points, options]);
2838
+ }
2839
+ reward(key, points = 1, options = {}) {
2840
+ return this._execAction("reward", key, [points, options]);
2841
+ }
2842
+ get(key, options = {}) {
2843
+ if (this.runActionAnyway) {
2844
+ return this.limiter.get(key, options);
2845
+ }
2846
+ return this._execAction("get", key, [options]);
2847
+ }
2848
+ set(key, points, secDuration, options = {}) {
2849
+ return this._execAction("set", key, [points, secDuration, options]);
2850
+ }
2851
+ delete(key, options = {}) {
2852
+ return this.limiter.delete(key, options);
2853
+ }
2854
+ };
2855
+ }
2856
+ });
2857
+
2858
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RLWrapperTimeouts.js
2859
+ var require_RLWrapperTimeouts = __commonJS({
2860
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RLWrapperTimeouts.js"(exports, module) {
2861
+ "use strict";
2862
+ var RateLimiterInsuredAbstract = require_RateLimiterInsuredAbstract();
2863
+ var isRateLimiterCompatible = require_isRateLimiterCompatible();
2864
+ module.exports = class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
2865
+ constructor(opts = {}) {
2866
+ super({
2867
+ ...opts,
2868
+ points: 0,
2869
+ duration: 0
2870
+ });
2871
+ this.limiter = opts.limiter;
2872
+ this.timeoutMs = opts.timeoutMs || 0;
2873
+ }
2874
+ get limiter() {
2875
+ return this._limiter;
2876
+ }
2877
+ set limiter(limiter) {
2878
+ if (!isRateLimiterCompatible(limiter)) {
2879
+ throw new TypeError("limiter must be an instance of RateLimiterAbstract or RateLimiterCompatibleAbstract");
2880
+ }
2881
+ this._limiter = limiter;
2882
+ if (!this.insuranceLimiter && limiter instanceof RateLimiterInsuredAbstract) {
2883
+ this.insuranceLimiter = limiter.insuranceLimiter;
2884
+ }
2885
+ }
2886
+ get timeoutMs() {
2887
+ return this._timeoutMs;
2888
+ }
2889
+ set timeoutMs(value) {
2890
+ if (typeof value !== "number" || value < 0) {
2891
+ throw new TypeError("timeoutMs must be a non-negative number");
2892
+ }
2893
+ this._timeoutMs = value;
2894
+ }
2895
+ _run(funcName, params) {
2896
+ return new Promise(async (resolve, reject) => {
2897
+ const timeout = setTimeout(() => {
2898
+ return reject(new Error("Operation timed out"));
2899
+ }, this.timeoutMs);
2900
+ await this.limiter[funcName](...params).then((result) => {
2901
+ clearTimeout(timeout);
2902
+ resolve(result);
2903
+ }).catch((err) => {
2904
+ clearTimeout(timeout);
2905
+ reject(err);
2906
+ });
2907
+ });
2908
+ }
2909
+ _consume(key, pointsToConsume = 1, options = {}) {
2910
+ return this._run("consume", [key, pointsToConsume, options]);
2911
+ }
2912
+ _penalty(key, points = 1, options = {}) {
2913
+ return this._run("penalty", [key, points, options]);
2914
+ }
2915
+ _reward(key, points = 1, options = {}) {
2916
+ return this._run("reward", [key, points, options]);
2917
+ }
2918
+ _get(key, options = {}) {
2919
+ return this._run("get", [key, options]);
2920
+ }
2921
+ _set(key, points, secDuration, options = {}) {
2922
+ return this._run("set", [key, points, secDuration, options]);
2923
+ }
2924
+ _block(key, secDuration, options = {}) {
2925
+ return this._run("block", [key, secDuration, options]);
2926
+ }
2927
+ _delete(key, options = {}) {
2928
+ return this._run("delete", [key, options]);
2929
+ }
2930
+ };
2931
+ }
2932
+ });
2933
+
2934
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterUnion.js
2935
+ var require_RateLimiterUnion = __commonJS({
2936
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterUnion.js"(exports, module) {
2937
+ "use strict";
2938
+ var isRateLimiterCompatible = require_isRateLimiterCompatible();
2939
+ module.exports = class RateLimiterUnion {
2940
+ constructor(...limiters) {
2941
+ if (limiters.length < 1) {
2942
+ throw new Error("RateLimiterUnion: at least one limiter have to be passed");
2943
+ }
2944
+ limiters.forEach((limiter) => {
2945
+ if (!isRateLimiterCompatible(limiter)) {
2946
+ throw new Error("RateLimiterUnion: all limiters have to be instance of RateLimiterAbstract or RateLimiterCompatibleAbstract");
2947
+ }
2948
+ });
2949
+ this._limiters = limiters;
2950
+ }
2951
+ consume(key, points = 1) {
2952
+ return new Promise((resolve, reject) => {
2953
+ const promises = [];
2954
+ this._limiters.forEach((limiter) => {
2955
+ promises.push(limiter.consume(key, points).catch((rej) => ({ rejected: true, rej })));
2956
+ });
2957
+ Promise.all(promises).then((res) => {
2958
+ const resObj = {};
2959
+ let rejected = false;
2960
+ res.forEach((item) => {
2961
+ if (item.rejected === true) {
2962
+ rejected = true;
2963
+ }
2964
+ });
2965
+ for (let i = 0; i < res.length; i++) {
2966
+ if (rejected && res[i].rejected === true) {
2967
+ resObj[this._limiters[i].keyPrefix] = res[i].rej;
2968
+ } else if (!rejected) {
2969
+ resObj[this._limiters[i].keyPrefix] = res[i];
2970
+ }
2971
+ }
2972
+ if (rejected) {
2973
+ reject(resObj);
2974
+ } else {
2975
+ resolve(resObj);
2976
+ }
2977
+ });
2978
+ });
2979
+ }
2980
+ };
2981
+ }
2982
+ });
2983
+
2984
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterQueueError.js
2985
+ var require_RateLimiterQueueError = __commonJS({
2986
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterQueueError.js"(exports, module) {
2987
+ "use strict";
2988
+ module.exports = class RateLimiterQueueError extends Error {
2989
+ constructor(message, extra) {
2990
+ super();
2991
+ if (Error.captureStackTrace) {
2992
+ Error.captureStackTrace(this, this.constructor);
2993
+ }
2994
+ this.name = "CustomError";
2995
+ this.message = message;
2996
+ if (extra) {
2997
+ this.extra = extra;
2998
+ }
2999
+ }
3000
+ };
3001
+ }
3002
+ });
3003
+
3004
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterQueue.js
3005
+ var require_RateLimiterQueue = __commonJS({
3006
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterQueue.js"(exports, module) {
3007
+ "use strict";
3008
+ var RateLimiterQueueError = require_RateLimiterQueueError();
3009
+ var MAX_QUEUE_SIZE = 4294967295;
3010
+ var KEY_DEFAULT = "limiter";
3011
+ module.exports = class RateLimiterQueue {
3012
+ constructor(limiterFlexible, opts = {}) {
3013
+ const maxQueueSize = opts.maxQueueSize !== void 0 ? opts.maxQueueSize : MAX_QUEUE_SIZE;
3014
+ this._queueLimiters = {
3015
+ KEY_DEFAULT: new RateLimiterQueueInternal(limiterFlexible, {
3016
+ ...opts,
3017
+ maxQueueSize,
3018
+ key: KEY_DEFAULT
3019
+ })
3020
+ };
3021
+ this._limiterFlexible = limiterFlexible;
3022
+ this._maxQueueSize = maxQueueSize;
3023
+ }
3024
+ getTokensRemaining(key = KEY_DEFAULT) {
3025
+ if (this._queueLimiters[key]) {
3026
+ return this._queueLimiters[key].getTokensRemaining();
3027
+ } else {
3028
+ return Promise.resolve(this._limiterFlexible.points);
3029
+ }
3030
+ }
3031
+ removeTokens(tokens, key = KEY_DEFAULT, expiresUnixAt = 0) {
3032
+ if (!this._queueLimiters[key]) {
3033
+ this._queueLimiters[key] = new RateLimiterQueueInternal(
3034
+ this._limiterFlexible,
3035
+ {
3036
+ key,
3037
+ maxQueueSize: this._maxQueueSize
3038
+ }
3039
+ );
3040
+ }
3041
+ return this._queueLimiters[key].removeTokens(tokens, expiresUnixAt);
3042
+ }
3043
+ };
3044
+ var RateLimiterQueueInternal = class {
3045
+ constructor(limiterFlexible, opts = {
3046
+ maxQueueSize: MAX_QUEUE_SIZE,
3047
+ key: KEY_DEFAULT
3048
+ }) {
3049
+ this._key = opts.key;
3050
+ this._waitTimeout = null;
3051
+ this._queue = [];
3052
+ this._limiterFlexible = limiterFlexible;
3053
+ this._hasExpiringRequests = false;
3054
+ this._maxQueueSize = opts.maxQueueSize;
3055
+ }
3056
+ getTokensRemaining() {
3057
+ return this._limiterFlexible.get(this._key).then((rlRes) => {
3058
+ return rlRes !== null ? rlRes.remainingPoints : this._limiterFlexible.points;
3059
+ });
3060
+ }
3061
+ removeTokens(tokens, expiresUnixAt = 0) {
3062
+ const _this = this;
3063
+ return new Promise((resolve, reject) => {
3064
+ if (tokens > _this._limiterFlexible.points) {
3065
+ reject(new RateLimiterQueueError(`Requested tokens ${tokens} exceeds maximum ${_this._limiterFlexible.points} tokens per interval`));
3066
+ return;
3067
+ }
3068
+ if (_this._queue.length > 0) {
3069
+ _this._queueRequest.call(_this, resolve, reject, tokens, expiresUnixAt);
3070
+ } else {
3071
+ _this._limiterFlexible.consume(_this._key, tokens).then((res) => {
3072
+ resolve(res.remainingPoints);
3073
+ }).catch((rej) => {
3074
+ if (rej instanceof Error) {
3075
+ reject(rej);
3076
+ } else {
3077
+ _this._queueRequest.call(_this, resolve, reject, tokens, expiresUnixAt);
3078
+ if (_this._waitTimeout === null) {
3079
+ _this._waitTimeout = setTimeout(_this._processFIFO.bind(_this), rej.msBeforeNext);
3080
+ }
3081
+ }
3082
+ });
3083
+ }
3084
+ });
3085
+ }
3086
+ _queueRequest(resolve, reject, tokens, expiresUnixAt = 0) {
3087
+ const _this = this;
3088
+ if (_this._queue.length < _this._maxQueueSize) {
3089
+ _this._queue.push({ resolve, reject, tokens, expiresUnixAt });
3090
+ if (expiresUnixAt > 0) {
3091
+ _this._hasExpiringRequests = true;
3092
+ }
3093
+ } else {
3094
+ reject(new RateLimiterQueueError(`Number of requests reached it's maximum ${_this._maxQueueSize}`));
3095
+ }
3096
+ }
3097
+ _processFIFO() {
3098
+ const _this = this;
3099
+ if (_this._waitTimeout !== null) {
3100
+ clearTimeout(_this._waitTimeout);
3101
+ _this._waitTimeout = null;
3102
+ }
3103
+ if (_this._hasExpiringRequests) {
3104
+ const nowSecs = Math.floor(Date.now() / 1e3);
3105
+ _this._queue = _this._queue.filter((item2) => {
3106
+ if (item2.expiresUnixAt > 0 && nowSecs >= item2.expiresUnixAt) {
3107
+ item2.reject(new RateLimiterQueueError("The request to remove tokens expired before it could be fulfilled"));
3108
+ return false;
3109
+ }
3110
+ return true;
3111
+ });
3112
+ }
3113
+ if (_this._queue.length === 0) {
3114
+ return;
3115
+ }
3116
+ const item = _this._queue.shift();
3117
+ _this._limiterFlexible.consume(_this._key, item.tokens).then((res) => {
3118
+ item.resolve(res.remainingPoints);
3119
+ _this._processFIFO.call(_this);
3120
+ }).catch((rej) => {
3121
+ if (rej instanceof Error) {
3122
+ item.reject(rej);
3123
+ _this._processFIFO.call(_this);
3124
+ } else {
3125
+ _this._queue.unshift(item);
3126
+ if (_this._waitTimeout === null) {
3127
+ _this._waitTimeout = setTimeout(_this._processFIFO.bind(_this), rej.msBeforeNext);
3128
+ }
3129
+ }
3130
+ });
3131
+ }
3132
+ };
3133
+ }
3134
+ });
3135
+
3136
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/BurstyRateLimiter.js
3137
+ var require_BurstyRateLimiter = __commonJS({
3138
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/BurstyRateLimiter.js"(exports, module) {
3139
+ "use strict";
3140
+ var RateLimiterRes2 = require_RateLimiterRes();
3141
+ module.exports = class BurstyRateLimiter {
3142
+ constructor(rateLimiter, burstLimiter) {
3143
+ this._rateLimiter = rateLimiter;
3144
+ this._burstLimiter = burstLimiter;
3145
+ }
3146
+ /**
3147
+ * Merge rate limiter response objects. Responses can be null
3148
+ *
3149
+ * @param {RateLimiterRes} [rlRes] Rate limiter response
3150
+ * @param {RateLimiterRes} [blRes] Bursty limiter response
3151
+ */
3152
+ _combineRes(rlRes, blRes) {
3153
+ if (!rlRes) {
3154
+ return null;
3155
+ }
3156
+ return new RateLimiterRes2(
3157
+ rlRes.remainingPoints,
3158
+ Math.min(rlRes.msBeforeNext, blRes ? blRes.msBeforeNext : 0),
3159
+ rlRes.consumedPoints,
3160
+ rlRes.isFirstInDuration
3161
+ );
3162
+ }
3163
+ /**
3164
+ * @param key
3165
+ * @param pointsToConsume
3166
+ * @param options
3167
+ * @returns {Promise<any>}
3168
+ */
3169
+ consume(key, pointsToConsume = 1, options = {}) {
3170
+ return this._rateLimiter.consume(key, pointsToConsume, options).catch((rlRej) => {
3171
+ if (rlRej instanceof RateLimiterRes2) {
3172
+ return this._burstLimiter.consume(key, pointsToConsume, options).then((blRes) => {
3173
+ return Promise.resolve(this._combineRes(rlRej, blRes));
3174
+ }).catch(
3175
+ (blRej) => {
3176
+ if (blRej instanceof RateLimiterRes2) {
3177
+ return Promise.reject(this._combineRes(rlRej, blRej));
3178
+ } else {
3179
+ return Promise.reject(blRej);
3180
+ }
3181
+ }
3182
+ );
3183
+ } else {
3184
+ return Promise.reject(rlRej);
3185
+ }
3186
+ });
3187
+ }
3188
+ /**
3189
+ * It doesn't expose available points from burstLimiter
3190
+ *
3191
+ * @param key
3192
+ * @returns {Promise<RateLimiterRes>}
3193
+ */
3194
+ get(key) {
3195
+ return Promise.all([
3196
+ this._rateLimiter.get(key),
3197
+ this._burstLimiter.get(key)
3198
+ ]).then(([rlRes, blRes]) => {
3199
+ return this._combineRes(rlRes, blRes);
3200
+ });
3201
+ }
3202
+ get points() {
3203
+ return this._rateLimiter.points;
3204
+ }
3205
+ };
3206
+ }
3207
+ });
3208
+
3209
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDynamo.js
3210
+ var require_RateLimiterDynamo = __commonJS({
3211
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDynamo.js"(exports, module) {
3212
+ "use strict";
3213
+ var RateLimiterRes2 = require_RateLimiterRes();
3214
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
3215
+ var DynamoItem = class {
3216
+ /**
3217
+ * Create a DynamoItem.
3218
+ * @param {string} rlKey - The key for the rate limiter.
3219
+ * @param {number} points - The number of points.
3220
+ * @param {number} expire - The expiration time in seconds.
3221
+ */
3222
+ constructor(rlKey, points, expire) {
3223
+ this.key = rlKey;
3224
+ this.points = points;
3225
+ this.expire = expire;
3226
+ }
3227
+ };
3228
+ var DEFAULT_READ_CAPACITY_UNITS = 25;
3229
+ var DEFAULT_WRITE_CAPACITY_UNITS = 25;
3230
+ var RateLimiterDynamo = class extends RateLimiterStoreAbstract {
3231
+ /**
3232
+ * Constructs a new instance of the class.
3233
+ * The storeClient MUST be an instance of AWS.DynamoDB NOT of AWS.DynamoDBClient.
3234
+ *
3235
+ * @param {Object} opts - The options for the constructor.
3236
+ * @param {function} cb - The callback function (optional).
3237
+ * @return {void}
3238
+ */
3239
+ constructor(opts, cb = null) {
3240
+ super(opts);
3241
+ this.client = opts.storeClient;
3242
+ this.tableName = opts.tableName;
3243
+ this.tableCreated = opts.tableCreated;
3244
+ this.ttlManuallySet = opts.ttlSet;
3245
+ if (!this.tableCreated) {
3246
+ this._createTable(opts.dynamoTableOpts).then((data) => {
3247
+ this.tableCreated = true;
3248
+ this._setTTL().finally(() => {
3249
+ if (typeof cb === "function") {
3250
+ cb();
3251
+ }
3252
+ });
3253
+ }).catch((err) => {
3254
+ if (typeof cb === "function") {
3255
+ cb(err);
3256
+ } else {
3257
+ throw err;
3258
+ }
3259
+ });
3260
+ } else {
3261
+ this._setTTL().finally(() => {
3262
+ if (typeof cb === "function") {
3263
+ cb();
3264
+ }
3265
+ });
3266
+ }
3267
+ }
3268
+ get tableName() {
3269
+ return this._tableName;
3270
+ }
3271
+ set tableName(value) {
3272
+ this._tableName = typeof value === "undefined" ? "node-rate-limiter-flexible" : value;
3273
+ }
3274
+ get tableCreated() {
3275
+ return this._tableCreated;
3276
+ }
3277
+ set tableCreated(value) {
3278
+ this._tableCreated = typeof value === "undefined" ? false : !!value;
3279
+ }
3280
+ /**
3281
+ * Creates a table in the database. Return null if the table already exists.
3282
+ *
3283
+ * @param {{readCapacityUnits: number, writeCapacityUnits: number}} tableOpts
3284
+ * @return {Promise} A promise that resolves with the result of creating the table.
3285
+ */
3286
+ async _createTable(tableOpts) {
3287
+ const params = {
3288
+ TableName: this.tableName,
3289
+ AttributeDefinitions: [
3290
+ {
3291
+ AttributeName: "key",
3292
+ AttributeType: "S"
3293
+ }
3294
+ ],
3295
+ KeySchema: [
3296
+ {
3297
+ AttributeName: "key",
3298
+ KeyType: "HASH"
3299
+ }
3300
+ ],
3301
+ ProvisionedThroughput: {
3302
+ ReadCapacityUnits: tableOpts && tableOpts.readCapacityUnits ? tableOpts.readCapacityUnits : DEFAULT_READ_CAPACITY_UNITS,
3303
+ WriteCapacityUnits: tableOpts && tableOpts.writeCapacityUnits ? tableOpts.writeCapacityUnits : DEFAULT_WRITE_CAPACITY_UNITS
3304
+ }
3305
+ };
3306
+ try {
3307
+ const data = await this.client.createTable(params);
3308
+ return data;
3309
+ } catch (err) {
3310
+ if (err.__type && err.__type.includes("ResourceInUseException")) {
3311
+ return null;
3312
+ } else {
3313
+ throw err;
3314
+ }
3315
+ }
3316
+ }
3317
+ /**
3318
+ * Retrieves an item from the table based on the provided key.
3319
+ *
3320
+ * @param {string} rlKey - The key used to retrieve the item.
3321
+ * @throws {Error} Throws an error if the table is not created yet.
3322
+ * @return {DynamoItem|null} - The retrieved item, or null if it doesn't exist.
3323
+ */
3324
+ async _get(rlKey) {
3325
+ if (!this.tableCreated) {
3326
+ throw new Error("Table is not created yet");
3327
+ }
3328
+ const params = {
3329
+ TableName: this.tableName,
3330
+ Key: {
3331
+ key: { S: rlKey }
3332
+ }
3333
+ };
3334
+ const data = await this.client.getItem(params);
3335
+ if (!data.Item) {
3336
+ return null;
3337
+ }
3338
+ const item = new DynamoItem(
3339
+ data.Item.key.S,
3340
+ Number(data.Item.points.N),
3341
+ Number(data.Item.expire.N)
3342
+ );
3343
+ const dateNowSec = Date.now() / 1e3;
3344
+ if (item.expire !== -1 && item.expire <= dateNowSec) {
3345
+ return null;
3346
+ }
3347
+ return item;
3348
+ }
3349
+ /**
3350
+ * Deletes an item from the table based on the given rlKey.
3351
+ *
3352
+ * @param {string} rlKey - The rlKey of the item to delete.
3353
+ * @throws {Error} Throws an error if the table is not created yet.
3354
+ * @return {boolean} Returns true if the item was successfully deleted, otherwise false.
3355
+ */
3356
+ async _delete(rlKey) {
3357
+ if (!this.tableCreated) {
3358
+ throw new Error("Table is not created yet");
3359
+ }
3360
+ const params = {
3361
+ TableName: this.tableName,
3362
+ Key: {
3363
+ key: { S: rlKey }
3364
+ },
3365
+ ConditionExpression: "attribute_exists(#k)",
3366
+ ExpressionAttributeNames: {
3367
+ "#k": "key"
3368
+ }
3369
+ };
3370
+ try {
3371
+ const data = await this._client.deleteItem(params);
3372
+ return data.$metadata.httpStatusCode === 200;
3373
+ } catch (err) {
3374
+ if (err.__type && err.__type.includes("ConditionalCheckFailedException")) {
3375
+ return false;
3376
+ } else {
3377
+ throw err;
3378
+ }
3379
+ }
3380
+ }
3381
+ /**
3382
+ * Implemented with DynamoDB Atomic Counters. 3 calls are made to DynamoDB but each call is atomic.
3383
+ * From the documentation: "UpdateItem calls are naturally serialized within DynamoDB,
3384
+ * so there are no race condition concerns with making multiple simultaneous calls."
3385
+ * See: https://aws.amazon.com/it/blogs/database/implement-resource-counters-with-amazon-dynamodb/
3386
+ * @param {*} rlKey
3387
+ * @param {*} points
3388
+ * @param {*} msDuration
3389
+ * @param {*} forceExpire
3390
+ * @param {*} options
3391
+ * @returns
3392
+ */
3393
+ async _upsert(rlKey, points, msDuration, forceExpire = false, options = {}) {
3394
+ if (!this.tableCreated) {
3395
+ throw new Error("Table is not created yet");
3396
+ }
3397
+ const dateNow = Date.now();
3398
+ const dateNowSec = dateNow / 1e3;
3399
+ const newExpireSec = msDuration > 0 ? (dateNow + msDuration) / 1e3 : -1;
3400
+ if (forceExpire) {
3401
+ return await this._baseUpsert({
3402
+ TableName: this.tableName,
3403
+ Key: { key: { S: rlKey } },
3404
+ UpdateExpression: "SET points = :points, expire = :expire",
3405
+ ExpressionAttributeValues: {
3406
+ ":points": { N: points.toString() },
3407
+ ":expire": { N: newExpireSec.toString() }
3408
+ },
3409
+ ReturnValues: "ALL_NEW"
3410
+ });
3411
+ }
3412
+ try {
3413
+ return await this._baseUpsert({
3414
+ TableName: this.tableName,
3415
+ Key: { key: { S: rlKey } },
3416
+ UpdateExpression: "SET points = :new_points, expire = :new_expire",
3417
+ ExpressionAttributeValues: {
3418
+ ":new_points": { N: points.toString() },
3419
+ ":new_expire": { N: newExpireSec.toString() },
3420
+ ":where_expire": { N: dateNowSec.toString() }
3421
+ },
3422
+ ConditionExpression: "expire <= :where_expire OR attribute_not_exists(points)",
3423
+ ReturnValues: "ALL_NEW"
3424
+ });
3425
+ } catch (err) {
3426
+ return await this._baseUpsert({
3427
+ TableName: this.tableName,
3428
+ Key: { key: { S: rlKey } },
3429
+ UpdateExpression: "SET points = points + :new_points",
3430
+ ExpressionAttributeValues: {
3431
+ ":new_points": { N: points.toString() },
3432
+ ":where_expire": { N: dateNowSec.toString() }
3433
+ },
3434
+ ConditionExpression: "expire > :where_expire",
3435
+ ReturnValues: "ALL_NEW"
3436
+ });
3437
+ }
3438
+ }
3439
+ /**
3440
+ * Asynchronously upserts data into the table. params is a DynamoDB params object.
3441
+ *
3442
+ * @param {Object} params - The parameters for the upsert operation.
3443
+ * @throws {Error} Throws an error if the table is not created yet.
3444
+ * @return {DynamoItem} Returns a DynamoItem object with the updated data.
3445
+ */
3446
+ async _baseUpsert(params) {
3447
+ if (!this.tableCreated) {
3448
+ throw new Error("Table is not created yet");
3449
+ }
3450
+ try {
3451
+ const data = await this.client.updateItem(params);
3452
+ return new DynamoItem(
3453
+ data.Attributes.key.S,
3454
+ Number(data.Attributes.points.N),
3455
+ Number(data.Attributes.expire.N)
3456
+ );
3457
+ } catch (err) {
3458
+ throw err;
3459
+ }
3460
+ }
3461
+ /**
3462
+ * Sets the Time-to-Live (TTL) for the table. TTL use the expire field in the table.
3463
+ * See: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html
3464
+ *
3465
+ * @return {Promise} A promise that resolves when the TTL is successfully set.
3466
+ * @throws {Error} Throws an error if the table is not created yet.
3467
+ * @returns {Promise}
3468
+ */
3469
+ async _setTTL() {
3470
+ if (!this.tableCreated) {
3471
+ throw new Error("Table is not created yet");
3472
+ }
3473
+ try {
3474
+ const isTTLSet = await this._isTTLSet();
3475
+ if (isTTLSet) {
3476
+ return;
3477
+ }
3478
+ const params = {
3479
+ TableName: this.tableName,
3480
+ TimeToLiveSpecification: {
3481
+ AttributeName: "expire",
3482
+ Enabled: true
3483
+ }
3484
+ };
3485
+ const res = await this.client.updateTimeToLive(params);
3486
+ return res;
3487
+ } catch (err) {
3488
+ throw err;
3489
+ }
3490
+ }
3491
+ /**
3492
+ * Checks if the Time To Live (TTL) feature is set for the DynamoDB table.
3493
+ *
3494
+ * @return {boolean} Returns true if the TTL feature is enabled for the table, otherwise false.
3495
+ * @throws {Error} Throws an error if the table is not created yet or if there is an error while checking the TTL status.
3496
+ */
3497
+ async _isTTLSet() {
3498
+ if (!this.tableCreated) {
3499
+ throw new Error("Table is not created yet");
3500
+ }
3501
+ if (this.ttlManuallySet) {
3502
+ return true;
3503
+ }
3504
+ try {
3505
+ const res = await this.client.describeTimeToLive({ TableName: this.tableName });
3506
+ return res.$metadata.httpStatusCode == 200 && res.TimeToLiveDescription.TimeToLiveStatus === "ENABLED" && res.TimeToLiveDescription.AttributeName === "expire";
3507
+ } catch (err) {
3508
+ throw err;
3509
+ }
3510
+ }
3511
+ /**
3512
+ * Generate a RateLimiterRes object based on the provided parameters.
3513
+ *
3514
+ * @param {string} rlKey - The key for the rate limiter.
3515
+ * @param {number} changedPoints - The number of points that have changed.
3516
+ * @param {DynamoItem} result - The result object of _get() method.
3517
+ * @returns {RateLimiterRes} - The generated RateLimiterRes object.
3518
+ */
3519
+ _getRateLimiterRes(rlKey, changedPoints, result) {
3520
+ const res = new RateLimiterRes2();
3521
+ res.isFirstInDuration = changedPoints === result.points;
3522
+ res.consumedPoints = res.isFirstInDuration ? changedPoints : result.points;
3523
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
3524
+ res.msBeforeNext = result.expire != -1 ? Math.max(result.expire * 1e3 - Date.now(), 0) : -1;
3525
+ return res;
3526
+ }
3527
+ };
3528
+ module.exports = RateLimiterDynamo;
3529
+ }
3530
+ });
3531
+
3532
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterPrisma.js
3533
+ var require_RateLimiterPrisma = __commonJS({
3534
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterPrisma.js"(exports, module) {
3535
+ "use strict";
3536
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
3537
+ var RateLimiterRes2 = require_RateLimiterRes();
3538
+ var RateLimiterPrisma = class extends RateLimiterStoreAbstract {
3539
+ /**
3540
+ * Constructor for the rate limiter
3541
+ * @param {Object} opts - Options for the rate limiter
3542
+ */
3543
+ constructor(opts) {
3544
+ super(opts);
3545
+ this.modelName = opts.tableName || "RateLimiterFlexible";
3546
+ this.prismaClient = opts.storeClient;
3547
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout || true;
3548
+ if (!this.prismaClient) {
3549
+ throw new Error("Prisma client is not provided");
3550
+ }
3551
+ if (this.clearExpiredByTimeout) {
3552
+ this._clearExpiredHourAgo();
3553
+ }
3554
+ }
3555
+ _getRateLimiterRes(rlKey, changedPoints, result) {
3556
+ const res = new RateLimiterRes2();
3557
+ let doc = result;
3558
+ res.isFirstInDuration = doc.points === changedPoints;
3559
+ res.consumedPoints = doc.points;
3560
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
3561
+ res.msBeforeNext = doc.expire !== null ? Math.max(new Date(doc.expire).getTime() - Date.now(), 0) : -1;
3562
+ return res;
3563
+ }
3564
+ _upsert(key, points, msDuration, forceExpire = false) {
3565
+ if (!this.prismaClient) {
3566
+ return Promise.reject(new Error("Prisma client is not established"));
3567
+ }
3568
+ const now = /* @__PURE__ */ new Date();
3569
+ const newExpire = msDuration > 0 ? new Date(now.getTime() + msDuration) : null;
3570
+ return this.prismaClient.$transaction(async (prisma) => {
3571
+ const existingRecord = await prisma[this.modelName].findFirst({
3572
+ where: { key }
3573
+ });
3574
+ if (existingRecord) {
3575
+ const shouldUpdateExpire = forceExpire || !existingRecord.expire || existingRecord.expire <= now || newExpire === null;
3576
+ return prisma[this.modelName].update({
3577
+ where: { key },
3578
+ data: {
3579
+ points: !shouldUpdateExpire ? existingRecord.points + points : points,
3580
+ ...shouldUpdateExpire && { expire: newExpire }
3581
+ }
3582
+ });
3583
+ } else {
3584
+ return prisma[this.modelName].create({
3585
+ data: {
3586
+ key,
3587
+ points,
3588
+ expire: newExpire
3589
+ }
3590
+ });
3591
+ }
3592
+ });
3593
+ }
3594
+ _get(rlKey) {
3595
+ if (!this.prismaClient) {
3596
+ return Promise.reject(new Error("Prisma client is not established"));
3597
+ }
3598
+ return this.prismaClient[this.modelName].findFirst({
3599
+ where: {
3600
+ AND: [
3601
+ { key: rlKey },
3602
+ {
3603
+ OR: [
3604
+ { expire: { gt: /* @__PURE__ */ new Date() } },
3605
+ { expire: null }
3606
+ ]
3607
+ }
3608
+ ]
3609
+ }
3610
+ });
3611
+ }
3612
+ _delete(rlKey) {
3613
+ if (!this.prismaClient) {
3614
+ return Promise.reject(new Error("Prisma client is not established"));
3615
+ }
3616
+ return this.prismaClient[this.modelName].deleteMany({
3617
+ where: {
3618
+ key: rlKey
3619
+ }
3620
+ }).then((res) => res.count > 0);
3621
+ }
3622
+ _clearExpiredHourAgo() {
3623
+ if (this._clearExpiredTimeoutId) {
3624
+ clearTimeout(this._clearExpiredTimeoutId);
3625
+ }
3626
+ this._clearExpiredTimeoutId = setTimeout(async () => {
3627
+ await this.prismaClient[this.modelName].deleteMany({
3628
+ where: {
3629
+ expire: {
3630
+ lt: new Date(Date.now() - 36e5)
3631
+ }
3632
+ }
3633
+ });
3634
+ this._clearExpiredHourAgo();
3635
+ }, 3e5);
3636
+ this._clearExpiredTimeoutId.unref();
3637
+ }
3638
+ };
3639
+ module.exports = RateLimiterPrisma;
3640
+ }
3641
+ });
3642
+
3643
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDrizzle.js
3644
+ var require_RateLimiterDrizzle = __commonJS({
3645
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDrizzle.js"(exports, module) {
3646
+ "use strict";
3647
+ var drizzleOperators = null;
3648
+ var CLEANUP_INTERVAL_MS = 3e5;
3649
+ var EXPIRED_THRESHOLD_MS = 36e5;
3650
+ var RateLimiterDrizzleError = class extends Error {
3651
+ constructor(message) {
3652
+ super(message);
3653
+ this.name = "RateLimiterDrizzleError";
3654
+ }
3655
+ };
3656
+ async function loadDrizzleOperators() {
3657
+ if (drizzleOperators) return drizzleOperators;
3658
+ const requiredOperators = ["and", "or", "gt", "lt", "eq", "isNull", "sql"];
3659
+ function getPackageName() {
3660
+ return ["drizzle", "orm"].join("-");
3661
+ }
3662
+ const collectModuleLayers = (mod) => {
3663
+ const layers = [];
3664
+ const seen = /* @__PURE__ */ new Set();
3665
+ let current = mod;
3666
+ while (current && (typeof current === "object" || typeof current === "function") && !seen.has(current)) {
3667
+ layers.push(current);
3668
+ seen.add(current);
3669
+ current = current.default;
3670
+ }
3671
+ return layers;
3672
+ };
3673
+ const importModule = async (specifier, { optional = false } = {}) => {
3674
+ try {
3675
+ return await import(
3676
+ /* @vite-ignore */
3677
+ specifier
3678
+ );
3679
+ } catch (error) {
3680
+ if (optional) {
3681
+ return null;
3682
+ }
3683
+ throw new RateLimiterDrizzleError(
3684
+ error.message || "Failed to import drizzle-orm package."
3685
+ );
3686
+ }
3687
+ };
3688
+ const mainModule = await importModule(`${getPackageName()}`);
3689
+ const sqlModule = await importModule(`${getPackageName()}/sql`, { optional: true });
3690
+ const mainCandidates = collectModuleLayers(mainModule);
3691
+ const sqlCandidates = sqlModule ? collectModuleLayers(sqlModule) : [];
3692
+ const resolvedOperators = {};
3693
+ const missingOperators = [];
3694
+ for (const operatorName of requiredOperators) {
3695
+ const candidates = operatorName === "sql" ? [...sqlCandidates, ...mainCandidates] : mainCandidates;
3696
+ const operator = candidates.map((candidate) => candidate?.[operatorName]).find((value) => typeof value === "function");
3697
+ if (!operator) {
3698
+ missingOperators.push(operatorName);
3699
+ continue;
3700
+ }
3701
+ resolvedOperators[operatorName] = operator;
3702
+ }
3703
+ if (missingOperators.length > 0) {
3704
+ throw new RateLimiterDrizzleError(
3705
+ `Failed to load drizzle-orm operators: missing ${missingOperators.join(", ")}`
3706
+ );
3707
+ }
3708
+ drizzleOperators = resolvedOperators;
3709
+ return drizzleOperators;
3710
+ }
3711
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
3712
+ var RateLimiterRes2 = require_RateLimiterRes();
3713
+ var RateLimiterDrizzle = class extends RateLimiterStoreAbstract {
3714
+ constructor(opts) {
3715
+ super(opts);
3716
+ if (!opts?.schema) {
3717
+ throw new RateLimiterDrizzleError("Drizzle schema is required");
3718
+ }
3719
+ if (!opts?.storeClient) {
3720
+ throw new RateLimiterDrizzleError("Drizzle client is required");
3721
+ }
3722
+ this.schema = opts.schema;
3723
+ this.drizzleClient = opts.storeClient;
3724
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout ?? true;
3725
+ if (this.clearExpiredByTimeout) {
3726
+ this._clearExpiredHourAgo();
3727
+ }
3728
+ }
3729
+ _getRateLimiterRes(rlKey, changedPoints, result) {
3730
+ const res = new RateLimiterRes2();
3731
+ let doc = result;
3732
+ res.isFirstInDuration = doc.points === changedPoints;
3733
+ res.consumedPoints = doc.points;
3734
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
3735
+ res.msBeforeNext = doc.expire !== null ? Math.max(new Date(doc.expire).getTime() - Date.now(), 0) : -1;
3736
+ return res;
3737
+ }
3738
+ async _upsert(key, points, msDuration, forceExpire = false) {
3739
+ if (!this.drizzleClient) {
3740
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3741
+ }
3742
+ const { eq, sql } = await loadDrizzleOperators();
3743
+ const now = /* @__PURE__ */ new Date();
3744
+ const newExpire = msDuration > 0 ? new Date(now.getTime() + msDuration) : null;
3745
+ const query = await this.drizzleClient.transaction(async (tx) => {
3746
+ const [existingRecord] = await tx.select().from(this.schema).where(eq(this.schema.key, key)).limit(1);
3747
+ const shouldUpdateExpire = forceExpire || !existingRecord?.expire || existingRecord?.expire <= now || newExpire === null;
3748
+ const [data] = await tx.insert(this.schema).values({
3749
+ key,
3750
+ points,
3751
+ expire: newExpire
3752
+ }).onConflictDoUpdate({
3753
+ target: this.schema.key,
3754
+ set: {
3755
+ points: !shouldUpdateExpire ? sql`${this.schema.points} + ${points}` : points,
3756
+ ...shouldUpdateExpire && { expire: newExpire }
3757
+ }
3758
+ }).returning();
3759
+ return data;
3760
+ });
3761
+ return query;
3762
+ }
3763
+ async _get(rlKey) {
3764
+ if (!this.drizzleClient) {
3765
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3766
+ }
3767
+ const { and, or, gt, eq, isNull } = await loadDrizzleOperators();
3768
+ const [response] = await this.drizzleClient.select().from(this.schema).where(
3769
+ and(
3770
+ eq(this.schema.key, rlKey),
3771
+ or(gt(this.schema.expire, /* @__PURE__ */ new Date()), isNull(this.schema.expire))
3772
+ )
3773
+ ).limit(1);
3774
+ return response || null;
3775
+ }
3776
+ async _delete(rlKey) {
3777
+ if (!this.drizzleClient) {
3778
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3779
+ }
3780
+ const { eq } = await loadDrizzleOperators();
3781
+ const [result] = await this.drizzleClient.delete(this.schema).where(eq(this.schema.key, rlKey)).returning({ key: this.schema.key });
3782
+ return !!result?.key;
3783
+ }
3784
+ _clearExpiredHourAgo() {
3785
+ if (this._clearExpiredTimeoutId) {
3786
+ clearTimeout(this._clearExpiredTimeoutId);
3787
+ }
3788
+ this._clearExpiredTimeoutId = setTimeout(async () => {
3789
+ try {
3790
+ const { lt } = await loadDrizzleOperators();
3791
+ await this.drizzleClient.delete(this.schema).where(lt(this.schema.expire, new Date(Date.now() - EXPIRED_THRESHOLD_MS)));
3792
+ } catch (error) {
3793
+ console.warn("Failed to clear expired records:", error);
3794
+ }
3795
+ this._clearExpiredHourAgo();
3796
+ }, CLEANUP_INTERVAL_MS);
3797
+ this._clearExpiredTimeoutId.unref();
3798
+ }
3799
+ };
3800
+ module.exports = RateLimiterDrizzle;
3801
+ }
3802
+ });
3803
+
3804
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDrizzleNonAtomic.js
3805
+ var require_RateLimiterDrizzleNonAtomic = __commonJS({
3806
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterDrizzleNonAtomic.js"(exports, module) {
3807
+ "use strict";
3808
+ var drizzleOperators = null;
3809
+ var CLEANUP_INTERVAL_MS = 3e5;
3810
+ var EXPIRED_THRESHOLD_MS = 36e5;
3811
+ var RateLimiterDrizzleError = class extends Error {
3812
+ constructor(message) {
3813
+ super(message);
3814
+ this.name = "RateLimiterDrizzleError";
3815
+ }
3816
+ };
3817
+ async function getDrizzleOperators() {
3818
+ if (drizzleOperators) return drizzleOperators;
3819
+ try {
3820
+ let getPackageName2 = function() {
3821
+ return ["drizzle", "orm"].join("-");
3822
+ };
3823
+ var getPackageName = getPackageName2;
3824
+ const drizzleOrm = await import(`${getPackageName2()}`);
3825
+ const { and, or, gt, lt, eq, isNull, sql } = drizzleOrm.default || drizzleOrm;
3826
+ drizzleOperators = { and, or, gt, lt, eq, isNull, sql };
3827
+ return drizzleOperators;
3828
+ } catch (error) {
3829
+ throw new RateLimiterDrizzleError(
3830
+ "drizzle-orm is not installed. Please install drizzle-orm to use RateLimiterDrizzleNonAtomic."
3831
+ );
3832
+ }
3833
+ }
3834
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
3835
+ var RateLimiterRes2 = require_RateLimiterRes();
3836
+ var RateLimiterDrizzleNonAtomic = class extends RateLimiterStoreAbstract {
3837
+ constructor(opts) {
3838
+ super(opts);
3839
+ if (!opts?.schema) {
3840
+ throw new RateLimiterDrizzleError("Drizzle schema is required");
3841
+ }
3842
+ if (!opts?.storeClient) {
3843
+ throw new RateLimiterDrizzleError("Drizzle client is required");
3844
+ }
3845
+ this.schema = opts.schema;
3846
+ this.drizzleClient = opts.storeClient;
3847
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout ?? true;
3848
+ if (this.clearExpiredByTimeout) {
3849
+ this._clearExpiredHourAgo();
3850
+ }
3851
+ }
3852
+ _getRateLimiterRes(rlKey, changedPoints, result) {
3853
+ const res = new RateLimiterRes2();
3854
+ let doc = result;
3855
+ res.isFirstInDuration = doc.points === changedPoints;
3856
+ res.consumedPoints = doc.points;
3857
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
3858
+ res.msBeforeNext = doc.expire !== null ? Math.max(new Date(doc.expire).getTime() - Date.now(), 0) : -1;
3859
+ return res;
3860
+ }
3861
+ async _upsert(key, points, msDuration, forceExpire = false) {
3862
+ if (!this.drizzleClient) {
3863
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3864
+ }
3865
+ const { eq } = await getDrizzleOperators();
3866
+ const now = /* @__PURE__ */ new Date();
3867
+ const newExpire = msDuration > 0 ? new Date(now.getTime() + msDuration) : null;
3868
+ const [existingRecord] = await this.drizzleClient.select().from(this.schema).where(eq(this.schema.key, key)).limit(1);
3869
+ const shouldUpdateExpire = forceExpire || !existingRecord || !existingRecord.expire || existingRecord.expire <= now || newExpire === null;
3870
+ let newPoints;
3871
+ if (existingRecord && !shouldUpdateExpire) {
3872
+ newPoints = existingRecord.points + points;
3873
+ } else {
3874
+ newPoints = points;
3875
+ }
3876
+ const [data] = await this.drizzleClient.insert(this.schema).values({
3877
+ key,
3878
+ points: newPoints,
3879
+ expire: newExpire
3880
+ }).onConflictDoUpdate({
3881
+ target: this.schema.key,
3882
+ set: {
3883
+ points: newPoints,
3884
+ ...shouldUpdateExpire && { expire: newExpire }
3885
+ }
3886
+ }).returning();
3887
+ return data;
3888
+ }
3889
+ async _get(rlKey) {
3890
+ if (!this.drizzleClient) {
3891
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3892
+ }
3893
+ const { and, or, gt, eq, isNull } = await getDrizzleOperators();
3894
+ const [response] = await this.drizzleClient.select().from(this.schema).where(
3895
+ and(
3896
+ eq(this.schema.key, rlKey),
3897
+ or(gt(this.schema.expire, /* @__PURE__ */ new Date()), isNull(this.schema.expire))
3898
+ )
3899
+ ).limit(1);
3900
+ return response || null;
3901
+ }
3902
+ async _delete(rlKey) {
3903
+ if (!this.drizzleClient) {
3904
+ return Promise.reject(new RateLimiterDrizzleError("Drizzle client is not established"));
3905
+ }
3906
+ const { eq } = await getDrizzleOperators();
3907
+ const [result] = await this.drizzleClient.delete(this.schema).where(eq(this.schema.key, rlKey)).returning({ key: this.schema.key });
3908
+ return !!(result && result.key);
3909
+ }
3910
+ _clearExpiredHourAgo() {
3911
+ if (this._clearExpiredTimeoutId) {
3912
+ clearTimeout(this._clearExpiredTimeoutId);
3913
+ }
3914
+ this._clearExpiredTimeoutId = setTimeout(async () => {
3915
+ try {
3916
+ const { lt } = await getDrizzleOperators();
3917
+ await this.drizzleClient.delete(this.schema).where(lt(this.schema.expire, new Date(Date.now() - EXPIRED_THRESHOLD_MS)));
3918
+ } catch (error) {
3919
+ console.warn("Failed to clear expired records:", error);
3920
+ }
3921
+ this._clearExpiredHourAgo();
3922
+ }, CLEANUP_INTERVAL_MS);
3923
+ this._clearExpiredTimeoutId.unref();
3924
+ }
3925
+ };
3926
+ module.exports = RateLimiterDrizzleNonAtomic;
3927
+ }
3928
+ });
3929
+
3930
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterValkey.js
3931
+ var require_RateLimiterValkey = __commonJS({
3932
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterValkey.js"(exports, module) {
3933
+ "use strict";
3934
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
3935
+ var RateLimiterRes2 = require_RateLimiterRes();
3936
+ var incrTtlLuaScript = `
3937
+ server.call('set', KEYS[1], 0, 'EX', ARGV[2], 'NX')
3938
+ local consumed = server.call('incrby', KEYS[1], ARGV[1])
3939
+ local ttl = server.call('pttl', KEYS[1])
3940
+ return {consumed, ttl}
3941
+ `;
3942
+ var RateLimiterValkey = class extends RateLimiterStoreAbstract {
3943
+ /**
3944
+ *
3945
+ * @param {Object} opts
3946
+ * Defaults {
3947
+ * ... see other in RateLimiterStoreAbstract
3948
+ *
3949
+ * storeClient: ValkeyClient
3950
+ * rejectIfValkeyNotReady: boolean = false - reject / invoke insuranceLimiter immediately when valkey connection is not "ready"
3951
+ * }
3952
+ */
3953
+ constructor(opts) {
3954
+ super(opts);
3955
+ this.client = opts.storeClient;
3956
+ this._rejectIfValkeyNotReady = !!opts.rejectIfValkeyNotReady;
3957
+ this._incrTtlLuaScript = opts.customIncrTtlLuaScript || incrTtlLuaScript;
3958
+ this.client.defineCommand("rlflxIncr", {
3959
+ numberOfKeys: 1,
3960
+ lua: this._incrTtlLuaScript
3961
+ });
3962
+ }
3963
+ /**
3964
+ * Prevent actual valkey call if valkey connection is not ready
3965
+ * @return {boolean}
3966
+ * @private
3967
+ */
3968
+ _isValkeyReady() {
3969
+ if (!this._rejectIfValkeyNotReady) {
3970
+ return true;
3971
+ }
3972
+ return this.client.status === "ready";
3973
+ }
3974
+ _getRateLimiterRes(rlKey, changedPoints, result) {
3975
+ let consumed;
3976
+ let resTtlMs;
3977
+ if (Array.isArray(result[0])) {
3978
+ [[, consumed], [, resTtlMs]] = result;
3979
+ } else {
3980
+ [consumed, resTtlMs] = result;
3981
+ }
3982
+ const res = new RateLimiterRes2();
3983
+ res.consumedPoints = +consumed;
3984
+ res.isFirstInDuration = res.consumedPoints === changedPoints;
3985
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
3986
+ res.msBeforeNext = resTtlMs;
3987
+ return res;
3988
+ }
3989
+ _upsert(rlKey, points, msDuration, forceExpire = false) {
3990
+ if (!this._isValkeyReady()) {
3991
+ throw new Error("Valkey connection is not ready");
3992
+ }
3993
+ const secDuration = Math.floor(msDuration / 1e3);
3994
+ if (forceExpire) {
3995
+ const multi = this.client.multi();
3996
+ if (secDuration > 0) {
3997
+ multi.set(rlKey, points, "EX", secDuration);
3998
+ } else {
3999
+ multi.set(rlKey, points);
4000
+ }
4001
+ return multi.pttl(rlKey).exec();
4002
+ }
4003
+ if (secDuration > 0) {
4004
+ return this.client.rlflxIncr([rlKey, String(points), String(secDuration), String(this.points), String(this.duration)]);
4005
+ }
4006
+ return this.client.multi().incrby(rlKey, points).pttl(rlKey).exec();
4007
+ }
4008
+ _get(rlKey) {
4009
+ if (!this._isValkeyReady()) {
4010
+ throw new Error("Valkey connection is not ready");
4011
+ }
4012
+ return this.client.multi().get(rlKey).pttl(rlKey).exec().then((result) => {
4013
+ const [[, points]] = result;
4014
+ if (points === null) return null;
4015
+ return result;
4016
+ });
4017
+ }
4018
+ _delete(rlKey) {
4019
+ return this.client.del(rlKey).then((result) => result > 0);
4020
+ }
4021
+ };
4022
+ module.exports = RateLimiterValkey;
4023
+ }
4024
+ });
4025
+
4026
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterValkeyGlide.js
4027
+ var require_RateLimiterValkeyGlide = __commonJS({
4028
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterValkeyGlide.js"(exports, module) {
4029
+ "use strict";
4030
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
4031
+ var RateLimiterRes2 = require_RateLimiterRes();
4032
+ var DEFAULT_LIBRARY_NAME = "ratelimiterflexible";
4033
+ var DEFAULT_VALKEY_SCRIPT = `local key = KEYS[1]
4034
+ local pointsToConsume = tonumber(ARGV[1])
4035
+ if tonumber(ARGV[2]) > 0 then
4036
+ server.call('set', key, "0", 'EX', ARGV[2], 'NX')
4037
+ local consumed = server.call('incrby', key, pointsToConsume)
4038
+ local pttl = server.call('pttl', key)
4039
+ return {consumed, pttl}
4040
+ end
4041
+ local consumed = server.call('incrby', key, pointsToConsume)
4042
+ local pttl = server.call('pttl', key)
4043
+ return {consumed, pttl}`;
4044
+ var GET_VALKEY_SCRIPT = `local key = KEYS[1]
4045
+ local value = server.call('get', key)
4046
+ if value == nil then
4047
+ return value
4048
+ end
4049
+ local pttl = server.call('pttl', key)
4050
+ return {tonumber(value), pttl}`;
4051
+ var RateLimiterValkeyGlide = class extends RateLimiterStoreAbstract {
4052
+ /**
4053
+ * Constructor for RateLimiterValkeyGlide
4054
+ *
4055
+ * @param {Object} opts - Configuration options
4056
+ * @param {GlideClient|GlideClusterClient} opts.storeClient - Valkey Glide client instance (required)
4057
+ * @param {number} opts.points - Maximum number of points that can be consumed over duration (required)
4058
+ * @param {number} opts.duration - Duration in seconds before points are reset (required, 0 = never expires)
4059
+ * @param {number} [opts.blockDuration=0] - Duration in seconds that a key will be blocked for if consumed more than points
4060
+ * @param {boolean} [opts.rejectIfValkeyNotReady=false] - Whether to reject requests if Valkey is not ready
4061
+ * @param {boolean} [opts.execEvenly=false] - Delay actions to distribute them evenly over duration
4062
+ * @param {number} [opts.execEvenlyMinDelayMs] - Minimum delay between actions when execEvenly is true
4063
+ * @param {string} [opts.customFunction] - Custom Lua script for rate limiting logic
4064
+ * @param {number} [opts.inMemoryBlockOnConsumed] - Points threshold for in-memory blocking
4065
+ * @param {number} [opts.inMemoryBlockDuration] - Duration in seconds for in-memory blocking
4066
+ * @param {string} [opts.customFunctionLibName] - Custom name for the function library, defaults to 'ratelimiter'.
4067
+ * The name is used to identify the library of the lua function. An custom name should be used only if you
4068
+ * you want to use different libraries for different rate limiters, otherwise it is not needed.
4069
+ * @param {RateLimiterAbstract} [opts.insuranceLimiter] - Backup limiter to use when the primary client fails
4070
+ *
4071
+ * @example
4072
+ * const rateLimiter = new RateLimiterValkeyGlide({
4073
+ * storeClient: glideClient,
4074
+ * points: 5,
4075
+ * duration: 1
4076
+ * });
4077
+ *
4078
+ * @example <caption>With custom Lua function</caption>
4079
+ * const customScript = `local key = KEYS[1]
4080
+ * local pointsToConsume = tonumber(ARGV[1]) or 0
4081
+ * local secDuration = tonumber(ARGV[2]) or 0
4082
+ *
4083
+ * -- Custom implementation
4084
+ * -- ...
4085
+ *
4086
+ * -- Must return exactly two values: [consumed_points, ttl_in_ms]
4087
+ * return {consumed, ttl}`
4088
+ *
4089
+ * const rateLimiter = new RateLimiterValkeyGlide({
4090
+ * storeClient: glideClient,
4091
+ * points: 5,
4092
+ * customFunction: customScript
4093
+ * });
4094
+ *
4095
+ * @example <caption>With insurance limiter</caption>
4096
+ * const rateLimiter = new RateLimiterValkeyGlide({
4097
+ * storeClient: primaryGlideClient,
4098
+ * points: 5,
4099
+ * duration: 2,
4100
+ * insuranceLimiter: new RateLimiterMemory({
4101
+ * points: 5,
4102
+ * duration: 2
4103
+ * })
4104
+ * });
4105
+ *
4106
+ * @description
4107
+ * When providing a custom Lua script via `opts.customFunction`, it must:
4108
+ *
4109
+ * 1. Accept parameters:
4110
+ * - KEYS[1]: The key being rate limited
4111
+ * - ARGV[1]: Points to consume (as string, use tonumber() to convert)
4112
+ * - ARGV[2]: Duration in seconds (as string, use tonumber() to convert)
4113
+ *
4114
+ * 2. Return an array with exactly two elements:
4115
+ * - [0]: Consumed points (number)
4116
+ * - [1]: TTL in milliseconds (number)
4117
+ *
4118
+ * 3. Handle scenarios:
4119
+ * - New key creation: Initialize with expiry for fixed windows
4120
+ * - Key updates: Increment existing counters
4121
+ */
4122
+ constructor(opts) {
4123
+ super(opts);
4124
+ this.client = opts.storeClient;
4125
+ this._scriptLoaded = false;
4126
+ this._getScriptLoaded = false;
4127
+ this._rejectIfValkeyNotReady = !!opts.rejectIfValkeyNotReady;
4128
+ this._luaScript = opts.customFunction || DEFAULT_VALKEY_SCRIPT;
4129
+ this._libraryName = opts.customFunctionLibName || DEFAULT_LIBRARY_NAME;
4130
+ }
4131
+ /**
4132
+ * Ensure scripts are loaded in the Valkey server
4133
+ * @returns {Promise<boolean>} True if scripts are loaded
4134
+ * @private
4135
+ */
4136
+ async _loadScripts() {
4137
+ if (this._scriptLoaded && this._getScriptLoaded) {
4138
+ return true;
4139
+ }
4140
+ if (!this.client) {
4141
+ throw new Error("Valkey client is not set");
4142
+ }
4143
+ const promises = [];
4144
+ if (!this._scriptLoaded) {
4145
+ const script = Buffer.from(`#!lua name=${this._libraryName}
4146
+ local function consume(KEYS, ARGV)
4147
+ ${this._luaScript.trim()}
4148
+ end
4149
+ server.register_function('consume', consume)`);
4150
+ promises.push(this.client.functionLoad(script, { replace: true }));
4151
+ } else promises.push(Promise.resolve(this._libraryName));
4152
+ if (!this._getScriptLoaded) {
4153
+ const script = Buffer.from(`#!lua name=ratelimiter_get
4154
+ local function getValue(KEYS, ARGV)
4155
+ ${GET_VALKEY_SCRIPT.trim()}
4156
+ end
4157
+ server.register_function('getValue', getValue)`);
4158
+ promises.push(this.client.functionLoad(script, { replace: true }));
4159
+ } else promises.push(Promise.resolve("ratelimiter_get"));
4160
+ const results = await Promise.all(promises);
4161
+ this._scriptLoaded = results[0] === this._libraryName;
4162
+ this._getScriptLoaded = results[1] === "ratelimiter_get";
4163
+ if (!this._scriptLoaded || !this._getScriptLoaded) {
4164
+ throw new Error("Valkey connection is not ready, scripts not loaded");
4165
+ }
4166
+ return true;
4167
+ }
4168
+ /**
4169
+ * Update or insert the rate limiter record
4170
+ *
4171
+ * @param {string} rlKey - The rate limiter key
4172
+ * @param {number} pointsToConsume - Points to be consumed
4173
+ * @param {number} msDuration - Duration in milliseconds
4174
+ * @param {boolean} [forceExpire=false] - Whether to force expiration
4175
+ * @param {Object} [options={}] - Additional options
4176
+ * @returns {Promise<Array>} Array containing consumed points and TTL
4177
+ * @private
4178
+ */
4179
+ async _upsert(rlKey, pointsToConsume, msDuration, forceExpire = false, options = {}) {
4180
+ await this._loadScripts();
4181
+ const secDuration = Math.floor(msDuration / 1e3);
4182
+ if (forceExpire) {
4183
+ if (secDuration > 0) {
4184
+ await this.client.set(
4185
+ rlKey,
4186
+ String(pointsToConsume),
4187
+ { expiry: { type: "EX", count: secDuration } }
4188
+ );
4189
+ return [pointsToConsume, secDuration * 1e3];
4190
+ }
4191
+ await this.client.set(rlKey, String(pointsToConsume));
4192
+ return [pointsToConsume, -1];
4193
+ }
4194
+ const result = await this.client.fcall(
4195
+ "consume",
4196
+ [rlKey],
4197
+ [String(pointsToConsume), String(secDuration)]
4198
+ );
4199
+ return result;
4200
+ }
4201
+ /**
4202
+ * Get the rate limiter record
4203
+ *
4204
+ * @param {string} rlKey - The rate limiter key
4205
+ * @param {Object} [options={}] - Additional options
4206
+ * @returns {Promise<Array|null>} Array containing consumed points and TTL, or null if not found
4207
+ * @private
4208
+ */
4209
+ async _get(rlKey, options = {}) {
4210
+ await this._loadScripts();
4211
+ const res = await this.client.fcall("getValue", [rlKey], []);
4212
+ return res.length > 0 ? res : null;
4213
+ }
4214
+ /**
4215
+ * Delete the rate limiter record
4216
+ *
4217
+ * @param {string} rlKey - The rate limiter key
4218
+ * @param {Object} [options={}] - Additional options
4219
+ * @returns {Promise<boolean>} True if successful, false otherwise
4220
+ * @private
4221
+ */
4222
+ async _delete(rlKey, options = {}) {
4223
+ const result = await this.client.del([rlKey]);
4224
+ return result > 0;
4225
+ }
4226
+ /**
4227
+ * Convert raw result to RateLimiterRes object
4228
+ *
4229
+ * @param {string} rlKey - The rate limiter key
4230
+ * @param {number} changedPoints - Points changed in this operation
4231
+ * @param {Array|null} result - Result from Valkey operation
4232
+ * @returns {RateLimiterRes|null} RateLimiterRes object or null if result is null
4233
+ * @private
4234
+ */
4235
+ _getRateLimiterRes(rlKey, changedPoints, result) {
4236
+ if (result === null) {
4237
+ return null;
4238
+ }
4239
+ const res = new RateLimiterRes2();
4240
+ const [consumedPointsStr, pttl] = result;
4241
+ const consumedPoints = Number(consumedPointsStr);
4242
+ res.isFirstInDuration = consumedPoints === changedPoints;
4243
+ res.consumedPoints = consumedPoints;
4244
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
4245
+ res.msBeforeNext = pttl;
4246
+ return res;
4247
+ }
4248
+ /**
4249
+ * Close the rate limiter and release resources
4250
+ * Note: The method won't going to close the Valkey client, as it may be shared with other instances.
4251
+ * @returns {Promise<void>} Promise that resolves when the rate limiter is closed
4252
+ */
4253
+ async close() {
4254
+ if (this._scriptLoaded) {
4255
+ await this.client.functionDelete(this._libraryName);
4256
+ this._scriptLoaded = false;
4257
+ }
4258
+ if (this._getScriptLoaded) {
4259
+ await this.client.functionDelete("ratelimiter_get");
4260
+ this._getScriptLoaded = false;
4261
+ }
4262
+ if (this.insuranceLimiter) {
4263
+ try {
4264
+ await this.insuranceLimiter.close();
4265
+ } catch (e) {
4266
+ }
4267
+ }
4268
+ this.client = null;
4269
+ this._scriptLoaded = false;
4270
+ this._getScriptLoaded = false;
4271
+ this._rejectIfValkeyNotReady = false;
4272
+ this._luaScript = null;
4273
+ this._libraryName = null;
4274
+ this.insuranceLimiter = null;
4275
+ }
4276
+ };
4277
+ module.exports = RateLimiterValkeyGlide;
4278
+ }
4279
+ });
4280
+
4281
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterSQLite.js
4282
+ var require_RateLimiterSQLite = __commonJS({
4283
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterSQLite.js"(exports, module) {
4284
+ "use strict";
4285
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
4286
+ var RateLimiterRes2 = require_RateLimiterRes();
4287
+ var RateLimiterSQLite = class extends RateLimiterStoreAbstract {
4288
+ /**
4289
+ * @callback callback
4290
+ * @param {Object} err
4291
+ *
4292
+ * @param {Object} opts
4293
+ * @param {callback} cb
4294
+ * Defaults {
4295
+ * ... see other in RateLimiterStoreAbstract
4296
+ * storeClient: sqliteClient, // SQLite database instance (sqlite3, better-sqlite3, or knex instance)
4297
+ * storeType: 'sqlite3' | 'better-sqlite3' | 'knex', // Optional, defaults to 'sqlite3'
4298
+ * tableName: 'string',
4299
+ * tableCreated: boolean,
4300
+ * clearExpiredByTimeout: boolean,
4301
+ * }
4302
+ */
4303
+ constructor(opts, cb = null) {
4304
+ super(opts);
4305
+ /**
4306
+ * Internal store type used to determine the SQLite client in use.
4307
+ * It can be one of the following:
4308
+ * - `"sqlite3".
4309
+ * - `"better-sqlite3".
4310
+ *
4311
+ * @type {("sqlite3" | "better-sqlite3" | null)}
4312
+ * @private
4313
+ */
4314
+ __publicField(this, "_internalStoreType", null);
4315
+ this.client = opts.storeClient;
4316
+ this.storeType = opts.storeType || "sqlite3";
4317
+ this.tableName = opts.tableName;
4318
+ this.tableCreated = opts.tableCreated || false;
4319
+ this.clearExpiredByTimeout = opts.clearExpiredByTimeout;
4320
+ this._validateStoreTypes(cb);
4321
+ this._validateStoreClient(cb);
4322
+ this._setInternalStoreType(cb);
4323
+ this._validateTableName(cb);
4324
+ if (!this.tableCreated) {
4325
+ this._createDbAndTable().then(() => {
4326
+ this.tableCreated = true;
4327
+ if (this.clearExpiredByTimeout) this._clearExpiredHourAgo();
4328
+ if (typeof cb === "function") cb();
4329
+ }).catch((err) => {
4330
+ if (typeof cb === "function") cb(err);
4331
+ else throw err;
4332
+ });
4333
+ } else {
4334
+ if (this.clearExpiredByTimeout) this._clearExpiredHourAgo();
4335
+ if (typeof cb === "function") cb();
4336
+ }
4337
+ }
4338
+ _validateStoreTypes(cb) {
4339
+ const validStoreTypes = ["sqlite3", "better-sqlite3", "knex"];
4340
+ if (!validStoreTypes.includes(this.storeType)) {
4341
+ const err = new Error(
4342
+ `storeType must be one of: ${validStoreTypes.join(", ")}`
4343
+ );
4344
+ if (typeof cb === "function") return cb(err);
4345
+ throw err;
4346
+ }
4347
+ }
4348
+ _validateStoreClient(cb) {
4349
+ if (this.storeType === "sqlite3") {
4350
+ if (typeof this.client.run !== "function") {
4351
+ const err = new Error(
4352
+ "storeClient must be an instance of sqlite3.Database when storeType is 'sqlite3' or no storeType was provided"
4353
+ );
4354
+ if (typeof cb === "function") return cb(err);
4355
+ throw err;
4356
+ }
4357
+ } else if (this.storeType === "better-sqlite3") {
4358
+ if (typeof this.client.prepare !== "function" || typeof this.client.run !== "undefined") {
4359
+ const err = new Error(
4360
+ "storeClient must be an instance of better-sqlite3.Database when storeType is 'better-sqlite3'"
4361
+ );
4362
+ if (typeof cb === "function") return cb(err);
4363
+ throw err;
4364
+ }
4365
+ } else if (this.storeType === "knex") {
4366
+ if (typeof this.client.raw !== "function") {
4367
+ const err = new Error(
4368
+ "storeClient must be an instance of Knex when storeType is 'knex'"
4369
+ );
4370
+ if (typeof cb === "function") return cb(err);
4371
+ throw err;
4372
+ }
4373
+ }
4374
+ }
4375
+ _setInternalStoreType(cb) {
4376
+ if (this.storeType === "knex") {
4377
+ const knexClientType = this.client.client.config.client;
4378
+ if (knexClientType === "sqlite3") {
4379
+ this._internalStoreType = "sqlite3";
4380
+ } else if (knexClientType === "better-sqlite3") {
4381
+ this._internalStoreType = "better-sqlite3";
4382
+ } else {
4383
+ const err = new Error(
4384
+ "Knex must be configured with 'sqlite3' or 'better-sqlite3' for RateLimiterSQLite"
4385
+ );
4386
+ if (typeof cb === "function") return cb(err);
4387
+ throw err;
4388
+ }
4389
+ } else {
4390
+ this._internalStoreType = this.storeType;
4391
+ }
4392
+ }
4393
+ _validateTableName(cb) {
4394
+ if (!/^[A-Za-z0-9_]*$/.test(this.tableName)) {
4395
+ const err = new Error("Table name must contain only letters and numbers");
4396
+ if (typeof cb === "function") return cb(err);
4397
+ throw err;
4398
+ }
4399
+ }
4400
+ /**
4401
+ * Acquires the database connection based on the storeType.
4402
+ * @returns {Promise<Object>} The database client or connection
4403
+ */
4404
+ async _getConnection() {
4405
+ if (this.storeType === "knex") {
4406
+ return this.client.client.acquireConnection();
4407
+ }
4408
+ return this.client;
4409
+ }
4410
+ /**
4411
+ * Releases the database connection if necessary.
4412
+ * @param {Object} conn The database client or connection
4413
+ */
4414
+ _releaseConnection(conn) {
4415
+ if (this.storeType === "knex") {
4416
+ this.client.client.releaseConnection(conn);
4417
+ }
4418
+ }
4419
+ async _createDbAndTable() {
4420
+ const conn = await this._getConnection();
4421
+ try {
4422
+ switch (this._internalStoreType) {
4423
+ case "sqlite3":
4424
+ await new Promise((resolve, reject) => {
4425
+ conn.run(
4426
+ this._getCreateTableSQL(),
4427
+ (err) => err ? reject(err) : resolve()
4428
+ );
4429
+ });
4430
+ break;
4431
+ case "better-sqlite3":
4432
+ conn.prepare(this._getCreateTableSQL()).run();
4433
+ break;
4434
+ default:
4435
+ throw new Error("Unsupported internalStoreType");
4436
+ }
4437
+ } finally {
4438
+ this._releaseConnection(conn);
4439
+ }
4440
+ }
4441
+ _getCreateTableSQL() {
4442
+ return `CREATE TABLE IF NOT EXISTS ${this.tableName} (
4443
+ key TEXT PRIMARY KEY,
4444
+ points INTEGER NOT NULL DEFAULT 0,
4445
+ expire INTEGER
4446
+ )`;
4447
+ }
4448
+ _clearExpiredHourAgo() {
4449
+ if (this._clearExpiredTimeoutId) clearTimeout(this._clearExpiredTimeoutId);
4450
+ this._clearExpiredTimeoutId = setTimeout(() => {
4451
+ this.clearExpired(Date.now() - 36e5).then(() => this._clearExpiredHourAgo());
4452
+ }, 3e5);
4453
+ this._clearExpiredTimeoutId.unref();
4454
+ }
4455
+ async clearExpired(nowMs) {
4456
+ const sql = `DELETE FROM ${this.tableName} WHERE expire < ?`;
4457
+ const conn = await this._getConnection();
4458
+ try {
4459
+ switch (this._internalStoreType) {
4460
+ case "sqlite3":
4461
+ await new Promise((resolve, reject) => {
4462
+ conn.run(sql, [nowMs], (err) => err ? reject(err) : resolve());
4463
+ });
4464
+ break;
4465
+ case "better-sqlite3":
4466
+ conn.prepare(sql).run(nowMs);
4467
+ break;
4468
+ default:
4469
+ throw new Error("Unsupported internalStoreType");
4470
+ }
4471
+ } finally {
4472
+ this._releaseConnection(conn);
4473
+ }
4474
+ }
4475
+ _getRateLimiterRes(rlKey, changedPoints, result) {
4476
+ const res = new RateLimiterRes2();
4477
+ res.isFirstInDuration = changedPoints === result.points;
4478
+ res.consumedPoints = res.isFirstInDuration ? changedPoints : result.points;
4479
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
4480
+ res.msBeforeNext = result.expire ? Math.max(result.expire - Date.now(), 0) : -1;
4481
+ return res;
4482
+ }
4483
+ async _upsertTransactionSQLite3(conn, upsertQuery, upsertParams) {
4484
+ return await new Promise((resolve, reject) => {
4485
+ conn.serialize(() => {
4486
+ conn.run("SAVEPOINT rate_limiter_trx;", (err) => {
4487
+ if (err) return reject(err);
4488
+ conn.get(upsertQuery, upsertParams, (err2, row) => {
4489
+ if (err2) {
4490
+ conn.run(
4491
+ "ROLLBACK TO SAVEPOINT rate_limiter_trx;",
4492
+ () => reject(err2)
4493
+ );
4494
+ return;
4495
+ }
4496
+ conn.run("RELEASE SAVEPOINT rate_limiter_trx;", () => resolve(row));
4497
+ });
4498
+ });
4499
+ });
4500
+ });
4501
+ }
4502
+ async _upsertTransactionBetterSQLite3(conn, upsertQuery, upsertParams) {
4503
+ return conn.transaction(
4504
+ () => conn.prepare(upsertQuery).get(...upsertParams)
4505
+ )();
4506
+ }
4507
+ async _upsertTransaction(rlKey, points, msDuration, forceExpire) {
4508
+ const dateNow = Date.now();
4509
+ const newExpire = msDuration > 0 ? dateNow + msDuration : null;
4510
+ const upsertQuery = forceExpire ? `INSERT OR REPLACE INTO ${this.tableName} (key, points, expire) VALUES (?, ?, ?) RETURNING points, expire` : `INSERT INTO ${this.tableName} (key, points, expire)
4511
+ VALUES (?, ?, ?)
4512
+ ON CONFLICT(key) DO UPDATE SET
4513
+ points = CASE WHEN expire IS NULL OR expire > ? THEN points + excluded.points ELSE excluded.points END,
4514
+ expire = CASE WHEN expire IS NULL OR expire > ? THEN expire ELSE excluded.expire END
4515
+ RETURNING points, expire`;
4516
+ const upsertParams = forceExpire ? [rlKey, points, newExpire] : [rlKey, points, newExpire, dateNow, dateNow];
4517
+ const conn = await this._getConnection();
4518
+ try {
4519
+ switch (this._internalStoreType) {
4520
+ case "sqlite3":
4521
+ return this._upsertTransactionSQLite3(
4522
+ conn,
4523
+ upsertQuery,
4524
+ upsertParams
4525
+ );
4526
+ case "better-sqlite3":
4527
+ return this._upsertTransactionBetterSQLite3(
4528
+ conn,
4529
+ upsertQuery,
4530
+ upsertParams
4531
+ );
4532
+ default:
4533
+ throw new Error("Unsupported internalStoreType");
4534
+ }
4535
+ } finally {
4536
+ this._releaseConnection(conn);
4537
+ }
4538
+ }
4539
+ _upsert(rlKey, points, msDuration, forceExpire = false) {
4540
+ if (!this.tableCreated) {
4541
+ return Promise.reject(new Error("Table is not created yet"));
4542
+ }
4543
+ return this._upsertTransaction(rlKey, points, msDuration, forceExpire);
4544
+ }
4545
+ async _get(rlKey) {
4546
+ const sql = `SELECT points, expire FROM ${this.tableName} WHERE key = ? AND (expire > ? OR expire IS NULL)`;
4547
+ const now = Date.now();
4548
+ const conn = await this._getConnection();
4549
+ try {
4550
+ switch (this._internalStoreType) {
4551
+ case "sqlite3":
4552
+ return await new Promise((resolve, reject) => {
4553
+ conn.get(
4554
+ sql,
4555
+ [rlKey, now],
4556
+ (err, row) => err ? reject(err) : resolve(row || null)
4557
+ );
4558
+ });
4559
+ case "better-sqlite3":
4560
+ return conn.prepare(sql).get(rlKey, now) || null;
4561
+ default:
4562
+ throw new Error("Unsupported internalStoreType");
4563
+ }
4564
+ } finally {
4565
+ this._releaseConnection(conn);
4566
+ }
4567
+ }
4568
+ async _delete(rlKey) {
4569
+ if (!this.tableCreated) {
4570
+ return Promise.reject(new Error("Table is not created yet"));
4571
+ }
4572
+ const sql = `DELETE FROM ${this.tableName} WHERE key = ?`;
4573
+ const conn = await this._getConnection();
4574
+ try {
4575
+ switch (this._internalStoreType) {
4576
+ case "sqlite3":
4577
+ return await new Promise((resolve, reject) => {
4578
+ conn.run(sql, [rlKey], function(err) {
4579
+ if (err) reject(err);
4580
+ else resolve(this.changes > 0);
4581
+ });
4582
+ });
4583
+ case "better-sqlite3":
4584
+ const result = conn.prepare(sql).run(rlKey);
4585
+ return result.changes > 0;
4586
+ default:
4587
+ throw new Error("Unsupported internalStoreType");
4588
+ }
4589
+ } finally {
4590
+ this._releaseConnection(conn);
4591
+ }
4592
+ }
4593
+ };
4594
+ module.exports = RateLimiterSQLite;
4595
+ }
4596
+ });
4597
+
4598
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterEtcdTransactionFailedError.js
4599
+ var require_RateLimiterEtcdTransactionFailedError = __commonJS({
4600
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterEtcdTransactionFailedError.js"(exports, module) {
4601
+ "use strict";
4602
+ module.exports = class RateLimiterEtcdTransactionFailedError extends Error {
4603
+ constructor(message) {
4604
+ super();
4605
+ if (Error.captureStackTrace) {
4606
+ Error.captureStackTrace(this, this.constructor);
4607
+ }
4608
+ this.name = "RateLimiterEtcdTransactionFailedError";
4609
+ this.message = message;
4610
+ }
4611
+ };
4612
+ }
4613
+ });
4614
+
4615
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterSetupError.js
4616
+ var require_RateLimiterSetupError = __commonJS({
4617
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/component/RateLimiterSetupError.js"(exports, module) {
4618
+ "use strict";
4619
+ module.exports = class RateLimiterSetupError extends Error {
4620
+ constructor(message) {
4621
+ super();
4622
+ if (Error.captureStackTrace) {
4623
+ Error.captureStackTrace(this, this.constructor);
4624
+ }
4625
+ this.name = "RateLimiterSetupError";
4626
+ this.message = message;
4627
+ }
4628
+ };
4629
+ }
4630
+ });
4631
+
4632
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterEtcdNonAtomic.js
4633
+ var require_RateLimiterEtcdNonAtomic = __commonJS({
4634
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterEtcdNonAtomic.js"(exports, module) {
4635
+ "use strict";
4636
+ var RateLimiterStoreAbstract = require_RateLimiterStoreAbstract();
4637
+ var RateLimiterRes2 = require_RateLimiterRes();
4638
+ var RateLimiterSetupError = require_RateLimiterSetupError();
4639
+ var RateLimiterEtcdNonAtomic = class extends RateLimiterStoreAbstract {
4640
+ /**
4641
+ * @param {Object} opts
4642
+ */
4643
+ constructor(opts) {
4644
+ super(opts);
4645
+ if (!opts.storeClient) {
4646
+ throw new RateLimiterSetupError('You need to set the option "storeClient" to an instance of class "Etcd3".');
4647
+ }
4648
+ this.client = opts.storeClient;
4649
+ }
4650
+ /**
4651
+ * Get RateLimiterRes object filled depending on storeResult, which specific for exact store.
4652
+ */
4653
+ _getRateLimiterRes(rlKey, changedPoints, result) {
4654
+ const res = new RateLimiterRes2();
4655
+ res.isFirstInDuration = changedPoints === result.points;
4656
+ res.consumedPoints = res.isFirstInDuration ? changedPoints : result.points;
4657
+ res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
4658
+ res.msBeforeNext = result.expire ? Math.max(result.expire - Date.now(), 0) : -1;
4659
+ return res;
4660
+ }
4661
+ /**
4662
+ * Resolve with object used for {@link _getRateLimiterRes} to generate {@link RateLimiterRes}.
4663
+ */
4664
+ async _upsert(rlKey, points, msDuration, forceExpire = false) {
4665
+ const expire = msDuration > 0 ? Date.now() + msDuration : null;
4666
+ let newValue = { points, expire };
4667
+ if (forceExpire) {
4668
+ await this.client.put(rlKey).value(JSON.stringify(newValue));
4669
+ } else {
4670
+ const oldValue = await this._get(rlKey);
4671
+ newValue = { points: (oldValue !== null ? oldValue.points : 0) + points, expire };
4672
+ await this.client.put(rlKey).value(JSON.stringify(newValue));
4673
+ }
4674
+ return newValue;
4675
+ }
4676
+ /**
4677
+ * Resolve with raw result from Store OR null if rlKey is not set
4678
+ * or Reject with error
4679
+ */
4680
+ async _get(rlKey) {
4681
+ return this.client.get(rlKey).string().then((result) => result !== null ? JSON.parse(result) : null);
4682
+ }
4683
+ /**
4684
+ * Resolve with true OR false if rlKey doesn't exist.
4685
+ * or Reject with error.
4686
+ */
4687
+ async _delete(rlKey) {
4688
+ return this.client.delete().key(rlKey).then((result) => result.deleted === "1");
4689
+ }
4690
+ };
4691
+ module.exports = RateLimiterEtcdNonAtomic;
4692
+ }
4693
+ });
4694
+
4695
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterEtcd.js
4696
+ var require_RateLimiterEtcd = __commonJS({
4697
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/lib/RateLimiterEtcd.js"(exports, module) {
4698
+ "use strict";
4699
+ var RateLimiterEtcdTransactionFailedError = require_RateLimiterEtcdTransactionFailedError();
4700
+ var RateLimiterEtcdNonAtomic = require_RateLimiterEtcdNonAtomic();
4701
+ var MAX_TRANSACTION_TRIES = 5;
4702
+ var RateLimiterEtcd = class extends RateLimiterEtcdNonAtomic {
4703
+ /**
4704
+ * Resolve with object used for {@link _getRateLimiterRes} to generate {@link RateLimiterRes}.
4705
+ */
4706
+ async _upsert(rlKey, points, msDuration, forceExpire = false) {
4707
+ const expire = msDuration > 0 ? Date.now() + msDuration : null;
4708
+ let newValue = { points, expire };
4709
+ let oldValue;
4710
+ if (forceExpire) {
4711
+ await this.client.put(rlKey).value(JSON.stringify(newValue));
4712
+ } else {
4713
+ const added = await this.client.if(rlKey, "Version", "===", "0").then(this.client.put(rlKey).value(JSON.stringify(newValue))).commit().then((result) => !!result.succeeded);
4714
+ if (!added) {
4715
+ let success = false;
4716
+ for (let i = 0; i < MAX_TRANSACTION_TRIES; i++) {
4717
+ oldValue = await this._get(rlKey);
4718
+ newValue = { points: oldValue.points + points, expire };
4719
+ success = await this.client.if(rlKey, "Value", "===", JSON.stringify(oldValue)).then(this.client.put(rlKey).value(JSON.stringify(newValue))).commit().then((result) => !!result.succeeded);
4720
+ if (success) {
4721
+ break;
4722
+ }
4723
+ }
4724
+ if (!success) {
4725
+ throw new RateLimiterEtcdTransactionFailedError("Could not set new value in a transaction.");
4726
+ }
4727
+ }
4728
+ }
4729
+ return newValue;
4730
+ }
4731
+ };
4732
+ module.exports = RateLimiterEtcd;
4733
+ }
4734
+ });
4735
+
4736
+ // ../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/index.js
4737
+ var require_rate_limiter_flexible = __commonJS({
4738
+ "../../node_modules/.pnpm/rate-limiter-flexible@11.2.1/node_modules/rate-limiter-flexible/index.js"(exports, module) {
4739
+ "use strict";
4740
+ var RateLimiterRedis = require_RateLimiterRedis();
4741
+ var RateLimiterRedisNonAtomic = require_RateLimiterRedisNonAtomic();
4742
+ var RateLimiterMongo = require_RateLimiterMongo();
4743
+ var RateLimiterMySQL = require_RateLimiterMySQL();
4744
+ var RateLimiterPostgres2 = require_RateLimiterPostgres();
4745
+ var { RateLimiterClusterMaster, RateLimiterClusterMasterPM2, RateLimiterCluster } = require_RateLimiterCluster();
4746
+ var RateLimiterMemory2 = require_RateLimiterMemory();
4747
+ var RateLimiterMemcache = require_RateLimiterMemcache();
4748
+ var RLWrapperBlackAndWhite = require_RLWrapperBlackAndWhite();
4749
+ var RLWrapperTimeouts = require_RLWrapperTimeouts();
4750
+ var RateLimiterUnion = require_RateLimiterUnion();
4751
+ var RateLimiterQueue = require_RateLimiterQueue();
4752
+ var BurstyRateLimiter = require_BurstyRateLimiter();
4753
+ var RateLimiterRes2 = require_RateLimiterRes();
4754
+ var RateLimiterCompatibleAbstract = require_RateLimiterCompatibleAbstract();
4755
+ var RateLimiterDynamo = require_RateLimiterDynamo();
4756
+ var RateLimiterPrisma = require_RateLimiterPrisma();
4757
+ var RateLimiterDrizzle = require_RateLimiterDrizzle();
4758
+ var RateLimiterDrizzleNonAtomic = require_RateLimiterDrizzleNonAtomic();
4759
+ var RateLimiterValkey = require_RateLimiterValkey();
4760
+ var RateLimiterValkeyGlide = require_RateLimiterValkeyGlide();
4761
+ var RateLimiterSQLite = require_RateLimiterSQLite();
4762
+ var RateLimiterEtcd = require_RateLimiterEtcd();
4763
+ var RateLimiterEtcdNonAtomic = require_RateLimiterEtcdNonAtomic();
4764
+ var RateLimiterQueueError = require_RateLimiterQueueError();
4765
+ var RateLimiterEtcdTransactionFailedError = require_RateLimiterEtcdTransactionFailedError();
4766
+ module.exports = {
4767
+ RateLimiterRedis,
4768
+ RateLimiterRedisNonAtomic,
4769
+ RateLimiterMongo,
4770
+ RateLimiterMySQL,
4771
+ RateLimiterPostgres: RateLimiterPostgres2,
4772
+ RateLimiterMemory: RateLimiterMemory2,
4773
+ RateLimiterMemcache,
4774
+ RateLimiterClusterMaster,
4775
+ RateLimiterClusterMasterPM2,
4776
+ RateLimiterCluster,
4777
+ RLWrapperBlackAndWhite,
4778
+ RLWrapperTimeouts,
4779
+ RateLimiterUnion,
4780
+ RateLimiterQueue,
4781
+ BurstyRateLimiter,
4782
+ RateLimiterRes: RateLimiterRes2,
4783
+ RateLimiterCompatibleAbstract,
4784
+ RateLimiterDynamo,
4785
+ RateLimiterPrisma,
4786
+ RateLimiterValkey,
4787
+ RateLimiterValkeyGlide,
4788
+ RateLimiterSQLite,
4789
+ RateLimiterEtcd,
4790
+ RateLimiterDrizzle,
4791
+ RateLimiterDrizzleNonAtomic,
4792
+ RateLimiterEtcdNonAtomic,
4793
+ RateLimiterQueueError,
4794
+ RateLimiterEtcdTransactionFailedError
4795
+ };
4796
+ }
4797
+ });
4798
+
4799
+ // src/rate-limit.ts
4800
+ var import_rate_limiter_flexible = __toESM(require_rate_limiter_flexible(), 1);
4801
+
4802
+ // src/errors.ts
4803
+ var ApiError = class extends Error {
4804
+ constructor(status, code, message, details) {
4805
+ super(message);
4806
+ this.name = "ApiError";
4807
+ this.status = status;
4808
+ this.code = code;
4809
+ this.details = details;
4810
+ }
4811
+ };
4812
+ function errorResponse(error) {
4813
+ const body = { error: { code: error.code, message: error.message } };
4814
+ if (error.details !== void 0) body.error.details = error.details;
4815
+ return new Response(JSON.stringify(body), {
4816
+ status: error.status,
4817
+ headers: { "content-type": "application/json; charset=utf-8" }
4818
+ });
4819
+ }
4820
+
4821
+ // src/middleware.ts
4822
+ function withHeaders(response, set) {
4823
+ try {
4824
+ set(response.headers);
4825
+ return response;
4826
+ } catch {
4827
+ const copy = new Response(response.body, response);
4828
+ set(copy.headers);
4829
+ return copy;
4830
+ }
4831
+ }
4832
+
4833
+ // src/rate-limit.ts
4834
+ function memoryRateLimitStore() {
4835
+ return storeOf(async (limit, windowSeconds) => new import_rate_limiter_flexible.RateLimiterMemory({ points: limit, duration: windowSeconds }));
4836
+ }
4837
+ function postgresRateLimitStore(client, options = {}) {
4838
+ const { table = "rate_limits", schema, createTable = true } = options;
4839
+ const storeClient = { query: (q) => client.query(q.text, q.values) };
4840
+ let hits = 0;
4841
+ return storeOf(
4842
+ (limit, windowSeconds) => new Promise((resolve, reject) => {
4843
+ const limiter = new import_rate_limiter_flexible.RateLimiterPostgres(
4844
+ {
4845
+ storeClient,
4846
+ storeType: "pool",
4847
+ tableName: table,
4848
+ schemaName: schema,
4849
+ tableCreated: !createTable,
4850
+ clearExpiredByTimeout: false,
4851
+ points: limit,
4852
+ duration: windowSeconds,
4853
+ insuranceLimiter: new import_rate_limiter_flexible.RateLimiterMemory({ points: limit, duration: windowSeconds })
4854
+ },
4855
+ // Called inside the constructor when the table exists already: resolve once it returned.
4856
+ (error) => error ? reject(error) : queueMicrotask(() => resolve(limiter))
4857
+ );
4858
+ }),
4859
+ (limiter) => {
4860
+ const sweep = limiter;
4861
+ if (++hits % 1e3 === 0) void sweep.clearExpired(Date.now() - 36e5).catch(() => {
4862
+ });
4863
+ }
4864
+ );
4865
+ }
4866
+ function storeOf(make, onHit) {
4867
+ const limiters = /* @__PURE__ */ new Map();
4868
+ return {
4869
+ async hit(key, limit, windowSeconds) {
4870
+ const id = `${limit}/${windowSeconds}`;
4871
+ let pending = limiters.get(id);
4872
+ if (!pending) {
4873
+ limiters.set(id, pending = make(limit, windowSeconds));
4874
+ pending.catch(() => limiters.delete(id));
4875
+ }
4876
+ const limiter = await pending;
4877
+ onHit?.(limiter);
4878
+ try {
4879
+ const res = await limiter.consume(key);
4880
+ return { allowed: true, remaining: res.remainingPoints, resetMs: res.msBeforeNext };
4881
+ } catch (thrown) {
4882
+ if (thrown instanceof import_rate_limiter_flexible.RateLimiterRes) return { allowed: false, remaining: 0, resetMs: thrown.msBeforeNext };
4883
+ throw thrown;
4884
+ }
4885
+ }
4886
+ };
4887
+ }
4888
+ var ADDRESSES = /* @__PURE__ */ Symbol.for("fluixi.clientAddress");
4889
+ var sharedMemory = memoryRateLimitStore();
4890
+ var created = 0;
4891
+ function clientAddressOf(request) {
4892
+ return globalThis[ADDRESSES]?.get(request);
4893
+ }
4894
+ function rateLimit(options) {
4895
+ const { match, methods, limit, window, key = clientAddressOf, store = sharedMemory } = options;
4896
+ const applies = matcher(match);
4897
+ const methodSet = methods && new Set(methods.map((m) => m.toUpperCase()));
4898
+ const bucket = options.name ?? `limit${++created}`;
4899
+ return async (request, next) => {
4900
+ if (methodSet && !methodSet.has(request.method)) return next();
4901
+ if (!applies(request)) return next();
4902
+ const who = await key(request);
4903
+ if (!who) return next();
4904
+ const { allowed, remaining, resetMs } = await store.hit(`${bucket}:${who}`, limit, window);
4905
+ const reset = String(Math.ceil(resetMs / 1e3));
4906
+ const set = (headers) => {
4907
+ headers.set("ratelimit-limit", String(limit));
4908
+ headers.set("ratelimit-remaining", String(remaining));
4909
+ headers.set("ratelimit-reset", reset);
4910
+ };
4911
+ if (!allowed) {
4912
+ const refused = errorResponse(new ApiError(429, "rate_limited", "Too many requests. Try again later."));
4913
+ refused.headers.set("retry-after", reset);
4914
+ set(refused.headers);
4915
+ return refused;
4916
+ }
4917
+ return withHeaders(await next(), set);
4918
+ };
4919
+ }
4920
+ function matcher(match) {
4921
+ if (!match) return () => true;
4922
+ if (typeof match === "function") return match;
4923
+ const exact = new Set(match.filter((p) => !p.endsWith("/*")));
4924
+ const prefixes = match.filter((p) => p.endsWith("/*")).map((p) => p.slice(0, -1));
4925
+ return (request) => {
4926
+ const { pathname } = new URL(request.url);
4927
+ return exact.has(pathname) || prefixes.some((p) => pathname.startsWith(p));
4928
+ };
4929
+ }
4930
+ export {
4931
+ clientAddressOf,
4932
+ memoryRateLimitStore,
4933
+ postgresRateLimitStore,
4934
+ rateLimit
4935
+ };