@fefade/common 1.0.4 → 1.0.6

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