@blocklet/rate-limit 1.16.45-beta-20250626-115702-00b49b4c
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 +13 -0
- package/README.md +5 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.js +118 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2018-2025 ArcBlock
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Store, type Options, ClientRateLimitInfo } from 'express-rate-limit';
|
|
2
|
+
type RateLimitStoreOptions = {
|
|
3
|
+
windowMs: number;
|
|
4
|
+
prefix?: string;
|
|
5
|
+
redisUrl?: string;
|
|
6
|
+
sqlitePath?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Store for rate limit
|
|
10
|
+
*/
|
|
11
|
+
export declare class RateLimitStore implements Store {
|
|
12
|
+
private windowMs;
|
|
13
|
+
private dbCache;
|
|
14
|
+
constructor(options: RateLimitStoreOptions);
|
|
15
|
+
get(key: string): Promise<{
|
|
16
|
+
totalHits: number;
|
|
17
|
+
resetTime: Date;
|
|
18
|
+
}>;
|
|
19
|
+
set(key: string, limitInfo: ClientRateLimitInfo): Promise<void>;
|
|
20
|
+
increment(key: string): Promise<{
|
|
21
|
+
totalHits: number;
|
|
22
|
+
resetTime: Date;
|
|
23
|
+
}>;
|
|
24
|
+
decrement(key: string): Promise<void>;
|
|
25
|
+
resetKey(key: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* express-rate-limit middleware with custom store
|
|
29
|
+
*/
|
|
30
|
+
export declare function createRateLimiter(options: Partial<Options> & {
|
|
31
|
+
prefix?: string;
|
|
32
|
+
redisUrl?: string;
|
|
33
|
+
sqlitePath?: string;
|
|
34
|
+
}): import("express-rate-limit").RateLimitRequestHandler;
|
|
35
|
+
export {};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable require-await */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
4
|
+
/* eslint-disable @typescript-eslint/indent */
|
|
5
|
+
/* eslint-disable max-classes-per-file */
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.RateLimitStore = void 0;
|
|
11
|
+
exports.createRateLimiter = createRateLimiter;
|
|
12
|
+
const db_cache_1 = require("@abtnode/db-cache");
|
|
13
|
+
const express_rate_limit_1 = require("express-rate-limit");
|
|
14
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
/**
|
|
16
|
+
* Store for rate limit
|
|
17
|
+
*/
|
|
18
|
+
class RateLimitStore {
|
|
19
|
+
constructor(options) {
|
|
20
|
+
const serverUrls = (0, db_cache_1.getAbtNodeRedisAndSQLiteUrl)();
|
|
21
|
+
this.dbCache = new db_cache_1.DBCache(() => ({
|
|
22
|
+
prefix: `rate-limit-${options.prefix || 'default'}`,
|
|
23
|
+
ttl: options.windowMs || 1000 * 60,
|
|
24
|
+
redisUrl: options.redisUrl || serverUrls.redisUrl,
|
|
25
|
+
sqlitePath: options.sqlitePath || serverUrls.sqlitePath || node_path_1.default.join(process.env.BLOCKLET_APP_DATA_DIR, 'rate-limit.db'),
|
|
26
|
+
}));
|
|
27
|
+
this.windowMs = options.windowMs;
|
|
28
|
+
}
|
|
29
|
+
async get(key) {
|
|
30
|
+
try {
|
|
31
|
+
const row = (await this.dbCache.get(key));
|
|
32
|
+
return row
|
|
33
|
+
? {
|
|
34
|
+
totalHits: row.totalHits,
|
|
35
|
+
resetTime: new Date(row.resetTime),
|
|
36
|
+
}
|
|
37
|
+
: null;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error('[RateLimit] Error in get:', error);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async set(key, limitInfo) {
|
|
45
|
+
try {
|
|
46
|
+
await this.dbCache.set(key, {
|
|
47
|
+
totalHits: limitInfo.totalHits,
|
|
48
|
+
resetTime: limitInfo.resetTime.getTime(),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('[RateLimit] Error in set:', error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async increment(key) {
|
|
56
|
+
const defaultLimitInfo = {
|
|
57
|
+
totalHits: 1,
|
|
58
|
+
resetTime: new Date(Date.now() + this.windowMs),
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
let limitInfo = await this.get(key);
|
|
62
|
+
// reset row if expired
|
|
63
|
+
if (!limitInfo || limitInfo.resetTime.getTime() < Date.now()) {
|
|
64
|
+
limitInfo = defaultLimitInfo;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
limitInfo.totalHits += 1;
|
|
68
|
+
}
|
|
69
|
+
await this.set(key, limitInfo);
|
|
70
|
+
return limitInfo;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('[RateLimit] Error in increment:', error);
|
|
74
|
+
return defaultLimitInfo;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async decrement(key) {
|
|
78
|
+
try {
|
|
79
|
+
const row = await this.get(key);
|
|
80
|
+
if (row) {
|
|
81
|
+
await this.set(key, {
|
|
82
|
+
totalHits: Math.max(0, row.totalHits - 1),
|
|
83
|
+
resetTime: row.resetTime,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('[RateLimit] Error in decrement:', error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async resetKey(key) {
|
|
92
|
+
try {
|
|
93
|
+
await this.dbCache.del(key);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error('[RateLimit] Error in resetKey:', error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.RateLimitStore = RateLimitStore;
|
|
101
|
+
/**
|
|
102
|
+
* express-rate-limit middleware with custom store
|
|
103
|
+
*/
|
|
104
|
+
function createRateLimiter(options) {
|
|
105
|
+
const store = new RateLimitStore({
|
|
106
|
+
prefix: options.prefix,
|
|
107
|
+
windowMs: options.windowMs || 1000 * 60,
|
|
108
|
+
redisUrl: options.redisUrl,
|
|
109
|
+
sqlitePath: options.sqlitePath,
|
|
110
|
+
});
|
|
111
|
+
return (0, express_rate_limit_1.rateLimit)({
|
|
112
|
+
store,
|
|
113
|
+
windowMs: 1000 * 60,
|
|
114
|
+
limit: 10,
|
|
115
|
+
legacyHeaders: false,
|
|
116
|
+
...options,
|
|
117
|
+
});
|
|
118
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@blocklet/rate-limit",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "1.16.45-beta-20250626-115702-00b49b4c",
|
|
7
|
+
"description": "rate limit middleware",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
|
+
"typings": "lib/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"lib"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"verify": "npm run lint:fix && npm run test && npm run build",
|
|
15
|
+
"lint": "eslint src tests",
|
|
16
|
+
"lint:fix": "npm run lint -- --fix",
|
|
17
|
+
"test": "jest --forceExit --detectOpenHandles",
|
|
18
|
+
"coverage": "npm run test -- --coverage",
|
|
19
|
+
"clean": "rm -fr lib",
|
|
20
|
+
"prebuild": "npm run clean",
|
|
21
|
+
"build:blocklet-rate-limit": "npm run build",
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"build:watch": "npm run build -- -w"
|
|
24
|
+
},
|
|
25
|
+
"author": "blocklet<blocklet@arcblock.io>",
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@abtnode/db-cache": "1.16.45-beta-20250626-115702-00b49b4c",
|
|
29
|
+
"express-rate-limit": "^7.5.1"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
33
|
+
"@types/express": "^5.0.0",
|
|
34
|
+
"@types/jest": "^29.5.13",
|
|
35
|
+
"@types/json-stable-stringify": "^1.0.36",
|
|
36
|
+
"@types/node": "^22.7.5",
|
|
37
|
+
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
38
|
+
"@typescript-eslint/parser": "^5.42.0",
|
|
39
|
+
"detect-port": "^1.5.1",
|
|
40
|
+
"eslint": "^8.57.0",
|
|
41
|
+
"jest": "^29.7.0",
|
|
42
|
+
"json-stable-stringify": "^1.0.1",
|
|
43
|
+
"prettier": "^3.3.2",
|
|
44
|
+
"ts-jest": "^29.2.5",
|
|
45
|
+
"ts-node": "^10.9.1",
|
|
46
|
+
"typescript": "^5.6.3"
|
|
47
|
+
},
|
|
48
|
+
"gitHead": "8a70f88f034e2926185d4d0b9503ab8430a772a1"
|
|
49
|
+
}
|