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