rate-limiter-flexible 2.1.3 → 2.1.7

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/README.md CHANGED
@@ -126,6 +126,10 @@ Some copy/paste examples on Wiki:
126
126
  * [RLWrapperBlackAndWhite](https://github.com/animir/node-rate-limiter-flexible/wiki/Black-and-White-lists) Black and White lists
127
127
  * [RateLimiterQueue](https://github.com/animir/node-rate-limiter-flexible/wiki/RateLimiterQueue) Rate limiter with FIFO queue
128
128
 
129
+ ### Changelog
130
+
131
+ See [releases](https://github.com/animir/node-rate-limiter-flexible/releases) for detailed changelog.
132
+
129
133
  ## Basic Options
130
134
 
131
135
  * **points**
@@ -157,9 +161,10 @@ Some copy/paste examples on Wiki:
157
161
  * [storeType](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#storetype) Have to be set to `knex`, if you use it.
158
162
  * [dbName](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#dbname) Where to store points.
159
163
  * [tableName](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#tablename) Table/collection.
164
+ * [tableCreated](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#tablecreated) Is table already created in MySQL or PostgreSQL.
160
165
  * [clearExpiredByTimeout](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#clearexpiredbytimeout) For MySQL and PostgreSQL.
161
166
 
162
- Cut off load picks:
167
+ Smooth out traffic picks:
163
168
  * [execEvenly](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#execevenly)
164
169
  * [execEvenlyMinDelayMs](https://github.com/animir/node-rate-limiter-flexible/wiki/Options#execevenlymindelayms)
165
170
 
@@ -218,3 +223,5 @@ It has to implement at least 4 methods:
218
223
  * `_delete` deletes all key related data and returns `true` on deleted, `false` if key is not found.
219
224
 
220
225
  All other methods depends on store. See `RateLimiterRedis` or `RateLimiterPostgres` for example.
226
+
227
+ Note: all changes should be covered by tests.
@@ -28,24 +28,33 @@ class RateLimiterMySQL extends RateLimiterStoreAbstract {
28
28
 
29
29
  this.clearExpiredByTimeout = opts.clearExpiredByTimeout;
30
30
 
31
- this._tableCreated = false;
32
- this._createDbAndTable()
33
- .then(() => {
34
- this._tableCreated = true;
35
- if (this.clearExpiredByTimeout) {
36
- this._clearExpiredHourAgo();
37
- }
38
- if (typeof cb === 'function') {
39
- cb();
40
- }
41
- })
42
- .catch((err) => {
43
- if (typeof cb === 'function') {
44
- cb(err);
45
- } else {
46
- throw err;
47
- }
48
- });
31
+ this.tableCreated = opts.tableCreated;
32
+ if (!this.tableCreated) {
33
+ this._createDbAndTable()
34
+ .then(() => {
35
+ this.tableCreated = true;
36
+ if (this.clearExpiredByTimeout) {
37
+ this._clearExpiredHourAgo();
38
+ }
39
+ if (typeof cb === 'function') {
40
+ cb();
41
+ }
42
+ })
43
+ .catch((err) => {
44
+ if (typeof cb === 'function') {
45
+ cb(err);
46
+ } else {
47
+ throw err;
48
+ }
49
+ });
50
+ } else {
51
+ if (this.clearExpiredByTimeout) {
52
+ this._clearExpiredHourAgo();
53
+ }
54
+ if (typeof cb === 'function') {
55
+ cb();
56
+ }
57
+ }
49
58
  }
50
59
 
51
60
  clearExpired(expire) {
@@ -189,6 +198,14 @@ class RateLimiterMySQL extends RateLimiterStoreAbstract {
189
198
  this._tableName = typeof value === 'undefined' ? this.keyPrefix : value;
190
199
  }
191
200
 
201
+ get tableCreated() {
202
+ return this._tableCreated
203
+ }
204
+
205
+ set tableCreated(value) {
206
+ this._tableCreated = typeof value === 'undefined' ? false : !!value;
207
+ }
208
+
192
209
  get clearExpiredByTimeout() {
193
210
  return this._clearExpiredByTimeout;
194
211
  }
@@ -277,7 +294,7 @@ class RateLimiterMySQL extends RateLimiterStoreAbstract {
277
294
  }
278
295
 
279
296
  _upsert(key, points, msDuration, forceExpire = false) {
280
- if (!this._tableCreated) {
297
+ if (!this.tableCreated) {
281
298
  return Promise.reject(Error('Table is not created yet'));
282
299
  }
283
300
 
@@ -301,7 +318,7 @@ class RateLimiterMySQL extends RateLimiterStoreAbstract {
301
318
  }
302
319
 
303
320
  _get(rlKey) {
304
- if (!this._tableCreated) {
321
+ if (!this.tableCreated) {
305
322
  return Promise.reject(Error('Table is not created yet'));
306
323
  }
307
324
 
@@ -331,7 +348,7 @@ class RateLimiterMySQL extends RateLimiterStoreAbstract {
331
348
  }
332
349
 
333
350
  _delete(rlKey) {
334
- if (!this._tableCreated) {
351
+ if (!this.tableCreated) {
335
352
  return Promise.reject(Error('Table is not created yet'));
336
353
  }
337
354
 
@@ -26,24 +26,30 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
26
26
 
27
27
  this.clearExpiredByTimeout = opts.clearExpiredByTimeout;
28
28
 
29
- this._tableCreated = false;
30
- this._createTable()
31
- .then(() => {
32
- this._tableCreated = true;
33
- if (this.clearExpiredByTimeout) {
34
- this._clearExpiredHourAgo();
35
- }
36
- if (typeof cb === 'function') {
37
- cb();
38
- }
39
- })
40
- .catch((err) => {
41
- if (typeof cb === 'function') {
42
- cb(err);
43
- } else {
44
- throw err;
45
- }
46
- });
29
+ this.tableCreated = opts.tableCreated;
30
+ if (!this.tableCreated) {
31
+ this._createTable()
32
+ .then(() => {
33
+ this.tableCreated = true;
34
+ if (this.clearExpiredByTimeout) {
35
+ this._clearExpiredHourAgo();
36
+ }
37
+ if (typeof cb === 'function') {
38
+ cb();
39
+ }
40
+ })
41
+ .catch((err) => {
42
+ if (typeof cb === 'function') {
43
+ cb(err);
44
+ } else {
45
+ throw err;
46
+ }
47
+ });
48
+ } else {
49
+ if (typeof cb === 'function') {
50
+ cb();
51
+ }
52
+ }
47
53
  }
48
54
 
49
55
  clearExpired(expire) {
@@ -152,17 +158,23 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
152
158
  }
153
159
 
154
160
  set clientType(value) {
161
+ const constructorName = this.client.constructor.name;
162
+
155
163
  if (typeof value === 'undefined') {
156
- if (this.client.constructor.name === 'Client') {
164
+ if (constructorName === 'Client') {
157
165
  value = 'client';
158
- } else if (this.client.constructor.name === 'Pool') {
166
+ } else if (
167
+ constructorName === 'Pool' ||
168
+ constructorName === 'BoundPool'
169
+ ) {
159
170
  value = 'pool';
160
- } else if (this.client.constructor.name === 'Sequelize') {
171
+ } else if (constructorName === 'Sequelize') {
161
172
  value = 'sequelize';
162
173
  } else {
163
174
  throw new Error('storeType is not defined');
164
175
  }
165
176
  }
177
+
166
178
  this._clientType = value.toLowerCase();
167
179
  }
168
180
 
@@ -174,6 +186,14 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
174
186
  this._tableName = typeof value === 'undefined' ? this.keyPrefix : value;
175
187
  }
176
188
 
189
+ get tableCreated() {
190
+ return this._tableCreated
191
+ }
192
+
193
+ set tableCreated(value) {
194
+ this._tableCreated = typeof value === 'undefined' ? false : !!value;
195
+ }
196
+
177
197
  get clearExpiredByTimeout() {
178
198
  return this._clearExpiredByTimeout;
179
199
  }
@@ -220,7 +240,7 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
220
240
  }
221
241
 
222
242
  _upsert(key, points, msDuration, forceExpire = false) {
223
- if (!this._tableCreated) {
243
+ if (!this.tableCreated) {
224
244
  return Promise.reject(Error('Table is not created yet'));
225
245
  }
226
246
 
@@ -248,7 +268,7 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
248
268
  }
249
269
 
250
270
  _get(rlKey) {
251
- if (!this._tableCreated) {
271
+ if (!this.tableCreated) {
252
272
  return Promise.reject(Error('Table is not created yet'));
253
273
  }
254
274
 
@@ -272,7 +292,7 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
272
292
  }
273
293
 
274
294
  _delete(rlKey) {
275
- if (!this._tableCreated) {
295
+ if (!this.tableCreated) {
276
296
  return Promise.reject(Error('Table is not created yet'));
277
297
  }
278
298
 
@@ -1,12 +1,46 @@
1
1
  const RateLimiterQueueError = require('./component/RateLimiterQueueError')
2
2
  const MAX_QUEUE_SIZE = 4294967295;
3
+ const KEY_DEFAULT = 'limiter';
3
4
 
4
5
  module.exports = class RateLimiterQueue {
6
+ constructor(limiterFlexible, opts = {
7
+ maxQueueSize: MAX_QUEUE_SIZE,
8
+ }) {
9
+ this._queueLimiters = {
10
+ KEY_DEFAULT: new RateLimiterQueueInternal(limiterFlexible, opts)
11
+ };
12
+ this._limiterFlexible = limiterFlexible;
13
+ this._maxQueueSize = opts.maxQueueSize
14
+ }
15
+
16
+ getTokensRemaining(key = KEY_DEFAULT) {
17
+ if (this._queueLimiters[key]) {
18
+ return this._queueLimiters[key].getTokensRemaining()
19
+ } else {
20
+ return Promise.resolve(this._limiterFlexible.points)
21
+ }
22
+ }
23
+
24
+ removeTokens(tokens, key = KEY_DEFAULT) {
25
+ if (!this._queueLimiters[key]) {
26
+ this._queueLimiters[key] = new RateLimiterQueueInternal(
27
+ this._limiterFlexible, {
28
+ key,
29
+ maxQueueSize: this._maxQueueSize,
30
+ })
31
+ }
32
+
33
+ return this._queueLimiters[key].removeTokens(tokens)
34
+ }
35
+ };
36
+
37
+ class RateLimiterQueueInternal {
5
38
 
6
39
  constructor(limiterFlexible, opts = {
7
40
  maxQueueSize: MAX_QUEUE_SIZE,
41
+ key: KEY_DEFAULT,
8
42
  }) {
9
- this._key = 'limiter';
43
+ this._key = opts.key;
10
44
  this._waitTimeout = null;
11
45
  this._queue = [];
12
46
  this._limiterFlexible = limiterFlexible;
@@ -90,4 +124,4 @@ module.exports = class RateLimiterQueue {
90
124
  }
91
125
  });
92
126
  }
93
- };
127
+ }
package/lib/index.d.ts CHANGED
@@ -67,6 +67,7 @@ interface IRateLimiterStoreOptions extends IRateLimiterOptions{
67
67
  insuranceLimiter?: RateLimiterAbstract;
68
68
  dbName?: string;
69
69
  tableName?: string;
70
+ tableCreated?: boolean;
70
71
  }
71
72
 
72
73
  interface IRateLimiterMongoOptions extends IRateLimiterStoreOptions{
@@ -157,7 +158,11 @@ interface IRateLimiterQueueOpts {
157
158
  }
158
159
 
159
160
  export class RateLimiterQueue {
160
- constructor(limiterFlexible: RateLimiterAbstract, opts?: IRateLimiterQueueOpts)
161
+ constructor(limiterFlexible: RateLimiterAbstract, opts?: IRateLimiterQueueOpts);
162
+
163
+ getTokensRemaining(key?: string | number): Promise<RateLimiterRes>;
164
+
165
+ removeTokens(tokens: number, key?: string | number): Promise<RateLimiterRes>;
161
166
  }
162
167
 
163
168
  export class BurstyRateLimiter {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rate-limiter-flexible",
3
- "version": "2.1.3",
3
+ "version": "2.1.7",
4
4
  "description": "Node.js rate limiter by key and protection from DDoS and Brute-Force attacks in process Memory, Redis, MongoDb, Memcached, MySQL, PostgreSQL, Cluster or PM",
5
5
  "main": "index.js",
6
6
  "scripts": {