ayiin 2.0.52 → 2.0.54
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/dist/methods/limiter.d.ts +3 -2
- package/dist/methods/limiter.js +27 -12
- package/dist/methods/response.d.ts +18 -34
- package/dist/methods/response.js +20 -4
- package/dist/types.d.ts +6 -0
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { RequestHandler } from "express";
|
|
2
2
|
import { RateLimiterOptions } from "../types";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
declare class Limiter {
|
|
4
|
+
private dates;
|
|
5
|
+
private api;
|
|
5
6
|
createRateLimit: (options: RateLimiterOptions) => RequestHandler;
|
|
6
7
|
}
|
|
7
8
|
export default Limiter;
|
package/dist/methods/limiter.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const dates_1 = __importDefault(require("./dates"));
|
|
7
|
+
const response_1 = __importDefault(require("./response"));
|
|
7
8
|
// 🔹 MemoryStore default
|
|
8
9
|
class MemoryStore {
|
|
9
10
|
store = new Map();
|
|
@@ -44,7 +45,9 @@ class MemoryStore {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
// 🔹 Class Limiter
|
|
47
|
-
class Limiter
|
|
48
|
+
class Limiter {
|
|
49
|
+
dates = new dates_1.default();
|
|
50
|
+
api = new response_1.default();
|
|
48
51
|
createRateLimit = (options) => {
|
|
49
52
|
const store = options.store ?? new MemoryStore();
|
|
50
53
|
if (options.refreshOnStart) {
|
|
@@ -76,27 +79,33 @@ class Limiter extends dates_1.default {
|
|
|
76
79
|
? options.messageFormat({
|
|
77
80
|
api: options.keyPrefix,
|
|
78
81
|
remainMs: remainingMs,
|
|
79
|
-
remain: this.formatRemainingTime(remainingMs),
|
|
82
|
+
remain: this.dates.formatRemainingTime(remainingMs),
|
|
80
83
|
})
|
|
81
84
|
: (options.messageFormat ??
|
|
82
|
-
`[FloodWait] - Silakan coba lagi dalam ${this.formatRemainingTime(remainingMs)}.`);
|
|
85
|
+
`[FloodWait] - Silakan coba lagi dalam ${this.dates.formatRemainingTime(remainingMs)}.`);
|
|
83
86
|
return res
|
|
84
87
|
.status(429)
|
|
85
|
-
.json({
|
|
88
|
+
.json(this.api.floodWait({
|
|
89
|
+
caption: msg,
|
|
90
|
+
data: {
|
|
91
|
+
seconds: remainingMs,
|
|
92
|
+
formatted: this.dates.formatRemainingTime(remainingMs),
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
// ambil level sekarang
|
|
89
98
|
let level = parseInt((await store.get(levelKey)) ?? "0", 10);
|
|
90
|
-
const refreshAtMs = this.toMilliseconds(options.refreshAt ?? { hours: 24 });
|
|
99
|
+
const refreshAtMs = this.dates.toMilliseconds(options.refreshAt ?? { hours: 24 });
|
|
91
100
|
// tentukan windowMs sesuai level
|
|
92
101
|
let windowMs;
|
|
93
102
|
if (Array.isArray(options.windowMs)) {
|
|
94
103
|
const idx = Math.min(level, options.windowMs.length - 1);
|
|
95
104
|
const win = options.windowMs[idx];
|
|
96
|
-
windowMs = this.toMilliseconds(win);
|
|
105
|
+
windowMs = this.dates.toMilliseconds(win);
|
|
97
106
|
}
|
|
98
107
|
else {
|
|
99
|
-
windowMs = this.toMilliseconds(options.windowMs);
|
|
108
|
+
windowMs = this.dates.toMilliseconds(options.windowMs);
|
|
100
109
|
}
|
|
101
110
|
// hitung permintaan sekarang
|
|
102
111
|
const hits = await store.incr(rateKey);
|
|
@@ -122,10 +131,10 @@ class Limiter extends dates_1.default {
|
|
|
122
131
|
if (Array.isArray(options.floodwaitMs)) {
|
|
123
132
|
const idx = Math.min(level - 1, options.floodwaitMs.length - 1);
|
|
124
133
|
const floodwait = options.floodwaitMs[idx];
|
|
125
|
-
floodwaitMs = this.toMilliseconds(floodwait ?? options.floodwaitMs[0]);
|
|
134
|
+
floodwaitMs = this.dates.toMilliseconds(floodwait ?? options.floodwaitMs[0]);
|
|
126
135
|
}
|
|
127
136
|
else {
|
|
128
|
-
floodwaitMs = this.toMilliseconds(options.floodwaitMs);
|
|
137
|
+
floodwaitMs = this.dates.toMilliseconds(options.floodwaitMs);
|
|
129
138
|
}
|
|
130
139
|
const untilDate = new Date(now + floodwaitMs).toISOString();
|
|
131
140
|
await store.set(floodKey, untilDate, floodwaitMs);
|
|
@@ -133,13 +142,19 @@ class Limiter extends dates_1.default {
|
|
|
133
142
|
? options.messageFormat({
|
|
134
143
|
api: options.keyPrefix,
|
|
135
144
|
remainMs: floodwaitMs,
|
|
136
|
-
remain: this.formatRemainingTime(floodwaitMs),
|
|
145
|
+
remain: this.dates.formatRemainingTime(floodwaitMs),
|
|
137
146
|
})
|
|
138
147
|
: (options.messageFormat ??
|
|
139
|
-
`[FloodWait] - Terlalu banyak permintaan. Silakan coba lagi dalam ${this.formatRemainingTime(floodwaitMs)}.`);
|
|
148
|
+
`[FloodWait] - Terlalu banyak permintaan. Silakan coba lagi dalam ${this.dates.formatRemainingTime(floodwaitMs)}.`);
|
|
140
149
|
return res
|
|
141
150
|
.status(429)
|
|
142
|
-
.json({
|
|
151
|
+
.json(this.api.floodWait({
|
|
152
|
+
caption: msg,
|
|
153
|
+
data: {
|
|
154
|
+
seconds: floodwaitMs,
|
|
155
|
+
formatted: this.dates.formatRemainingTime(floodwaitMs),
|
|
156
|
+
},
|
|
157
|
+
}));
|
|
143
158
|
}
|
|
144
159
|
next();
|
|
145
160
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ResponseJson } from "../types";
|
|
1
2
|
declare class ResponseApi {
|
|
2
3
|
success: ({ caption, data, code, }: {
|
|
3
4
|
caption: string;
|
|
@@ -13,47 +14,30 @@ declare class ResponseApi {
|
|
|
13
14
|
caption: string;
|
|
14
15
|
title?: string;
|
|
15
16
|
data?: any;
|
|
16
|
-
}) =>
|
|
17
|
-
|
|
18
|
-
responseSuccess: boolean;
|
|
19
|
-
responseMessage: string;
|
|
20
|
-
responseData: any;
|
|
21
|
-
};
|
|
22
|
-
invalidFields: ({ caption, data }: {
|
|
17
|
+
}) => ResponseJson;
|
|
18
|
+
invalidFields: ({ caption, data, }: {
|
|
23
19
|
caption: string;
|
|
24
20
|
data?: any;
|
|
25
|
-
}) =>
|
|
26
|
-
|
|
27
|
-
responseSuccess: boolean;
|
|
28
|
-
responseMessage: string;
|
|
29
|
-
responseData: any;
|
|
30
|
-
};
|
|
31
|
-
notFound: ({ caption, data }: {
|
|
21
|
+
}) => ResponseJson;
|
|
22
|
+
notFound: ({ caption, data, }: {
|
|
32
23
|
caption: string;
|
|
33
24
|
data?: any;
|
|
34
|
-
}) =>
|
|
35
|
-
|
|
36
|
-
responseSuccess: boolean;
|
|
37
|
-
responseMessage: string;
|
|
38
|
-
responseData: any;
|
|
39
|
-
};
|
|
40
|
-
unauthorized: ({ caption, data }: {
|
|
25
|
+
}) => ResponseJson;
|
|
26
|
+
unauthorized: ({ caption, data, }: {
|
|
41
27
|
caption: string;
|
|
42
28
|
data?: any;
|
|
43
|
-
}) =>
|
|
44
|
-
|
|
45
|
-
responseSuccess: boolean;
|
|
46
|
-
responseMessage: string;
|
|
47
|
-
responseData: any;
|
|
48
|
-
};
|
|
49
|
-
internalServer: ({ caption, data }: {
|
|
29
|
+
}) => ResponseJson;
|
|
30
|
+
forbidden: ({ caption, data, }: {
|
|
50
31
|
caption: string;
|
|
51
32
|
data?: any;
|
|
52
|
-
}) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
33
|
+
}) => ResponseJson;
|
|
34
|
+
floodWait: ({ caption, data, }: {
|
|
35
|
+
caption: string;
|
|
36
|
+
data?: any;
|
|
37
|
+
}) => ResponseJson;
|
|
38
|
+
internalServer: ({ caption, data, }: {
|
|
39
|
+
caption: string;
|
|
40
|
+
data?: any;
|
|
41
|
+
}) => ResponseJson;
|
|
58
42
|
}
|
|
59
43
|
export default ResponseApi;
|
package/dist/methods/response.js
CHANGED
|
@@ -18,7 +18,7 @@ class ResponseApi {
|
|
|
18
18
|
responseData: data,
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
|
-
invalidFields = ({ caption, data }) => {
|
|
21
|
+
invalidFields = ({ caption, data, }) => {
|
|
22
22
|
return {
|
|
23
23
|
responseCode: 4007401,
|
|
24
24
|
responseSuccess: false,
|
|
@@ -26,7 +26,7 @@ class ResponseApi {
|
|
|
26
26
|
responseData: data,
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
-
notFound = ({ caption, data }) => {
|
|
29
|
+
notFound = ({ caption, data, }) => {
|
|
30
30
|
return {
|
|
31
31
|
responseCode: 4047400,
|
|
32
32
|
responseSuccess: false,
|
|
@@ -34,7 +34,7 @@ class ResponseApi {
|
|
|
34
34
|
responseData: data,
|
|
35
35
|
};
|
|
36
36
|
};
|
|
37
|
-
unauthorized = ({ caption, data }) => {
|
|
37
|
+
unauthorized = ({ caption, data, }) => {
|
|
38
38
|
return {
|
|
39
39
|
responseCode: 4017400,
|
|
40
40
|
responseSuccess: false,
|
|
@@ -42,7 +42,23 @@ class ResponseApi {
|
|
|
42
42
|
responseData: data,
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
|
-
|
|
45
|
+
forbidden = ({ caption, data, }) => {
|
|
46
|
+
return {
|
|
47
|
+
responseCode: 4037400,
|
|
48
|
+
responseSuccess: false,
|
|
49
|
+
responseMessage: `[Forbidden] - ${caption}`,
|
|
50
|
+
responseData: data,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
floodWait = ({ caption, data, }) => {
|
|
54
|
+
return {
|
|
55
|
+
responseCode: 4297400,
|
|
56
|
+
responseSuccess: false,
|
|
57
|
+
responseMessage: `[Flood Wait] - ${caption}`,
|
|
58
|
+
responseData: data,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
internalServer = ({ caption, data, }) => {
|
|
46
62
|
return {
|
|
47
63
|
responseCode: 5007400,
|
|
48
64
|
responseSuccess: false,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { Request, Response } from "express";
|
|
2
|
+
export interface ResponseJson {
|
|
3
|
+
responseCode: number;
|
|
4
|
+
responseSuccess: boolean;
|
|
5
|
+
responseMessage: string;
|
|
6
|
+
responseData: any;
|
|
7
|
+
}
|
|
2
8
|
export interface RateLimitStore {
|
|
3
9
|
get(key: string): Promise<string | undefined>;
|
|
4
10
|
set(key: string, value: string, ttlMs?: number): Promise<void>;
|