rate-limiter-flexible 10.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CONTEXT.md CHANGED
@@ -30,7 +30,7 @@ const { RateLimiterMemory } = require("rate-limiter-flexible");
30
30
  ## Core Concepts
31
31
 
32
32
  - **Atomic increments** — all operations use atomic increments to prevent race conditions.
33
- - **Fixed window** algorithm — much faster than rolling window. See [comparative benchmarks](https://github.com/animir/node-rate-limiter-flexible/wiki/Comparative-benchmarks).
33
+ - **Enhanced fixed window** algorithm — starts counting from the moment a request is received, diversifying rate limit reset times across clients. Much faster than rolling window. See [comparative benchmarks](https://github.com/animir/node-rate-limiter-flexible/wiki/Comparative-benchmarks).
34
34
  - **Zero production dependencies.**
35
35
  - **Deno compatible** — see [example gist](https://gist.github.com/animir/d06ca92931677f330d3f2d4c6c3108e4).
36
36
  - **Browser compatible** — `RateLimiterMemory` works in the browser.
@@ -45,8 +45,8 @@ Options can be changed at runtime: `rateLimiter.points = 50`, `rateLimiter.durat
45
45
 
46
46
  | Option | Default | Description |
47
47
  |--------|---------|-------------|
48
- | `points` | `4` | Max points consumable over `duration`. |
49
- | `duration` | `1` | Seconds before points reset (from first consume). `0` = never expire. |
48
+ | `points` | **Required** | Max points consumable over `duration`. Must be a number. |
49
+ | `duration` | **Required** | Seconds before points reset (from first consume). Must be >= 0. `0` = never expire. |
50
50
  | `keyPrefix` | `'rlflx'` | Unique prefix per limiter to avoid key collisions. For some stores, used as table/collection name. |
51
51
  | `blockDuration` | `0` | If >0, block key for this many seconds once points exhausted. |
52
52
  | `storeClient` | — | Required for store limiters. Accepts `@valkey/valkey-glide`, `iovalkey`, `redis`, `ioredis`, `memcached`, `mongodb`, `pg`, `mysql2`, `mysql`, Sequelize, TypeORM, Knex, or any related pool/connection. |
@@ -156,9 +156,9 @@ const headers = {
156
156
  | Limiter | Description |
157
157
  |---------|-------------|
158
158
  | `BurstyRateLimiter` | Combines two limiters: primary + burst allowance. |
159
- | `RateLimiterUnion` | Consume from multiple limiters simultaneously. Only `consume` method. |
159
+ | `RateLimiterUnion` | Consume from multiple limiters simultaneously. Only `consume` method. Accepts any `RateLimiterAbstract` or `RateLimiterCompatibleAbstract` instance. |
160
160
  | `RateLimiterQueue` | Queue actions and execute at controlled rate (FIFO). |
161
- | `RLWrapperBlackAndWhite` | Wrap any limiter with black/white IP lists. |
161
+ | `RLWrapperBlackAndWhite` | Wrap any limiter with black/white IP lists. Can be used as `insuranceLimiter`, in `RLWrapperTimeouts`, or `RateLimiterUnion`. |
162
162
  | `RLWrapperTimeouts` | Wrap any limiter with custom timeout behavior. |
163
163
 
164
164
  ## Common Patterns
@@ -469,3 +469,11 @@ Any new limiter with storage must extend `RateLimiterStoreAbstract` and implemen
469
469
  - `_upsert` — atomic or non-atomic increment. Must support `forceExpire` mode. If non-atomic, suffix class with `NonAtomic` (e.g. `RateLimiterRedisNonAtomic`).
470
470
  - `_get` — return raw data by key or `null`.
471
471
  - `_delete` — delete key data, return `true`/`false`.
472
+
473
+ ## Creating Custom Wrappers
474
+
475
+ For wrapper classes that don't need full `RateLimiterAbstract` functionality (like `points`, `duration`, etc.), extend `RateLimiterCompatibleAbstract` instead. This lightweight abstract class requires implementing:
476
+ - `consume`, `penalty`, `reward`, `get`, `set`, `block`, `delete` methods
477
+ - `blockDuration` and `execEvenly` getters/setters (if not used, empty no-op implementations can be provided)
478
+
479
+ Classes extending `RateLimiterCompatibleAbstract` can be used anywhere `RateLimiterAbstract` is accepted: as `insuranceLimiter`, in `RLWrapperTimeouts`, `RateLimiterUnion`, etc. See `RLWrapperBlackAndWhite` for an example implementation.
package/README.md CHANGED
@@ -32,8 +32,7 @@ Memory limiter also works in the browser.
32
32
 
33
33
  **Deno compatible** See [this example](https://gist.github.com/animir/d06ca92931677f330d3f2d4c6c3108e4)
34
34
 
35
- It uses a **fixed window**, as it is much faster than a rolling window.
36
- [See comparative benchmarks with other libraries here](https://github.com/animir/node-rate-limiter-flexible/wiki/Comparative-benchmarks)
35
+ The enhanced fixed window algorithm starts counting from the moment a request is received, diversifying rate limit reset times across clients.
37
36
 
38
37
  ## Installation
39
38
 
@@ -227,4 +226,6 @@ It has to implement 4 methods:
227
226
 
228
227
  All other methods depend on the store. See `RateLimiterRedis` or `RateLimiterPostgres` for examples.
229
228
 
229
+ For wrapper classes that don't need full `RateLimiterAbstract` functionality, extend `RateLimiterCompatibleAbstract` instead. It requires implementing `consume`, `penalty`, `reward`, `get`, `set`, `block`, `delete` methods and `blockDuration`/`execEvenly` getters/setters. If the wrapper doesn't use `blockDuration` or `execEvenly`, empty no-op implementations can be provided. See `RLWrapperBlackAndWhite` for an example.
230
+
230
231
  Note: all changes should be covered by tests.
package/index.js CHANGED
@@ -12,6 +12,7 @@ const RateLimiterUnion = require('./lib/RateLimiterUnion');
12
12
  const RateLimiterQueue = require('./lib/RateLimiterQueue');
13
13
  const BurstyRateLimiter = require('./lib/BurstyRateLimiter');
14
14
  const RateLimiterRes = require('./lib/RateLimiterRes');
15
+ const RateLimiterCompatibleAbstract = require('./lib/RateLimiterCompatibleAbstract');
15
16
  const RateLimiterDynamo = require('./lib/RateLimiterDynamo');
16
17
  const RateLimiterPrisma = require('./lib/RateLimiterPrisma');
17
18
  const RateLimiterDrizzle = require('./lib/RateLimiterDrizzle');
@@ -41,6 +42,7 @@ module.exports = {
41
42
  RateLimiterQueue,
42
43
  BurstyRateLimiter,
43
44
  RateLimiterRes,
45
+ RateLimiterCompatibleAbstract,
44
46
  RateLimiterDynamo,
45
47
  RateLimiterPrisma,
46
48
  RateLimiterValkey,
@@ -1,7 +1,9 @@
1
1
  const RateLimiterRes = require('./RateLimiterRes');
2
+ const RateLimiterCompatibleAbstract = require('./RateLimiterCompatibleAbstract');
2
3
 
3
- module.exports = class RLWrapperBlackAndWhite {
4
+ module.exports = class RLWrapperBlackAndWhite extends RateLimiterCompatibleAbstract {
4
5
  constructor(opts = {}) {
6
+ super();
5
7
  this.limiter = opts.limiter;
6
8
  this.blackList = opts.blackList;
7
9
  this.whiteList = opts.whiteList;
@@ -22,6 +24,26 @@ module.exports = class RLWrapperBlackAndWhite {
22
24
  this._limiter = value;
23
25
  }
24
26
 
27
+ get keyPrefix() {
28
+ return this.limiter.keyPrefix;
29
+ }
30
+
31
+ get blockDuration() {
32
+ return this.limiter.blockDuration;
33
+ }
34
+
35
+ set blockDuration(value) {
36
+ this.limiter.blockDuration = value;
37
+ }
38
+
39
+ get execEvenly() {
40
+ return this.limiter.execEvenly;
41
+ }
42
+
43
+ set execEvenly(value) {
44
+ this.limiter.execEvenly = value;
45
+ }
46
+
25
47
  get runActionAnyway() {
26
48
  return this._runActionAnyway;
27
49
  }
@@ -102,94 +124,52 @@ module.exports = class RLWrapperBlackAndWhite {
102
124
  return Promise.resolve(this.getWhiteRes());
103
125
  }
104
126
 
105
- consume(key, pointsToConsume = 1) {
127
+ _execAction(action, key, args, rejectOnBlack = false) {
106
128
  let res;
107
129
  if (this.isWhiteListedSomewhere(key)) {
108
130
  res = this.resolveWhite();
109
131
  } else if (this.isBlackListedSomewhere(key)) {
110
- res = this.rejectBlack();
132
+ res = rejectOnBlack ? this.rejectBlack() : this.resolveBlack();
111
133
  }
112
134
 
113
135
  if (typeof res === 'undefined') {
114
- return this.limiter.consume(key, pointsToConsume);
136
+ return this.limiter[action](key, ...args);
115
137
  }
116
138
 
117
139
  if (this.runActionAnyway) {
118
- this.limiter.consume(key, pointsToConsume).catch(() => {});
140
+ this.limiter[action](key, ...args).catch(() => {});
119
141
  }
120
142
  return res;
121
143
  }
122
144
 
123
- block(key, secDuration) {
124
- let res;
125
- if (this.isWhiteListedSomewhere(key)) {
126
- res = this.resolveWhite();
127
- } else if (this.isBlackListedSomewhere(key)) {
128
- res = this.resolveBlack();
129
- }
130
-
131
- if (typeof res === 'undefined') {
132
- return this.limiter.block(key, secDuration);
133
- }
134
-
135
- if (this.runActionAnyway) {
136
- this.limiter.block(key, secDuration).catch(() => {});
137
- }
138
- return res;
145
+ consume(key, pointsToConsume = 1, options = {}) {
146
+ return this._execAction('consume', key, [pointsToConsume, options], true);
139
147
  }
140
148
 
141
- penalty(key, points) {
142
- let res;
143
- if (this.isWhiteListedSomewhere(key)) {
144
- res = this.resolveWhite();
145
- } else if (this.isBlackListedSomewhere(key)) {
146
- res = this.resolveBlack();
147
- }
148
-
149
- if (typeof res === 'undefined') {
150
- return this.limiter.penalty(key, points);
151
- }
152
-
153
- if (this.runActionAnyway) {
154
- this.limiter.penalty(key, points).catch(() => {});
155
- }
156
- return res;
149
+ block(key, secDuration, options = {}) {
150
+ return this._execAction('block', key, [secDuration, options]);
157
151
  }
158
152
 
159
- reward(key, points) {
160
- let res;
161
- if (this.isWhiteListedSomewhere(key)) {
162
- res = this.resolveWhite();
163
- } else if (this.isBlackListedSomewhere(key)) {
164
- res = this.resolveBlack();
165
- }
153
+ penalty(key, points = 1, options = {}) {
154
+ return this._execAction('penalty', key, [points, options]);
155
+ }
166
156
 
167
- if (typeof res === 'undefined') {
168
- return this.limiter.reward(key, points);
169
- }
157
+ reward(key, points = 1, options = {}) {
158
+ return this._execAction('reward', key, [points, options]);
159
+ }
170
160
 
161
+ get(key, options = {}) {
171
162
  if (this.runActionAnyway) {
172
- this.limiter.reward(key, points).catch(() => {});
163
+ return this.limiter.get(key, options);
173
164
  }
174
- return res;
165
+ return this._execAction('get', key, [options]);
175
166
  }
176
167
 
177
- get(key) {
178
- let res;
179
- if (this.isWhiteListedSomewhere(key)) {
180
- res = this.resolveWhite();
181
- } else if (this.isBlackListedSomewhere(key)) {
182
- res = this.resolveBlack();
183
- }
184
-
185
- if (typeof res === 'undefined' || this.runActionAnyway) {
186
- return this.limiter.get(key);
187
- }
188
-
189
- return res;
168
+ set(key, points, secDuration, options = {}) {
169
+ return this._execAction('set', key, [points, secDuration, options]);
190
170
  }
191
171
 
192
- delete(key) {
193
- return this.limiter.delete(key);
172
+ delete(key, options = {}) {
173
+ return this.limiter.delete(key, options);
194
174
  }
195
175
  };
@@ -1,9 +1,13 @@
1
- const RateLimiterAbstract = require('./RateLimiterAbstract');
2
1
  const RateLimiterInsuredAbstract = require('./RateLimiterInsuredAbstract');
2
+ const isRateLimiterCompatible = require('./helper/isRateLimiterCompatible');
3
3
 
4
4
  module.exports = class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
5
5
  constructor(opts= {}) {
6
- super(opts);
6
+ super({
7
+ ...opts,
8
+ points: 0,
9
+ duration: 0,
10
+ });
7
11
  this.limiter = opts.limiter;
8
12
  this.timeoutMs = opts.timeoutMs || 0;
9
13
  }
@@ -13,8 +17,8 @@ module.exports = class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
13
17
  }
14
18
 
15
19
  set limiter(limiter) {
16
- if (!(limiter instanceof RateLimiterAbstract)) {
17
- throw new TypeError('limiter must be an instance of RateLimiterAbstract');
20
+ if (!isRateLimiterCompatible(limiter)) {
21
+ throw new TypeError('limiter must be an instance of RateLimiterAbstract or RateLimiterCompatibleAbstract');
18
22
  }
19
23
  this._limiter = limiter;
20
24
  if (!this.insuranceLimiter && limiter instanceof RateLimiterInsuredAbstract) {
@@ -100,7 +100,7 @@ module.exports = class RateLimiterAbstract {
100
100
  }
101
101
 
102
102
  parseKey(rlKey) {
103
- return rlKey.substring(this.keyPrefix.length);
103
+ return this.keyPrefix.length > 0 ? rlKey.substring(this.keyPrefix.length + 1) : rlKey;
104
104
  }
105
105
 
106
106
  consume() {
@@ -0,0 +1,49 @@
1
+ module.exports = class RateLimiterCompatibleAbstract {
2
+ get keyPrefix() {
3
+ throw new Error("You have to implement the getter 'keyPrefix'!");
4
+ }
5
+
6
+ get blockDuration() {
7
+ throw new Error("You have to implement the getter 'blockDuration'!");
8
+ }
9
+
10
+ set blockDuration(value) {
11
+ throw new Error("You have to implement the setter 'blockDuration'!");
12
+ }
13
+
14
+ get execEvenly() {
15
+ throw new Error("You have to implement the getter 'execEvenly'!");
16
+ }
17
+
18
+ set execEvenly(value) {
19
+ throw new Error("You have to implement the setter 'execEvenly'!");
20
+ }
21
+
22
+ consume() {
23
+ throw new Error("You have to implement the method 'consume'!");
24
+ }
25
+
26
+ penalty() {
27
+ throw new Error("You have to implement the method 'penalty'!");
28
+ }
29
+
30
+ reward() {
31
+ throw new Error("You have to implement the method 'reward'!");
32
+ }
33
+
34
+ get() {
35
+ throw new Error("You have to implement the method 'get'!");
36
+ }
37
+
38
+ set() {
39
+ throw new Error("You have to implement the method 'set'!");
40
+ }
41
+
42
+ block() {
43
+ throw new Error("You have to implement the method 'block'!");
44
+ }
45
+
46
+ delete() {
47
+ throw new Error("You have to implement the method 'delete'!");
48
+ }
49
+ };
@@ -1,5 +1,6 @@
1
1
  const RateLimiterAbstract = require('./RateLimiterAbstract');
2
2
  const RateLimiterRes = require('./RateLimiterRes');
3
+ const isRateLimiterCompatible = require('./helper/isRateLimiterCompatible');
3
4
 
4
5
  module.exports = class RateLimiterInsuredAbstract extends RateLimiterAbstract {
5
6
  constructor(opts = {}) {
@@ -12,8 +13,8 @@ module.exports = class RateLimiterInsuredAbstract extends RateLimiterAbstract {
12
13
  }
13
14
 
14
15
  set insuranceLimiter(value) {
15
- if (typeof value !== 'undefined' && !(value instanceof RateLimiterAbstract)) {
16
- throw new Error('insuranceLimiter must be instance of RateLimiterAbstract');
16
+ if (typeof value !== 'undefined' && !isRateLimiterCompatible(value)) {
17
+ throw new Error('insuranceLimiter must be instance of RateLimiterAbstract or RateLimiterCompatibleAbstract');
17
18
  }
18
19
  this._insuranceLimiter = value;
19
20
  if (this._insuranceLimiter) {
@@ -25,7 +26,7 @@ module.exports = class RateLimiterInsuredAbstract extends RateLimiterAbstract {
25
26
  _handleError(err, funcName, resolve, reject, params) {
26
27
  if (err instanceof RateLimiterRes) {
27
28
  reject(err);
28
- } else if (!(this.insuranceLimiter instanceof RateLimiterAbstract)) {
29
+ } else if (!isRateLimiterCompatible(this.insuranceLimiter)) {
29
30
  reject(err);
30
31
  } else {
31
32
  this.insuranceLimiter[funcName](...params)
@@ -1,4 +1,3 @@
1
- const RateLimiterAbstract = require('./RateLimiterAbstract');
2
1
  const BlockedKeys = require('./component/BlockedKeys');
3
2
  const RateLimiterRes = require('./RateLimiterRes');
4
3
  const RateLimiterInsuredAbstract = require('./RateLimiterInsuredAbstract');
@@ -152,7 +151,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterInsuredAbstra
152
151
  */
153
152
  set(key, points, secDuration, options = {}) {
154
153
  const msDuration = (secDuration >= 0 ? secDuration : this.duration) * 1000;
155
- return this._block(this.getKey(key), points, msDuration, options);
154
+ return this._set(this.getKey(key), points, msDuration, options);
156
155
  }
157
156
 
158
157
  /**
@@ -300,6 +299,26 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterInsuredAbstra
300
299
  });
301
300
  }
302
301
 
302
+ /**
303
+ * @param rlKey
304
+ * @param points
305
+ * @param msDuration
306
+ * @param {Object} options
307
+ *
308
+ * @return Promise<any>
309
+ */
310
+ _set(rlKey, points, msDuration, options = {}) {
311
+ return new Promise((resolve, reject) => {
312
+ this._upsert(rlKey, points, msDuration, true, options)
313
+ .then(() => {
314
+ resolve(new RateLimiterRes(0, msDuration > 0 ? msDuration : -1, points));
315
+ })
316
+ .catch((err) => {
317
+ this._handleError(err, 'set', resolve, reject, [this.parseKey(rlKey), points, msDuration / 1000, options]);
318
+ });
319
+ });
320
+ }
321
+
303
322
  /**
304
323
  * Have to be implemented in every limiter
305
324
  * Resolve with raw result from Store OR null if rlKey is not set
@@ -1,4 +1,4 @@
1
- const RateLimiterAbstract = require('./RateLimiterAbstract');
1
+ const isRateLimiterCompatible = require('./helper/isRateLimiterCompatible');
2
2
 
3
3
  module.exports = class RateLimiterUnion {
4
4
  constructor(...limiters) {
@@ -6,8 +6,8 @@ module.exports = class RateLimiterUnion {
6
6
  throw new Error('RateLimiterUnion: at least one limiter have to be passed');
7
7
  }
8
8
  limiters.forEach((limiter) => {
9
- if (!(limiter instanceof RateLimiterAbstract)) {
10
- throw new Error('RateLimiterUnion: all limiters have to be instance of RateLimiterAbstract');
9
+ if (!isRateLimiterCompatible(limiter)) {
10
+ throw new Error('RateLimiterUnion: all limiters have to be instance of RateLimiterAbstract or RateLimiterCompatibleAbstract');
11
11
  }
12
12
  });
13
13
 
@@ -0,0 +1,6 @@
1
+ const RateLimiterAbstract = require('../RateLimiterAbstract');
2
+ const RateLimiterCompatibleAbstract = require('../RateLimiterCompatibleAbstract');
3
+
4
+ module.exports = function isRateLimiterCompatible(obj) {
5
+ return obj instanceof RateLimiterAbstract || obj instanceof RateLimiterCompatibleAbstract;
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rate-limiter-flexible",
3
- "version": "10.0.0",
3
+ "version": "11.0.0",
4
4
  "description": "Node.js atomic and non-atomic counters, rate limiting tools, protection from DoS and brute-force attacks at scale",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/types.d.ts CHANGED
@@ -27,6 +27,55 @@ export class RateLimiterRes {
27
27
  };
28
28
  }
29
29
 
30
+ export class RateLimiterCompatibleAbstract {
31
+ readonly keyPrefix: string;
32
+ blockDuration: number;
33
+ execEvenly: boolean;
34
+
35
+ consume(
36
+ key: string | number,
37
+ pointsToConsume?: number,
38
+ options?: { [key: string]: any }
39
+ ): Promise<RateLimiterRes>;
40
+
41
+ penalty(
42
+ key: string | number,
43
+ points?: number,
44
+ options?: { [key: string]: any }
45
+ ): Promise<RateLimiterRes>;
46
+
47
+ reward(
48
+ key: string | number,
49
+ points?: number,
50
+ options?: { [key: string]: any }
51
+ ): Promise<RateLimiterRes>;
52
+
53
+ get(
54
+ key: string | number,
55
+ options?: { [key: string]: any }
56
+ ): Promise<RateLimiterRes | null>;
57
+
58
+ set(
59
+ key: string | number,
60
+ points: number,
61
+ secDuration: number,
62
+ options?: { [key: string]: any }
63
+ ): Promise<RateLimiterRes>;
64
+
65
+ block(
66
+ key: string | number,
67
+ secDuration: number,
68
+ options?: { [key: string]: any }
69
+ ): Promise<RateLimiterRes>;
70
+
71
+ delete(
72
+ key: string | number,
73
+ options?: { [key: string]: any }
74
+ ): Promise<boolean>;
75
+ }
76
+
77
+ export type RateLimiterLike = RateLimiterAbstract | RateLimiterCompatibleAbstract;
78
+
30
79
  export class RateLimiterAbstract {
31
80
  constructor(opts: IRateLimiterOptions);
32
81
 
@@ -224,7 +273,7 @@ interface IRateLimiterOptions {
224
273
  execEvenly?: boolean;
225
274
  execEvenlyMinDelayMs?: number;
226
275
  blockDuration?: number;
227
- insuranceLimiter?: RateLimiterAbstract;
276
+ insuranceLimiter?: RateLimiterLike;
228
277
  }
229
278
 
230
279
  interface IRateLimiterClusterOptions extends IRateLimiterOptions {
@@ -236,7 +285,7 @@ interface IRateLimiterStoreOptions extends IRateLimiterOptions {
236
285
  storeType?: string;
237
286
  inMemoryBlockOnConsumed?: number;
238
287
  inMemoryBlockDuration?: number;
239
- insuranceLimiter?: RateLimiterAbstract;
288
+ insuranceLimiter?: RateLimiterLike;
240
289
  dbName?: string;
241
290
  tableName?: string;
242
291
  tableCreated?: boolean;
@@ -277,7 +326,7 @@ interface ICallbackReady {
277
326
  }
278
327
 
279
328
  interface IRLWrapperBlackAndWhiteOptions {
280
- limiter: RateLimiterAbstract;
329
+ limiter: RateLimiterLike;
281
330
  blackList?: string[] | number[];
282
331
  whiteList?: string[] | number[];
283
332
  isBlackListed?(key: any): boolean;
@@ -393,17 +442,24 @@ export class RateLimiterDrizzleNonAtomic extends RateLimiterStoreAbstract {
393
442
  export class RateLimiterMemcache extends RateLimiterStoreAbstract { }
394
443
 
395
444
  export class RateLimiterUnion {
396
- constructor(...limiters: RateLimiterAbstract[]);
445
+ constructor(...limiters: RateLimiterLike[]);
397
446
 
398
447
  consume(key: string | number, points?: number): Promise<Record<string, RateLimiterRes>>;
399
448
  }
400
449
 
401
- export class RLWrapperBlackAndWhite extends RateLimiterAbstract {
450
+ export class RLWrapperBlackAndWhite extends RateLimiterCompatibleAbstract {
402
451
  constructor(opts: IRLWrapperBlackAndWhiteOptions);
452
+
453
+ limiter: RateLimiterLike;
454
+ blackList: string[] | number[];
455
+ whiteList: string[] | number[];
456
+ isBlackListed: (key: any) => boolean;
457
+ isWhiteListed: (key: any) => boolean;
458
+ runActionAnyway: boolean;
403
459
  }
404
460
 
405
- interface IRLWrapperTimeoutsOptions extends IRateLimiterOptions {
406
- limiter: RateLimiterAbstract;
461
+ interface IRLWrapperTimeoutsOptions extends Omit<IRateLimiterOptions, 'points' | 'duration'> {
462
+ limiter: RateLimiterLike;
407
463
  timeoutMs?: number;
408
464
  }
409
465
 
@@ -417,7 +473,7 @@ interface IRateLimiterQueueOpts {
417
473
 
418
474
  export class RateLimiterQueue {
419
475
  constructor(
420
- limiterFlexible: RateLimiterAbstract | BurstyRateLimiter,
476
+ limiterFlexible: RateLimiterLike | BurstyRateLimiter,
421
477
  opts?: IRateLimiterQueueOpts
422
478
  );
423
479
 
@@ -428,8 +484,8 @@ export class RateLimiterQueue {
428
484
 
429
485
  export class BurstyRateLimiter {
430
486
  constructor(
431
- rateLimiter: RateLimiterAbstract,
432
- burstLimiter: RateLimiterAbstract
487
+ rateLimiter: RateLimiterLike,
488
+ burstLimiter: RateLimiterLike
433
489
  );
434
490
 
435
491
  consume(