ayiin 2.0.53 → 2.0.55
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/index.d.ts +1 -2
- package/dist/methods/index.js +0 -2
- package/dist/methods/limiter.d.ts +3 -2
- package/dist/methods/limiter.js +27 -12
- package/dist/methods/response.d.ts +14 -48
- package/dist/methods/response.js +6 -6
- package/dist/types.d.ts +6 -0
- package/package.json +1 -1
- package/dist/methods/files.d.ts +0 -15
- package/dist/methods/files.js +0 -26
package/dist/methods/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import Async from "./async";
|
|
|
2
2
|
import Crypt from "./crypt";
|
|
3
3
|
import Currency from "./currency";
|
|
4
4
|
import Dates from "./dates";
|
|
5
|
-
import Files from "./files";
|
|
6
5
|
import Limiter from "./limiter";
|
|
7
6
|
import Objects from "./objects";
|
|
8
7
|
import Random from "./random";
|
|
@@ -12,6 +11,6 @@ import Token from "./token";
|
|
|
12
11
|
import Validation from "./validation";
|
|
13
12
|
declare class Methods {
|
|
14
13
|
}
|
|
15
|
-
interface Methods extends Async, Crypt, Currency, Dates,
|
|
14
|
+
interface Methods extends Async, Crypt, Currency, Dates, Limiter, Objects, Random, ResponseApi, Strings, Token, Validation {
|
|
16
15
|
}
|
|
17
16
|
export default Methods;
|
package/dist/methods/index.js
CHANGED
|
@@ -7,7 +7,6 @@ const async_1 = __importDefault(require("./async"));
|
|
|
7
7
|
const crypt_1 = __importDefault(require("./crypt"));
|
|
8
8
|
const currency_1 = __importDefault(require("./currency"));
|
|
9
9
|
const dates_1 = __importDefault(require("./dates"));
|
|
10
|
-
const files_1 = __importDefault(require("./files"));
|
|
11
10
|
const limiter_1 = __importDefault(require("./limiter"));
|
|
12
11
|
const objects_1 = __importDefault(require("./objects"));
|
|
13
12
|
const random_1 = __importDefault(require("./random"));
|
|
@@ -22,7 +21,6 @@ Object.assign(Methods.prototype, new async_1.default());
|
|
|
22
21
|
Object.assign(Methods.prototype, new crypt_1.default());
|
|
23
22
|
Object.assign(Methods.prototype, new currency_1.default());
|
|
24
23
|
Object.assign(Methods.prototype, new dates_1.default());
|
|
25
|
-
Object.assign(Methods.prototype, new files_1.default());
|
|
26
24
|
Object.assign(Methods.prototype, new limiter_1.default());
|
|
27
25
|
Object.assign(Methods.prototype, new objects_1.default());
|
|
28
26
|
Object.assign(Methods.prototype, new random_1.default());
|
|
@@ -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,65 +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
|
-
forbidden: ({ caption, data }: {
|
|
29
|
+
}) => ResponseJson;
|
|
30
|
+
forbidden: ({ caption, data, }: {
|
|
50
31
|
caption: string;
|
|
51
32
|
data?: any;
|
|
52
|
-
}) =>
|
|
53
|
-
|
|
54
|
-
responseSuccess: boolean;
|
|
55
|
-
responseMessage: string;
|
|
56
|
-
responseData: any;
|
|
57
|
-
};
|
|
58
|
-
floodWait: ({ caption, data }: {
|
|
33
|
+
}) => ResponseJson;
|
|
34
|
+
floodWait: ({ caption, data, }: {
|
|
59
35
|
caption: string;
|
|
60
36
|
data?: any;
|
|
61
|
-
}) =>
|
|
62
|
-
|
|
63
|
-
responseSuccess: boolean;
|
|
64
|
-
responseMessage: string;
|
|
65
|
-
responseData: any;
|
|
66
|
-
};
|
|
67
|
-
internalServer: ({ caption, data }: {
|
|
37
|
+
}) => ResponseJson;
|
|
38
|
+
internalServer: ({ caption, data, }: {
|
|
68
39
|
caption: string;
|
|
69
40
|
data?: any;
|
|
70
|
-
}) =>
|
|
71
|
-
responseCode: number;
|
|
72
|
-
responseSuccess: boolean;
|
|
73
|
-
responseMessage: string;
|
|
74
|
-
responseData: any;
|
|
75
|
-
};
|
|
41
|
+
}) => ResponseJson;
|
|
76
42
|
}
|
|
77
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,7 @@ class ResponseApi {
|
|
|
42
42
|
responseData: data,
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
|
-
forbidden = ({ caption, data }) => {
|
|
45
|
+
forbidden = ({ caption, data, }) => {
|
|
46
46
|
return {
|
|
47
47
|
responseCode: 4037400,
|
|
48
48
|
responseSuccess: false,
|
|
@@ -50,7 +50,7 @@ class ResponseApi {
|
|
|
50
50
|
responseData: data,
|
|
51
51
|
};
|
|
52
52
|
};
|
|
53
|
-
floodWait = ({ caption, data }) => {
|
|
53
|
+
floodWait = ({ caption, data, }) => {
|
|
54
54
|
return {
|
|
55
55
|
responseCode: 4297400,
|
|
56
56
|
responseSuccess: false,
|
|
@@ -58,7 +58,7 @@ class ResponseApi {
|
|
|
58
58
|
responseData: data,
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
|
-
internalServer = ({ caption, data }) => {
|
|
61
|
+
internalServer = ({ caption, data, }) => {
|
|
62
62
|
return {
|
|
63
63
|
responseCode: 5007400,
|
|
64
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>;
|
package/package.json
CHANGED
package/dist/methods/files.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
declare class Files {
|
|
2
|
-
/**
|
|
3
|
-
* Pastikan direktori ada
|
|
4
|
-
* @param {string} path - path direktori
|
|
5
|
-
* @returns {Promise<void>}
|
|
6
|
-
*/
|
|
7
|
-
ensureDir: (path: string) => Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* Baca file JSON
|
|
10
|
-
* @param {string} path - path file
|
|
11
|
-
* @returns {Promise<T>} data JSON
|
|
12
|
-
*/
|
|
13
|
-
readJSON: <T>(path: string) => Promise<T>;
|
|
14
|
-
}
|
|
15
|
-
export default Files;
|
package/dist/methods/files.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
7
|
-
class Files {
|
|
8
|
-
/**
|
|
9
|
-
* Pastikan direktori ada
|
|
10
|
-
* @param {string} path - path direktori
|
|
11
|
-
* @returns {Promise<void>}
|
|
12
|
-
*/
|
|
13
|
-
ensureDir = async (path) => {
|
|
14
|
-
await promises_1.default.mkdir(path, { recursive: true });
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Baca file JSON
|
|
18
|
-
* @param {string} path - path file
|
|
19
|
-
* @returns {Promise<T>} data JSON
|
|
20
|
-
*/
|
|
21
|
-
readJSON = async (path) => {
|
|
22
|
-
const data = await promises_1.default.readFile(path, "utf-8");
|
|
23
|
-
return JSON.parse(data);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
exports.default = Files;
|