@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.
- package/LICENSE.md +7 -0
- package/README.md +25 -0
- package/changes.json +5 -0
- package/index.js +55 -0
- package/lib/BurstyRateLimiter.js +78 -0
- package/lib/ExpressBruteFlexible.js +359 -0
- package/lib/RLWrapperBlackAndWhite.js +195 -0
- package/lib/RLWrapperTimeouts.js +82 -0
- package/lib/RateLimiterAbstract.js +125 -0
- package/lib/RateLimiterCluster.js +367 -0
- package/lib/RateLimiterDrizzle.js +174 -0
- package/lib/RateLimiterDrizzleNonAtomic.js +175 -0
- package/lib/RateLimiterDynamo.js +401 -0
- package/lib/RateLimiterEtcd.js +63 -0
- package/lib/RateLimiterEtcdNonAtomic.js +80 -0
- package/lib/RateLimiterInsuredAbstract.js +112 -0
- package/lib/RateLimiterMemcache.js +150 -0
- package/lib/RateLimiterMemory.js +106 -0
- package/lib/RateLimiterMongo.js +261 -0
- package/lib/RateLimiterMySQL.js +400 -0
- package/lib/RateLimiterPostgres.js +351 -0
- package/lib/RateLimiterPrisma.js +127 -0
- package/lib/RateLimiterQueue.js +131 -0
- package/lib/RateLimiterRedis.js +209 -0
- package/lib/RateLimiterRedisNonAtomic.js +195 -0
- package/lib/RateLimiterRes.js +64 -0
- package/lib/RateLimiterSQLite.js +338 -0
- package/lib/RateLimiterStoreAbstract.js +349 -0
- package/lib/RateLimiterUnion.js +51 -0
- package/lib/RateLimiterValkey.js +117 -0
- package/lib/RateLimiterValkeyGlide.js +273 -0
- package/lib/component/BlockedKeys/BlockedKeys.js +75 -0
- package/lib/component/BlockedKeys/index.js +3 -0
- package/lib/component/MemoryStorage/MemoryStorage.js +83 -0
- package/lib/component/MemoryStorage/Record.js +40 -0
- package/lib/component/MemoryStorage/index.js +3 -0
- package/lib/component/RateLimiterEtcdTransactionFailedError.js +10 -0
- package/lib/component/RateLimiterQueueError.js +13 -0
- package/lib/component/RateLimiterSetupError.js +10 -0
- package/lib/constants.js +21 -0
- package/package.json +100 -0
- package/types.d.ts +581 -0
package/lib/constants.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const LIMITER_TYPES = {
|
|
2
|
+
MEMORY: 'memory',
|
|
3
|
+
CLUSTER: 'cluster',
|
|
4
|
+
MEMCACHE: 'memcache',
|
|
5
|
+
MONGO: 'mongo',
|
|
6
|
+
REDIS: 'redis',
|
|
7
|
+
MYSQL: 'mysql',
|
|
8
|
+
POSTGRES: 'postgres',
|
|
9
|
+
DYNAMO: 'dynamo',
|
|
10
|
+
PRISMA: 'prisma',
|
|
11
|
+
SQLITE: 'sqlite',
|
|
12
|
+
VALKEY: 'valkey',
|
|
13
|
+
VALKEY_GLIDE: 'valkey-glide',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const ERR_UNKNOWN_LIMITER_TYPE_MESSAGE = 'Unknown limiter type. Use one of LIMITER_TYPES constants.';
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
LIMITER_TYPES,
|
|
20
|
+
ERR_UNKNOWN_LIMITER_TYPE_MESSAGE,
|
|
21
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@depup/rate-limiter-flexible",
|
|
3
|
+
"version": "9.1.1-depup.0",
|
|
4
|
+
"description": "[DepUp] Node.js atomic and non-atomic counters, rate limiting tools, protection from DoS and brute-force attacks at scale",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dc:up": "docker-compose -f docker-compose.yml up -d",
|
|
8
|
+
"dc:down": "docker-compose -f docker-compose.yml down",
|
|
9
|
+
"valkey-cluster:up": "docker-compose -f docker-compose.valkey-cluster.yml up -d",
|
|
10
|
+
"valkey-cluster:down": "docker-compose -f docker-compose.valkey-cluster.yml down -v",
|
|
11
|
+
"test:valkey-cluster": "VALKEY_CLUSTER_PORT=7001 mocha test/RateLimiterValkeyGlide.test.js -- -g 'RateLimiterValkeyGlide with cluster client'",
|
|
12
|
+
"prisma:postgres": "prisma generate --schema=./test/RateLimiterPrisma/Postgres/schema.prisma && prisma db push --schema=./test/RateLimiterPrisma/Postgres/schema.prisma",
|
|
13
|
+
"drizzle:postgres": "cd ./test/RateLimiterDrizzle/Postgres && drizzle-kit push",
|
|
14
|
+
"test": "npm run prisma:postgres && npm run drizzle:postgres && nyc --reporter=html --reporter=text mocha \"test/**/*.test.js\"",
|
|
15
|
+
"debug-test": "mocha --inspect-brk lib/**/**.test.js",
|
|
16
|
+
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
|
17
|
+
"eslint": "eslint --quiet lib/**/**.js test/**/**.js",
|
|
18
|
+
"eslint-fix": "eslint --fix lib/**/**.js test/**/**.js"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/animir/node-rate-limiter-flexible.git"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"depup",
|
|
26
|
+
"dependency-bumped",
|
|
27
|
+
"updated-deps",
|
|
28
|
+
"rate-limiter-flexible",
|
|
29
|
+
"ratelimter",
|
|
30
|
+
"authorization",
|
|
31
|
+
"security",
|
|
32
|
+
"rate",
|
|
33
|
+
"limit",
|
|
34
|
+
"bruteforce",
|
|
35
|
+
"throttle",
|
|
36
|
+
"redis",
|
|
37
|
+
"mongodb",
|
|
38
|
+
"dynamodb",
|
|
39
|
+
"mysql",
|
|
40
|
+
"postgres",
|
|
41
|
+
"prisma",
|
|
42
|
+
"drizzle",
|
|
43
|
+
"koa",
|
|
44
|
+
"express",
|
|
45
|
+
"hapi",
|
|
46
|
+
"valkey",
|
|
47
|
+
"valkey-glide",
|
|
48
|
+
"GLIDE",
|
|
49
|
+
"cluster",
|
|
50
|
+
"memcached"
|
|
51
|
+
],
|
|
52
|
+
"author": "animir <animirr@gmail.com>",
|
|
53
|
+
"license": "ISC",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/animir/node-rate-limiter-flexible/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/animir/node-rate-limiter-flexible#readme",
|
|
58
|
+
"types": "./types.d.ts",
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@aws-sdk/client-dynamodb": "^3.431.0",
|
|
61
|
+
"@prisma/client": "^5.8.0",
|
|
62
|
+
"@valkey/valkey-glide": "^1.3.1",
|
|
63
|
+
"better-sqlite3": "^11.9.0",
|
|
64
|
+
"chai": "^4.1.2",
|
|
65
|
+
"coveralls": "^3.0.1",
|
|
66
|
+
"drizzle-kit": "^0.31.4",
|
|
67
|
+
"drizzle-orm": "^0.44.3",
|
|
68
|
+
"eslint": "^4.19.1",
|
|
69
|
+
"eslint-config-airbnb-base": "^12.1.0",
|
|
70
|
+
"eslint-plugin-import": "^2.7.0",
|
|
71
|
+
"eslint-plugin-node": "^6.0.1",
|
|
72
|
+
"eslint-plugin-security": "^1.4.0",
|
|
73
|
+
"etcd3": "^1.1.2",
|
|
74
|
+
"ioredis": "^5.3.2",
|
|
75
|
+
"iovalkey": "^0.3.1",
|
|
76
|
+
"istanbul": "^1.1.0-alpha.1",
|
|
77
|
+
"knex": "^3.1.0",
|
|
78
|
+
"memcached-mock": "^0.1.0",
|
|
79
|
+
"mocha": "^10.2.0",
|
|
80
|
+
"nyc": "^15.1.0",
|
|
81
|
+
"pg": "^8.16.3",
|
|
82
|
+
"prisma": "^5.8.0",
|
|
83
|
+
"redis": "^4.6.8",
|
|
84
|
+
"redis-mock": "^0.48.0",
|
|
85
|
+
"sinon": "^17.0.1",
|
|
86
|
+
"sqlite3": "^5.1.7"
|
|
87
|
+
},
|
|
88
|
+
"browser": {
|
|
89
|
+
"cluster": false,
|
|
90
|
+
"crypto": false
|
|
91
|
+
},
|
|
92
|
+
"depup": {
|
|
93
|
+
"changes": {},
|
|
94
|
+
"depsUpdated": 0,
|
|
95
|
+
"originalPackage": "rate-limiter-flexible",
|
|
96
|
+
"originalVersion": "9.1.1",
|
|
97
|
+
"processedAt": "2026-03-09T05:24:58.594Z",
|
|
98
|
+
"smokeTest": "passed"
|
|
99
|
+
}
|
|
100
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
export interface IRateLimiterRes {
|
|
2
|
+
msBeforeNext?: number;
|
|
3
|
+
remainingPoints?: number;
|
|
4
|
+
consumedPoints?: number;
|
|
5
|
+
isFirstInDuration?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class RateLimiterRes {
|
|
9
|
+
constructor(
|
|
10
|
+
remainingPoints?: number,
|
|
11
|
+
msBeforeNext?: number,
|
|
12
|
+
consumedPoints?: number,
|
|
13
|
+
isFirstInDuration?: boolean
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
readonly msBeforeNext: number;
|
|
17
|
+
readonly remainingPoints: number;
|
|
18
|
+
readonly consumedPoints: number;
|
|
19
|
+
readonly isFirstInDuration: boolean;
|
|
20
|
+
|
|
21
|
+
toString(): string;
|
|
22
|
+
toJSON(): {
|
|
23
|
+
remainingPoints: number;
|
|
24
|
+
msBeforeNext: number;
|
|
25
|
+
consumedPoints: number;
|
|
26
|
+
isFirstInDuration: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class RateLimiterAbstract {
|
|
31
|
+
constructor(opts: IRateLimiterOptions);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Maximum number of points can be consumed over duration. Limiter compares this number with
|
|
35
|
+
* number of consumed points by key to decide if an operation should be rejected or resolved.
|
|
36
|
+
*/
|
|
37
|
+
points: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Number of seconds before consumed points are reset.
|
|
41
|
+
* Keys never expire, if duration is 0.
|
|
42
|
+
*/
|
|
43
|
+
duration: number;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* duration in milliseconds
|
|
47
|
+
*/
|
|
48
|
+
get msDuration(): number;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* If positive number and consumed more than points in current duration, block for blockDuration
|
|
52
|
+
* seconds.
|
|
53
|
+
*/
|
|
54
|
+
blockDuration: number;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* blockDuration in milliseconds
|
|
58
|
+
*/
|
|
59
|
+
get msBlockDuration(): number;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Delay action to be executed evenly over duration First action in duration is executed without
|
|
63
|
+
* delay. All next allowed actions in current duration are delayed by formula
|
|
64
|
+
* msBeforeDurationEnd / (remainingPoints + 2) with minimum delay of duration * 1000 / points.
|
|
65
|
+
* It allows to cut off load peaks similar way to Leaky Bucket.
|
|
66
|
+
*
|
|
67
|
+
* Note: it isn't recommended to use it for long duration and few points, as it may delay action
|
|
68
|
+
* for too long with default execEvenlyMinDelayMs.
|
|
69
|
+
*/
|
|
70
|
+
execEvenly: boolean;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sets minimum delay in milliseconds, when action is delayed with execEvenly
|
|
74
|
+
*/
|
|
75
|
+
execEvenlyMinDelayMs: number;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* If you need to create several limiters for different purpose.
|
|
79
|
+
* Set to empty string '', if keys should be stored without prefix.
|
|
80
|
+
*/
|
|
81
|
+
keyPrefix: string;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Returns internal key prefixed with keyPrefix option as it is saved in store.
|
|
85
|
+
*/
|
|
86
|
+
getKey(key: string | number): string;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns internal key without the keyPrefix.
|
|
90
|
+
*/
|
|
91
|
+
parseKey(rlKey: string): string;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param key is usually IP address or some unique client id
|
|
95
|
+
* @param pointsToConsume number of points consumed. default: 1
|
|
96
|
+
* @param options is object with additional settings:
|
|
97
|
+
* - customDuration expire in seconds for this operation only overwrites limiter's duration. It doesn't work, if key already created.
|
|
98
|
+
* @returns Returns Promise, which:
|
|
99
|
+
* - `resolved` with `RateLimiterRes` when point(s) is consumed, so action can be done
|
|
100
|
+
* - `rejected` only for store and database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
101
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
102
|
+
* - `rejected` when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object
|
|
103
|
+
* - `rejected` when key is blocked (if block strategy is set up), where reject reason `rejRes` is `RateLimiterRes` object
|
|
104
|
+
*/
|
|
105
|
+
consume(
|
|
106
|
+
key: string | number,
|
|
107
|
+
pointsToConsume?: number,
|
|
108
|
+
options?: { [key: string]: any }
|
|
109
|
+
): Promise<RateLimiterRes>;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Fine key by points number of points for one duration.
|
|
113
|
+
*
|
|
114
|
+
* Note: Depending on time penalty may go to next durations
|
|
115
|
+
*
|
|
116
|
+
* @returns Returns Promise, which:
|
|
117
|
+
* - `resolved` with RateLimiterRes
|
|
118
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
119
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
120
|
+
*/
|
|
121
|
+
penalty(
|
|
122
|
+
key: string | number,
|
|
123
|
+
points?: number,
|
|
124
|
+
options?: { [key: string]: any }
|
|
125
|
+
): Promise<RateLimiterRes>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Reward key by points number of points for one duration.
|
|
129
|
+
* Note: Depending on time reward may go to next durations
|
|
130
|
+
* @returns Promise, which:
|
|
131
|
+
* - `resolved` with RateLimiterRes
|
|
132
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
133
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
134
|
+
*/
|
|
135
|
+
reward(
|
|
136
|
+
key: string | number,
|
|
137
|
+
points?: number,
|
|
138
|
+
options?: { [key: string]: any }
|
|
139
|
+
): Promise<RateLimiterRes>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get RateLimiterRes in current duration. It always returns RateLimiterRes.isFirstInDuration=false.
|
|
143
|
+
* @param key is usually IP address or some unique client id
|
|
144
|
+
* @param options
|
|
145
|
+
* @returns Promise, which:
|
|
146
|
+
* - `resolved` with RateLimiterRes if key is set
|
|
147
|
+
* - `resolved` with null if key is NOT set or expired
|
|
148
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
149
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
150
|
+
*/
|
|
151
|
+
get(
|
|
152
|
+
key: string | number,
|
|
153
|
+
options?: { [key: string]: any }
|
|
154
|
+
): Promise<RateLimiterRes | null>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Set points to key for secDuration seconds.
|
|
158
|
+
* Store it forever, if secDuration is 0.
|
|
159
|
+
* @param key
|
|
160
|
+
* @param points
|
|
161
|
+
* @param secDuration
|
|
162
|
+
* @param options
|
|
163
|
+
* @returns Promise, which:
|
|
164
|
+
* - `resolved` with RateLimiterRes
|
|
165
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
166
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
167
|
+
*/
|
|
168
|
+
set(
|
|
169
|
+
key: string | number,
|
|
170
|
+
points: number,
|
|
171
|
+
secDuration: number,
|
|
172
|
+
options?: { [key: string]: any }
|
|
173
|
+
): Promise<RateLimiterRes>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Block key by setting consumed points to points + 1 for secDuration seconds.
|
|
177
|
+
*
|
|
178
|
+
* It force updates expire, if there is already key.
|
|
179
|
+
*
|
|
180
|
+
* Blocked key never expires, if secDuration is 0.
|
|
181
|
+
* @returns Promise, which:
|
|
182
|
+
* - `resolved` with RateLimiterRes
|
|
183
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
184
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
185
|
+
*/
|
|
186
|
+
block(
|
|
187
|
+
key: string | number,
|
|
188
|
+
secDuration: number,
|
|
189
|
+
options?: { [key: string]: any }
|
|
190
|
+
): Promise<RateLimiterRes>;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Delete all data related to key.
|
|
194
|
+
*
|
|
195
|
+
* For example, previously blocked key is not blocked after delete as there is no data anymore.
|
|
196
|
+
* @returns Promise, which:
|
|
197
|
+
* - `resolved` with boolean, true if data is removed by key, false if there is no such key.
|
|
198
|
+
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
|
|
199
|
+
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
|
|
200
|
+
*/
|
|
201
|
+
delete(
|
|
202
|
+
key: string | number,
|
|
203
|
+
options?: { [key: string]: any }
|
|
204
|
+
): Promise<boolean>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export class RateLimiterInsuredAbstract extends RateLimiterAbstract {
|
|
208
|
+
constructor(opts: IRateLimiterOptions);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export class RateLimiterStoreAbstract extends RateLimiterInsuredAbstract {
|
|
212
|
+
constructor(opts: IRateLimiterStoreOptions);
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Cleanup keys blocked in current process memory
|
|
216
|
+
*/
|
|
217
|
+
deleteInMemoryBlockedAll(): void;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
interface IRateLimiterOptions {
|
|
221
|
+
keyPrefix?: string;
|
|
222
|
+
points?: number;
|
|
223
|
+
duration?: number;
|
|
224
|
+
execEvenly?: boolean;
|
|
225
|
+
execEvenlyMinDelayMs?: number;
|
|
226
|
+
blockDuration?: number;
|
|
227
|
+
insuranceLimiter?: RateLimiterAbstract;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface IRateLimiterClusterOptions extends IRateLimiterOptions {
|
|
231
|
+
timeoutMs?: number;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
interface IRateLimiterStoreOptions extends IRateLimiterOptions {
|
|
235
|
+
storeClient: any;
|
|
236
|
+
storeType?: string;
|
|
237
|
+
inMemoryBlockOnConsumed?: number;
|
|
238
|
+
inMemoryBlockDuration?: number;
|
|
239
|
+
insuranceLimiter?: RateLimiterAbstract;
|
|
240
|
+
dbName?: string;
|
|
241
|
+
tableName?: string;
|
|
242
|
+
tableCreated?: boolean;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
interface IRateLimiterStoreNoAutoExpiryOptions extends IRateLimiterStoreOptions {
|
|
246
|
+
clearExpiredByTimeout?: boolean;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
interface IRateLimiterStoreNoAutoExpiryOptionsAndSchema extends IRateLimiterStoreNoAutoExpiryOptions {
|
|
250
|
+
schema: any;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
interface IRateLimiterMongoOptions extends IRateLimiterStoreOptions {
|
|
254
|
+
indexKeyPrefix?: {
|
|
255
|
+
[key: string]: any;
|
|
256
|
+
};
|
|
257
|
+
disableIndexesCreation?: boolean;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
interface IRateLimiterPostgresOptions extends IRateLimiterStoreNoAutoExpiryOptions {
|
|
261
|
+
schemaName?: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
interface IRateLimiterRedisOptions extends IRateLimiterStoreOptions {
|
|
265
|
+
rejectIfRedisNotReady?: boolean;
|
|
266
|
+
useRedisPackage?: boolean;
|
|
267
|
+
useRedis3AndLowerPackage?: boolean;
|
|
268
|
+
customIncrTtlLuaScript?: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
interface IRateLimiterValkeyOptions extends IRateLimiterStoreOptions {
|
|
272
|
+
customIncrTtlLuaScript?: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
interface ICallbackReady {
|
|
276
|
+
(error?: Error): void;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
interface IRLWrapperBlackAndWhiteOptions {
|
|
280
|
+
limiter: RateLimiterAbstract;
|
|
281
|
+
blackList?: string[] | number[];
|
|
282
|
+
whiteList?: string[] | number[];
|
|
283
|
+
isBlackListed?(key: any): boolean;
|
|
284
|
+
isWhiteListed?(key: any): boolean;
|
|
285
|
+
runActionAnyway?: boolean;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export class RateLimiterMemory extends RateLimiterAbstract {
|
|
289
|
+
constructor(opts: IRateLimiterOptions);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export class RateLimiterCluster extends RateLimiterAbstract {
|
|
293
|
+
constructor(opts: IRateLimiterClusterOptions);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export class RateLimiterClusterMaster {
|
|
297
|
+
constructor();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export class RateLimiterClusterMasterPM2 {
|
|
301
|
+
constructor(pm2: any);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export class RateLimiterRedis extends RateLimiterStoreAbstract {
|
|
305
|
+
constructor(opts: IRateLimiterRedisOptions);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export class RateLimiterRedisNonAtomic extends RateLimiterStoreAbstract {
|
|
309
|
+
constructor(opts: IRateLimiterRedisOptions);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export class RateLimiterValkey extends RateLimiterStoreAbstract {
|
|
313
|
+
constructor(opts: IRateLimiterValkeyOptions);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface IRateLimiterMongoFunctionOptions {
|
|
317
|
+
attrs: { [key: string]: any };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export class RateLimiterMongo extends RateLimiterStoreAbstract {
|
|
321
|
+
constructor(opts: IRateLimiterMongoOptions);
|
|
322
|
+
indexKeyPrefix(): Object;
|
|
323
|
+
indexKeyPrefix(obj?: Object): void;
|
|
324
|
+
|
|
325
|
+
createIndexes(): Promise<void>;
|
|
326
|
+
|
|
327
|
+
consume(
|
|
328
|
+
key: string | number,
|
|
329
|
+
pointsToConsume?: number,
|
|
330
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
331
|
+
): Promise<RateLimiterRes>;
|
|
332
|
+
|
|
333
|
+
penalty(
|
|
334
|
+
key: string | number,
|
|
335
|
+
points?: number,
|
|
336
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
337
|
+
): Promise<RateLimiterRes>;
|
|
338
|
+
|
|
339
|
+
reward(
|
|
340
|
+
key: string | number,
|
|
341
|
+
points?: number,
|
|
342
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
343
|
+
): Promise<RateLimiterRes>;
|
|
344
|
+
|
|
345
|
+
block(
|
|
346
|
+
key: string | number,
|
|
347
|
+
secDuration: number,
|
|
348
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
349
|
+
): Promise<RateLimiterRes>;
|
|
350
|
+
|
|
351
|
+
get(
|
|
352
|
+
key: string | number,
|
|
353
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
354
|
+
): Promise<RateLimiterRes | null>;
|
|
355
|
+
|
|
356
|
+
set(
|
|
357
|
+
key: string | number,
|
|
358
|
+
points: number,
|
|
359
|
+
secDuration: number,
|
|
360
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
361
|
+
): Promise<RateLimiterRes>;
|
|
362
|
+
|
|
363
|
+
delete(
|
|
364
|
+
key: string | number,
|
|
365
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
366
|
+
): Promise<boolean>;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export class RateLimiterMySQL extends RateLimiterStoreAbstract {
|
|
370
|
+
constructor(opts: IRateLimiterStoreNoAutoExpiryOptions, cb?: ICallbackReady);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export class RateLimiterPostgres extends RateLimiterStoreAbstract {
|
|
374
|
+
constructor(opts: IRateLimiterPostgresOptions, cb?: ICallbackReady);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export class RateLimiterSQLite extends RateLimiterStoreAbstract {
|
|
378
|
+
constructor(opts: IRateLimiterStoreNoAutoExpiryOptions, cb?: ICallbackReady);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export class RateLimiterPrisma extends RateLimiterStoreAbstract {
|
|
382
|
+
constructor(opts: IRateLimiterStoreNoAutoExpiryOptions, cb?: ICallbackReady);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export class RateLimiterDrizzle extends RateLimiterStoreAbstract {
|
|
386
|
+
constructor(opts: IRateLimiterStoreNoAutoExpiryOptionsAndSchema, cb?: ICallbackReady);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export class RateLimiterDrizzleNonAtomic extends RateLimiterStoreAbstract {
|
|
390
|
+
constructor(opts: IRateLimiterStoreNoAutoExpiryOptionsAndSchema, cb?: ICallbackReady);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export class RateLimiterMemcache extends RateLimiterStoreAbstract { }
|
|
394
|
+
|
|
395
|
+
export class RateLimiterUnion {
|
|
396
|
+
constructor(...limiters: RateLimiterAbstract[]);
|
|
397
|
+
|
|
398
|
+
consume(key: string | number, points?: number): Promise<Record<string, RateLimiterRes>>;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export class RLWrapperBlackAndWhite extends RateLimiterAbstract {
|
|
402
|
+
constructor(opts: IRLWrapperBlackAndWhiteOptions);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
interface IRLWrapperTimeoutsOptions extends IRateLimiterOptions {
|
|
406
|
+
limiter: RateLimiterAbstract;
|
|
407
|
+
timeoutMs?: number;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
|
|
411
|
+
constructor(opts: IRLWrapperTimeoutsOptions);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
interface IRateLimiterQueueOpts {
|
|
415
|
+
maxQueueSize?: number;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export class RateLimiterQueue {
|
|
419
|
+
constructor(
|
|
420
|
+
limiterFlexible: RateLimiterAbstract | BurstyRateLimiter,
|
|
421
|
+
opts?: IRateLimiterQueueOpts
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
getTokensRemaining(key?: string | number): Promise<number>;
|
|
425
|
+
|
|
426
|
+
removeTokens(tokens: number, key?: string | number): Promise<number>;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export class BurstyRateLimiter {
|
|
430
|
+
constructor(
|
|
431
|
+
rateLimiter: RateLimiterAbstract,
|
|
432
|
+
burstLimiter: RateLimiterAbstract
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
consume(
|
|
436
|
+
key: string | number,
|
|
437
|
+
pointsToConsume?: number,
|
|
438
|
+
options?: IRateLimiterMongoFunctionOptions
|
|
439
|
+
): Promise<RateLimiterRes>;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
interface IRateLimiterDynamoOptions extends IRateLimiterStoreOptions {
|
|
443
|
+
dynamoTableOpts?: {
|
|
444
|
+
readCapacityUnits: number;
|
|
445
|
+
writeCapacityUnits: number;
|
|
446
|
+
};
|
|
447
|
+
ttlSet?: boolean;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export class RateLimiterDynamo extends RateLimiterStoreAbstract {
|
|
451
|
+
constructor(opts: IRateLimiterDynamoOptions, cb?: ICallbackReady);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Options for RateLimiterValkeyGlide
|
|
456
|
+
*/
|
|
457
|
+
interface IRateLimiterValkeyGlideOptions extends IRateLimiterStoreOptions {
|
|
458
|
+
/**
|
|
459
|
+
* Valkey Glide client instance (GlideClient or GlideClusterClient)
|
|
460
|
+
*/
|
|
461
|
+
storeClient: any; // GlideClient | GlideClusterClient;
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Whether to reject requests if Valkey is not ready
|
|
465
|
+
* @default false
|
|
466
|
+
*/
|
|
467
|
+
rejectIfValkeyNotReady?: boolean;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Custom Lua script for rate limiting logic.
|
|
471
|
+
* Must accept parameters:
|
|
472
|
+
* - KEYS[1]: The key being rate limited
|
|
473
|
+
* - ARGV[1]: Points to consume (as string, use tonumber() to convert)
|
|
474
|
+
* - ARGV[2]: Duration in seconds (as string, use tonumber() to convert)
|
|
475
|
+
*
|
|
476
|
+
* Must return an array with exactly two elements:
|
|
477
|
+
* - [0]: Consumed points (number)
|
|
478
|
+
* - [1]: TTL in milliseconds (number)
|
|
479
|
+
*/
|
|
480
|
+
customFunction?: string;
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Custom name for the function library, defaults to 'ratelimiter'.
|
|
484
|
+
* The name is used to identify the library of the Lua function.
|
|
485
|
+
* A custom name should be used only if you want to use different
|
|
486
|
+
* libraries for different rate limiters.
|
|
487
|
+
* @default 'ratelimiter'
|
|
488
|
+
*/
|
|
489
|
+
customFunctionLibName?: string;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Rate limiter that uses Valkey Glide client for storage
|
|
494
|
+
*/
|
|
495
|
+
export class RateLimiterValkeyGlide extends RateLimiterStoreAbstract {
|
|
496
|
+
/**
|
|
497
|
+
* Creates a new instance of RateLimiterValkeyGlide
|
|
498
|
+
*
|
|
499
|
+
* @param opts Configuration options
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```typescript
|
|
503
|
+
* // Basic usage
|
|
504
|
+
* const rateLimiter = new RateLimiterValkeyGlide({
|
|
505
|
+
* storeClient: glideClient,
|
|
506
|
+
* points: 5,
|
|
507
|
+
* duration: 1
|
|
508
|
+
* });
|
|
509
|
+
*
|
|
510
|
+
* // With custom Lua function
|
|
511
|
+
* const customScript = `local key = KEYS[1]
|
|
512
|
+
* local pointsToConsume = tonumber(ARGV[1]) or 0
|
|
513
|
+
* local secDuration = tonumber(ARGV[2]) or 0
|
|
514
|
+
*
|
|
515
|
+
* -- Custom implementation
|
|
516
|
+
* -- ...
|
|
517
|
+
*
|
|
518
|
+
* -- Must return exactly two values: [consumed_points, ttl_in_ms]
|
|
519
|
+
* return {consumed, ttl}`;
|
|
520
|
+
*
|
|
521
|
+
* const rateLimiter = new RateLimiterValkeyGlide({
|
|
522
|
+
* storeClient: glideClient,
|
|
523
|
+
* points: 5,
|
|
524
|
+
* customFunction: customScript
|
|
525
|
+
* });
|
|
526
|
+
*
|
|
527
|
+
* // With insurance limiter
|
|
528
|
+
* const rateLimiter = new RateLimiterValkeyGlide({
|
|
529
|
+
* storeClient: primaryGlideClient,
|
|
530
|
+
* points: 5,
|
|
531
|
+
* duration: 2,
|
|
532
|
+
* insuranceLimiter: new RateLimiterMemory({
|
|
533
|
+
* points: 5,
|
|
534
|
+
* duration: 2
|
|
535
|
+
* })
|
|
536
|
+
* });
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
constructor(opts: IRateLimiterValkeyGlideOptions);
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Close the rate limiter and release resources
|
|
543
|
+
* Note: The method won't close the Valkey client, as it may be shared with other instances.
|
|
544
|
+
*
|
|
545
|
+
* @returns Promise that resolves when the rate limiter is closed
|
|
546
|
+
*/
|
|
547
|
+
close(): Promise<void>;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Etcd Rate Limiter class.
|
|
552
|
+
*
|
|
553
|
+
* The option "storeClient" needs to be set to an instance of class "EtcdClient".
|
|
554
|
+
*/
|
|
555
|
+
export class RateLimiterEtcd extends RateLimiterEtcdNonAtomic {
|
|
556
|
+
constructor(opts: IRateLimiterStoreOptions);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Non-Atomic Etcd Rate Limiter class.
|
|
561
|
+
*
|
|
562
|
+
* The option "storeClient" needs to be set to an instance of class "EtcdClient".
|
|
563
|
+
*/
|
|
564
|
+
export class RateLimiterEtcdNonAtomic extends RateLimiterStoreAbstract {
|
|
565
|
+
constructor(opts: IRateLimiterStoreOptions);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export class RateLimiterQueueError extends Error {
|
|
569
|
+
constructor(message?: string, extra?: string);
|
|
570
|
+
|
|
571
|
+
readonly name: string;
|
|
572
|
+
readonly message: string;
|
|
573
|
+
readonly extra: string;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export class RateLimiterEtcdTransactionFailedError extends Error {
|
|
577
|
+
constructor(message?: string);
|
|
578
|
+
|
|
579
|
+
readonly name: string;
|
|
580
|
+
readonly message: string;
|
|
581
|
+
}
|