@depup/rate-limiter-flexible 9.1.1-depup.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.
Files changed (42) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +25 -0
  3. package/changes.json +5 -0
  4. package/index.js +55 -0
  5. package/lib/BurstyRateLimiter.js +78 -0
  6. package/lib/ExpressBruteFlexible.js +359 -0
  7. package/lib/RLWrapperBlackAndWhite.js +195 -0
  8. package/lib/RLWrapperTimeouts.js +82 -0
  9. package/lib/RateLimiterAbstract.js +125 -0
  10. package/lib/RateLimiterCluster.js +367 -0
  11. package/lib/RateLimiterDrizzle.js +174 -0
  12. package/lib/RateLimiterDrizzleNonAtomic.js +175 -0
  13. package/lib/RateLimiterDynamo.js +401 -0
  14. package/lib/RateLimiterEtcd.js +63 -0
  15. package/lib/RateLimiterEtcdNonAtomic.js +80 -0
  16. package/lib/RateLimiterInsuredAbstract.js +112 -0
  17. package/lib/RateLimiterMemcache.js +150 -0
  18. package/lib/RateLimiterMemory.js +106 -0
  19. package/lib/RateLimiterMongo.js +261 -0
  20. package/lib/RateLimiterMySQL.js +400 -0
  21. package/lib/RateLimiterPostgres.js +351 -0
  22. package/lib/RateLimiterPrisma.js +127 -0
  23. package/lib/RateLimiterQueue.js +131 -0
  24. package/lib/RateLimiterRedis.js +209 -0
  25. package/lib/RateLimiterRedisNonAtomic.js +195 -0
  26. package/lib/RateLimiterRes.js +64 -0
  27. package/lib/RateLimiterSQLite.js +338 -0
  28. package/lib/RateLimiterStoreAbstract.js +349 -0
  29. package/lib/RateLimiterUnion.js +51 -0
  30. package/lib/RateLimiterValkey.js +117 -0
  31. package/lib/RateLimiterValkeyGlide.js +273 -0
  32. package/lib/component/BlockedKeys/BlockedKeys.js +75 -0
  33. package/lib/component/BlockedKeys/index.js +3 -0
  34. package/lib/component/MemoryStorage/MemoryStorage.js +83 -0
  35. package/lib/component/MemoryStorage/Record.js +40 -0
  36. package/lib/component/MemoryStorage/index.js +3 -0
  37. package/lib/component/RateLimiterEtcdTransactionFailedError.js +10 -0
  38. package/lib/component/RateLimiterQueueError.js +13 -0
  39. package/lib/component/RateLimiterSetupError.js +10 -0
  40. package/lib/constants.js +21 -0
  41. package/package.json +100 -0
  42. package/types.d.ts +581 -0
@@ -0,0 +1,195 @@
1
+ const RateLimiterRes = require('./RateLimiterRes');
2
+
3
+ module.exports = class RLWrapperBlackAndWhite {
4
+ constructor(opts = {}) {
5
+ this.limiter = opts.limiter;
6
+ this.blackList = opts.blackList;
7
+ this.whiteList = opts.whiteList;
8
+ this.isBlackListed = opts.isBlackListed;
9
+ this.isWhiteListed = opts.isWhiteListed;
10
+ this.runActionAnyway = opts.runActionAnyway;
11
+ }
12
+
13
+ get limiter() {
14
+ return this._limiter;
15
+ }
16
+
17
+ set limiter(value) {
18
+ if (typeof value === 'undefined') {
19
+ throw new Error('limiter is not set');
20
+ }
21
+
22
+ this._limiter = value;
23
+ }
24
+
25
+ get runActionAnyway() {
26
+ return this._runActionAnyway;
27
+ }
28
+
29
+ set runActionAnyway(value) {
30
+ this._runActionAnyway = typeof value === 'undefined' ? false : value;
31
+ }
32
+
33
+ get blackList() {
34
+ return this._blackList;
35
+ }
36
+
37
+ set blackList(value) {
38
+ this._blackList = Array.isArray(value) ? value : [];
39
+ }
40
+
41
+ get isBlackListed() {
42
+ return this._isBlackListed;
43
+ }
44
+
45
+ set isBlackListed(func) {
46
+ if (typeof func === 'undefined') {
47
+ func = () => false;
48
+ }
49
+ if (typeof func !== 'function') {
50
+ throw new Error('isBlackListed must be function');
51
+ }
52
+ this._isBlackListed = func;
53
+ }
54
+
55
+ get whiteList() {
56
+ return this._whiteList;
57
+ }
58
+
59
+ set whiteList(value) {
60
+ this._whiteList = Array.isArray(value) ? value : [];
61
+ }
62
+
63
+ get isWhiteListed() {
64
+ return this._isWhiteListed;
65
+ }
66
+
67
+ set isWhiteListed(func) {
68
+ if (typeof func === 'undefined') {
69
+ func = () => false;
70
+ }
71
+ if (typeof func !== 'function') {
72
+ throw new Error('isWhiteListed must be function');
73
+ }
74
+ this._isWhiteListed = func;
75
+ }
76
+
77
+ isBlackListedSomewhere(key) {
78
+ return this.blackList.indexOf(key) >= 0 || this.isBlackListed(key);
79
+ }
80
+
81
+ isWhiteListedSomewhere(key) {
82
+ return this.whiteList.indexOf(key) >= 0 || this.isWhiteListed(key);
83
+ }
84
+
85
+ getBlackRes() {
86
+ return new RateLimiterRes(0, Number.MAX_SAFE_INTEGER, 0, false);
87
+ }
88
+
89
+ getWhiteRes() {
90
+ return new RateLimiterRes(Number.MAX_SAFE_INTEGER, 0, 0, false);
91
+ }
92
+
93
+ rejectBlack() {
94
+ return Promise.reject(this.getBlackRes());
95
+ }
96
+
97
+ resolveBlack() {
98
+ return Promise.resolve(this.getBlackRes());
99
+ }
100
+
101
+ resolveWhite() {
102
+ return Promise.resolve(this.getWhiteRes());
103
+ }
104
+
105
+ consume(key, pointsToConsume = 1) {
106
+ let res;
107
+ if (this.isWhiteListedSomewhere(key)) {
108
+ res = this.resolveWhite();
109
+ } else if (this.isBlackListedSomewhere(key)) {
110
+ res = this.rejectBlack();
111
+ }
112
+
113
+ if (typeof res === 'undefined') {
114
+ return this.limiter.consume(key, pointsToConsume);
115
+ }
116
+
117
+ if (this.runActionAnyway) {
118
+ this.limiter.consume(key, pointsToConsume).catch(() => {});
119
+ }
120
+ return res;
121
+ }
122
+
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;
139
+ }
140
+
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;
157
+ }
158
+
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
+ }
166
+
167
+ if (typeof res === 'undefined') {
168
+ return this.limiter.reward(key, points);
169
+ }
170
+
171
+ if (this.runActionAnyway) {
172
+ this.limiter.reward(key, points).catch(() => {});
173
+ }
174
+ return res;
175
+ }
176
+
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;
190
+ }
191
+
192
+ delete(key) {
193
+ return this.limiter.delete(key);
194
+ }
195
+ };
@@ -0,0 +1,82 @@
1
+ const RateLimiterAbstract = require('./RateLimiterAbstract');
2
+ const RateLimiterInsuredAbstract = require('./RateLimiterInsuredAbstract');
3
+
4
+ module.exports = class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
5
+ constructor(opts= {}) {
6
+ super(opts);
7
+ this.limiter = opts.limiter;
8
+ this.timeoutMs = opts.timeoutMs || 0;
9
+ }
10
+
11
+ get limiter() {
12
+ return this._limiter;
13
+ }
14
+
15
+ set limiter(limiter) {
16
+ if (!(limiter instanceof RateLimiterAbstract)) {
17
+ throw new TypeError('limiter must be an instance of RateLimiterAbstract');
18
+ }
19
+ this._limiter = limiter;
20
+ if (!this.insuranceLimiter && limiter instanceof RateLimiterInsuredAbstract) {
21
+ this.insuranceLimiter = limiter.insuranceLimiter;
22
+ }
23
+ }
24
+
25
+ get timeoutMs() {
26
+ return this._timeoutMs;
27
+ }
28
+
29
+ set timeoutMs(value) {
30
+ if (typeof value !== 'number' || value < 0) {
31
+ throw new TypeError('timeoutMs must be a non-negative number');
32
+ }
33
+ this._timeoutMs = value;
34
+ }
35
+
36
+ _run(funcName, params) {
37
+ return new Promise(async (resolve, reject) => {
38
+ const timeout = setTimeout(() => {
39
+ return reject(new Error('Operation timed out'));
40
+ }, this.timeoutMs);
41
+
42
+ await this.limiter[funcName](...params)
43
+ .then((result) => {
44
+ clearTimeout(timeout);
45
+ resolve(result);
46
+ })
47
+ .catch((err) => {
48
+ clearTimeout(timeout);
49
+ reject(err);
50
+ });
51
+ });
52
+ }
53
+
54
+ _consume(key, pointsToConsume = 1, options = {}) {
55
+ return this._run('consume', [key, pointsToConsume, options]);
56
+ }
57
+
58
+ _penalty(key, points = 1, options = {}) {
59
+ return this._run('penalty', [key, points, options]);
60
+ }
61
+
62
+ _reward(key, points = 1, options = {}) {
63
+ return this._run('reward', [key, points, options]);
64
+ }
65
+
66
+ _get(key, options = {}) {
67
+ return this._run('get', [key, options]);
68
+ }
69
+
70
+ _set(key, points, secDuration, options = {}) {
71
+ return this._run('set', [key, points, secDuration, options]);
72
+ }
73
+
74
+ _block(key, secDuration, options = {}) {
75
+ return this._run('block', [key, secDuration, options]);
76
+ }
77
+
78
+ _delete(key, options = {}) {
79
+ return this._run('delete', [key, options]);
80
+ }
81
+
82
+ }
@@ -0,0 +1,125 @@
1
+ module.exports = class RateLimiterAbstract {
2
+ /**
3
+ *
4
+ * @param opts Object Defaults {
5
+ * points: 4, // Number of points
6
+ * duration: 1, // Per seconds
7
+ * blockDuration: 0, // Block if consumed more than points in current duration for blockDuration seconds
8
+ * execEvenly: false, // Execute allowed actions evenly over duration
9
+ * execEvenlyMinDelayMs: duration * 1000 / points, // ms, works with execEvenly=true option
10
+ * keyPrefix: 'rlflx',
11
+ * }
12
+ */
13
+ constructor(opts = {}) {
14
+ this.points = opts.points;
15
+ this.duration = opts.duration;
16
+ this.blockDuration = opts.blockDuration;
17
+ this.execEvenly = opts.execEvenly;
18
+ this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs;
19
+ this.keyPrefix = opts.keyPrefix;
20
+ }
21
+
22
+ get points() {
23
+ return this._points;
24
+ }
25
+
26
+ set points(value) {
27
+ this._points = value >= 0 ? value : 4;
28
+ }
29
+
30
+ get duration() {
31
+ return this._duration;
32
+ }
33
+
34
+ set duration(value) {
35
+ this._duration = typeof value === 'undefined' ? 1 : value;
36
+ }
37
+
38
+ get msDuration() {
39
+ return this.duration * 1000;
40
+ }
41
+
42
+ get blockDuration() {
43
+ return this._blockDuration;
44
+ }
45
+
46
+ set blockDuration(value) {
47
+ this._blockDuration = typeof value === 'undefined' ? 0 : value;
48
+ }
49
+
50
+ get msBlockDuration() {
51
+ return this.blockDuration * 1000;
52
+ }
53
+
54
+ get execEvenly() {
55
+ return this._execEvenly;
56
+ }
57
+
58
+ set execEvenly(value) {
59
+ this._execEvenly = typeof value === 'undefined' ? false : Boolean(value);
60
+ }
61
+
62
+ get execEvenlyMinDelayMs() {
63
+ return this._execEvenlyMinDelayMs;
64
+ }
65
+
66
+ set execEvenlyMinDelayMs(value) {
67
+ this._execEvenlyMinDelayMs = typeof value === 'undefined' ? Math.ceil(this.msDuration / this.points) : value;
68
+ }
69
+
70
+ get keyPrefix() {
71
+ return this._keyPrefix;
72
+ }
73
+
74
+ set keyPrefix(value) {
75
+ if (typeof value === 'undefined') {
76
+ value = 'rlflx';
77
+ }
78
+ if (typeof value !== 'string') {
79
+ throw new Error('keyPrefix must be string');
80
+ }
81
+ this._keyPrefix = value;
82
+ }
83
+
84
+ _getKeySecDuration(options = {}) {
85
+ return options && options.customDuration >= 0
86
+ ? options.customDuration
87
+ : this.duration;
88
+ }
89
+
90
+ getKey(key) {
91
+ return this.keyPrefix.length > 0 ? `${this.keyPrefix}:${key}` : key;
92
+ }
93
+
94
+ parseKey(rlKey) {
95
+ return rlKey.substring(this.keyPrefix.length);
96
+ }
97
+
98
+ consume() {
99
+ throw new Error("You have to implement the method 'consume'!");
100
+ }
101
+
102
+ penalty() {
103
+ throw new Error("You have to implement the method 'penalty'!");
104
+ }
105
+
106
+ reward() {
107
+ throw new Error("You have to implement the method 'reward'!");
108
+ }
109
+
110
+ get() {
111
+ throw new Error("You have to implement the method 'get'!");
112
+ }
113
+
114
+ set() {
115
+ throw new Error("You have to implement the method 'set'!");
116
+ }
117
+
118
+ block() {
119
+ throw new Error("You have to implement the method 'block'!");
120
+ }
121
+
122
+ delete() {
123
+ throw new Error("You have to implement the method 'delete'!");
124
+ }
125
+ };