azurajs 3.0.1 → 3.0.2
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/config/index.js +128 -6
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +130 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/core/index.js +1100 -11
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +1102 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/decorators/index.js +117 -87
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/index.mjs +98 -1
- package/dist/decorators/index.mjs.map +1 -1
- package/dist/index.js +2592 -236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2537 -9
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/index.js +16 -7
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +17 -1
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/plugins/index.js +1056 -73
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/index.mjs +1042 -1
- package/dist/plugins/index.mjs.map +1 -1
- package/dist/types/index.js +49 -12
- package/dist/types/index.js.map +1 -1
- package/dist/types/index.mjs +49 -2
- package/dist/types/index.mjs.map +1 -1
- package/dist/utils/index.js +551 -50
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +541 -3
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +35 -17
- package/{dist/chunk-DR254CWJ.mjs → src/config/ConfigModule.ts} +169 -132
- package/src/config/index.ts +1 -0
- package/src/core/index.ts +2 -0
- package/src/core/router.ts +284 -0
- package/{dist/chunk-EYAHUNC7.mjs → src/core/server.ts} +590 -699
- package/src/decorators/Route.ts +110 -0
- package/src/decorators/index.ts +23 -0
- package/src/index.ts +12 -0
- package/src/middleware/LoggingMiddleware.ts +20 -0
- package/src/middleware/index.ts +1 -0
- package/src/plugins/CORSPlugin.ts +56 -0
- package/src/plugins/CircuitBreakerPlugin.ts +84 -0
- package/src/plugins/CompressionPlugin.ts +80 -0
- package/src/plugins/ETagPlugin.ts +31 -0
- package/src/plugins/HealthCheckPlugin.ts +57 -0
- package/src/plugins/HelmetPlugin.ts +89 -0
- package/src/plugins/JWTPlugin.ts +132 -0
- package/src/plugins/MultipartPlugin.ts +168 -0
- package/src/plugins/ProxyPlugin.ts +89 -0
- package/src/plugins/RateLimitPlugin.ts +96 -0
- package/src/plugins/RequestIdPlugin.ts +21 -0
- package/src/plugins/SSEPlugin.ts +114 -0
- package/src/plugins/SessionPlugin.ts +98 -0
- package/src/plugins/StaticPlugin.ts +152 -0
- package/src/plugins/TimeoutPlugin.ts +33 -0
- package/src/plugins/index.ts +18 -0
- package/src/types/common.type.ts +82 -0
- package/src/types/config.type.ts +57 -0
- package/{dist/chunk-OWUGAI5V.mjs → src/types/http/status.ts} +49 -51
- package/src/types/index.ts +55 -0
- package/src/types/plugins/plugin.type.ts +170 -0
- package/src/types/reflect.d.ts +14 -0
- package/src/types/routes.type.ts +70 -0
- package/src/utils/HttpError.ts +62 -0
- package/src/utils/IpResolver.ts +30 -0
- package/src/utils/Logger.ts +144 -0
- package/src/utils/Parser.ts +182 -0
- package/src/utils/cookies/CookieManager.ts +48 -0
- package/src/utils/index.ts +9 -0
- package/{dist/chunk-UWIFSGSQ.mjs → src/utils/validators/DTOValidator.ts} +145 -141
- package/src/utils/validators/SchemaValidator.ts +45 -0
- package/dist/chunk-3UFAWS2V.js +0 -392
- package/dist/chunk-3UFAWS2V.js.map +0 -1
- package/dist/chunk-4LSFAAZW.js +0 -4
- package/dist/chunk-4LSFAAZW.js.map +0 -1
- package/dist/chunk-7NSRIVZM.js +0 -54
- package/dist/chunk-7NSRIVZM.js.map +0 -1
- package/dist/chunk-AOG6NYAM.js +0 -144
- package/dist/chunk-AOG6NYAM.js.map +0 -1
- package/dist/chunk-DR254CWJ.mjs.map +0 -1
- package/dist/chunk-EYAHUNC7.mjs.map +0 -1
- package/dist/chunk-HHDQPIJN.mjs +0 -19
- package/dist/chunk-HHDQPIJN.mjs.map +0 -1
- package/dist/chunk-HHZNAGGI.js +0 -702
- package/dist/chunk-HHZNAGGI.js.map +0 -1
- package/dist/chunk-KJM5XCAY.js +0 -21
- package/dist/chunk-KJM5XCAY.js.map +0 -1
- package/dist/chunk-NLSZKAPA.mjs +0 -1044
- package/dist/chunk-NLSZKAPA.mjs.map +0 -1
- package/dist/chunk-OWUGAI5V.mjs.map +0 -1
- package/dist/chunk-POPNQEOK.js +0 -1063
- package/dist/chunk-POPNQEOK.js.map +0 -1
- package/dist/chunk-QPRW4YU4.js +0 -134
- package/dist/chunk-QPRW4YU4.js.map +0 -1
- package/dist/chunk-REJDZUZ5.mjs +0 -382
- package/dist/chunk-REJDZUZ5.mjs.map +0 -1
- package/dist/chunk-TC6N6TJZ.mjs +0 -100
- package/dist/chunk-TC6N6TJZ.mjs.map +0 -1
- package/dist/chunk-TEUXKMXP.js +0 -122
- package/dist/chunk-TEUXKMXP.js.map +0 -1
- package/dist/chunk-UWIFSGSQ.mjs.map +0 -1
- package/dist/chunk-YPBKY4KY.mjs +0 -3
- package/dist/chunk-YPBKY4KY.mjs.map +0 -1
package/dist/utils/index.js
CHANGED
|
@@ -1,54 +1,555 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
3
|
+
// src/utils/Logger.ts
|
|
4
|
+
var LEVEL_PRIORITY = {
|
|
5
|
+
debug: 0,
|
|
6
|
+
info: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
error: 3,
|
|
9
|
+
silent: 4
|
|
10
|
+
};
|
|
11
|
+
var COLORS = {
|
|
12
|
+
reset: "\x1B[0m",
|
|
13
|
+
bold: "\x1B[1m",
|
|
14
|
+
dim: "\x1B[2m",
|
|
15
|
+
red: "\x1B[31m",
|
|
16
|
+
green: "\x1B[32m",
|
|
17
|
+
yellow: "\x1B[33m",
|
|
18
|
+
blue: "\x1B[34m",
|
|
19
|
+
magenta: "\x1B[35m",
|
|
20
|
+
cyan: "\x1B[36m",
|
|
21
|
+
white: "\x1B[37m",
|
|
22
|
+
gray: "\x1B[90m"};
|
|
23
|
+
var METHOD_COLORS = {
|
|
24
|
+
GET: COLORS.green,
|
|
25
|
+
POST: COLORS.blue,
|
|
26
|
+
PUT: COLORS.yellow,
|
|
27
|
+
DELETE: COLORS.red,
|
|
28
|
+
PATCH: COLORS.magenta,
|
|
29
|
+
HEAD: COLORS.cyan,
|
|
30
|
+
OPTIONS: COLORS.gray
|
|
31
|
+
};
|
|
32
|
+
function statusColor(code) {
|
|
33
|
+
if (code < 200) return COLORS.gray;
|
|
34
|
+
if (code < 300) return COLORS.green;
|
|
35
|
+
if (code < 400) return COLORS.cyan;
|
|
36
|
+
if (code < 500) return COLORS.yellow;
|
|
37
|
+
return COLORS.red;
|
|
38
|
+
}
|
|
39
|
+
function formatDuration(ns) {
|
|
40
|
+
const us = Number(ns) / 1e3;
|
|
41
|
+
if (us < 1e3) return `${us.toFixed(0)}\xB5s`;
|
|
42
|
+
const ms = us / 1e3;
|
|
43
|
+
if (ms < 1e3) return `${ms.toFixed(1)}ms`;
|
|
44
|
+
return `${(ms / 1e3).toFixed(2)}s`;
|
|
45
|
+
}
|
|
46
|
+
var Logger = class {
|
|
47
|
+
level;
|
|
48
|
+
useColors;
|
|
49
|
+
showTimestamp;
|
|
50
|
+
prefix;
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.level = options.level ?? "info";
|
|
53
|
+
this.useColors = options.colors ?? process.stdout.isTTY !== false;
|
|
54
|
+
this.showTimestamp = options.timestamp ?? true;
|
|
55
|
+
this.prefix = options.prefix ?? "azura";
|
|
56
|
+
}
|
|
57
|
+
shouldLog(level) {
|
|
58
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.level];
|
|
59
|
+
}
|
|
60
|
+
timestamp() {
|
|
61
|
+
if (!this.showTimestamp) return "";
|
|
62
|
+
const now = /* @__PURE__ */ new Date();
|
|
63
|
+
return `${COLORS.gray}${now.toISOString().slice(11, 23)}${COLORS.reset} `;
|
|
64
|
+
}
|
|
65
|
+
tag(level) {
|
|
66
|
+
if (!this.useColors) return `[${level.toUpperCase()}]`;
|
|
67
|
+
const colorMap = {
|
|
68
|
+
debug: COLORS.gray,
|
|
69
|
+
info: COLORS.blue,
|
|
70
|
+
warn: COLORS.yellow,
|
|
71
|
+
error: COLORS.red
|
|
72
|
+
};
|
|
73
|
+
return `${colorMap[level] ?? ""}[${level.toUpperCase()}]${COLORS.reset}`;
|
|
74
|
+
}
|
|
75
|
+
debug(message, ...args) {
|
|
76
|
+
if (!this.shouldLog("debug")) return;
|
|
77
|
+
console.debug(`${this.timestamp()}${this.tag("debug")} ${message}`, ...args);
|
|
78
|
+
}
|
|
79
|
+
info(message, ...args) {
|
|
80
|
+
if (!this.shouldLog("info")) return;
|
|
81
|
+
console.info(`${this.timestamp()}${this.tag("info")} ${message}`, ...args);
|
|
82
|
+
}
|
|
83
|
+
warn(message, ...args) {
|
|
84
|
+
if (!this.shouldLog("warn")) return;
|
|
85
|
+
console.warn(`${this.timestamp()}${this.tag("warn")} ${message}`, ...args);
|
|
86
|
+
}
|
|
87
|
+
error(message, ...args) {
|
|
88
|
+
if (!this.shouldLog("error")) return;
|
|
89
|
+
console.error(`${this.timestamp()}${this.tag("error")} ${message}`, ...args);
|
|
90
|
+
}
|
|
91
|
+
request(method, path, statusCode, duration) {
|
|
92
|
+
if (!this.shouldLog("info")) return;
|
|
93
|
+
const mc = this.useColors ? METHOD_COLORS[method] ?? COLORS.white : "";
|
|
94
|
+
const sc = this.useColors ? statusColor(statusCode) : "";
|
|
95
|
+
const r = this.useColors ? COLORS.reset : "";
|
|
96
|
+
const dur = formatDuration(duration);
|
|
97
|
+
console.info(
|
|
98
|
+
`${this.timestamp()}${mc}${method.padEnd(7)}${r} ${path} ${sc}${statusCode}${r} ${COLORS.dim}${dur}${r}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
banner(port, host) {
|
|
102
|
+
if (!this.shouldLog("info")) return;
|
|
103
|
+
const c = this.useColors;
|
|
104
|
+
const lines = [
|
|
105
|
+
"",
|
|
106
|
+
`${c ? COLORS.bold + COLORS.cyan : ""} \u26A1 AzuraJS v3.0.0${c ? COLORS.reset : ""}`,
|
|
107
|
+
"",
|
|
108
|
+
`${c ? COLORS.green : ""} \u279C Local: ${c ? COLORS.bold : ""}http://${host}:${port}/${c ? COLORS.reset : ""}`,
|
|
109
|
+
`${c ? COLORS.dim : ""} \u279C Press Ctrl+C to stop${c ? COLORS.reset : ""}`,
|
|
110
|
+
""
|
|
111
|
+
];
|
|
112
|
+
console.info(lines.join("\n"));
|
|
113
|
+
}
|
|
114
|
+
setLevel(level) {
|
|
115
|
+
this.level = level;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
new Logger();
|
|
119
|
+
|
|
120
|
+
// src/types/http/status.ts
|
|
121
|
+
var HttpStatusText = {
|
|
122
|
+
200: "OK",
|
|
123
|
+
201: "Created",
|
|
124
|
+
202: "Accepted",
|
|
125
|
+
204: "No Content",
|
|
126
|
+
301: "Moved Permanently",
|
|
127
|
+
302: "Found",
|
|
128
|
+
304: "Not Modified",
|
|
129
|
+
400: "Bad Request",
|
|
130
|
+
401: "Unauthorized",
|
|
131
|
+
403: "Forbidden",
|
|
132
|
+
404: "Not Found",
|
|
133
|
+
405: "Method Not Allowed",
|
|
134
|
+
409: "Conflict",
|
|
135
|
+
410: "Gone",
|
|
136
|
+
422: "Unprocessable Entity",
|
|
137
|
+
429: "Too Many Requests",
|
|
138
|
+
500: "Internal Server Error",
|
|
139
|
+
501: "Not Implemented",
|
|
140
|
+
502: "Bad Gateway",
|
|
141
|
+
503: "Service Unavailable",
|
|
142
|
+
504: "Gateway Timeout"
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/utils/HttpError.ts
|
|
146
|
+
var HttpError = class _HttpError extends Error {
|
|
147
|
+
statusCode;
|
|
148
|
+
details;
|
|
149
|
+
isOperational;
|
|
150
|
+
constructor(statusCode, message, details) {
|
|
151
|
+
super(message ?? HttpStatusText[statusCode] ?? "Unknown Error");
|
|
152
|
+
this.statusCode = statusCode;
|
|
153
|
+
this.details = details;
|
|
154
|
+
this.isOperational = true;
|
|
155
|
+
Object.setPrototypeOf(this, _HttpError.prototype);
|
|
156
|
+
}
|
|
157
|
+
toJSON() {
|
|
158
|
+
const obj = {
|
|
159
|
+
error: {
|
|
160
|
+
statusCode: this.statusCode,
|
|
161
|
+
message: this.message
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
if (this.details) obj.error.details = this.details;
|
|
165
|
+
return obj;
|
|
166
|
+
}
|
|
167
|
+
static badRequest(message, details) {
|
|
168
|
+
return new _HttpError(400, message ?? "Bad Request", details);
|
|
169
|
+
}
|
|
170
|
+
static unauthorized(message) {
|
|
171
|
+
return new _HttpError(401, message ?? "Unauthorized");
|
|
172
|
+
}
|
|
173
|
+
static forbidden(message) {
|
|
174
|
+
return new _HttpError(403, message ?? "Forbidden");
|
|
175
|
+
}
|
|
176
|
+
static notFound(message) {
|
|
177
|
+
return new _HttpError(404, message ?? "Not Found");
|
|
178
|
+
}
|
|
179
|
+
static methodNotAllowed(message) {
|
|
180
|
+
return new _HttpError(405, message ?? "Method Not Allowed");
|
|
181
|
+
}
|
|
182
|
+
static conflict(message, details) {
|
|
183
|
+
return new _HttpError(409, message ?? "Conflict", details);
|
|
184
|
+
}
|
|
185
|
+
static unprocessableEntity(message, details) {
|
|
186
|
+
return new _HttpError(422, message ?? "Unprocessable Entity", details);
|
|
187
|
+
}
|
|
188
|
+
static tooManyRequests(message) {
|
|
189
|
+
return new _HttpError(429, message ?? "Too Many Requests");
|
|
190
|
+
}
|
|
191
|
+
static internal(message) {
|
|
192
|
+
return new _HttpError(500, message ?? "Internal Server Error");
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/utils/IpResolver.ts
|
|
197
|
+
var PROXY_HEADERS = [
|
|
198
|
+
"x-forwarded-for",
|
|
199
|
+
"x-real-ip",
|
|
200
|
+
"cf-connecting-ip",
|
|
201
|
+
"x-client-ip",
|
|
202
|
+
"x-cluster-client-ip",
|
|
203
|
+
"fastly-client-ip",
|
|
204
|
+
"true-client-ip"
|
|
205
|
+
];
|
|
206
|
+
function resolveIp(req) {
|
|
207
|
+
for (const header of PROXY_HEADERS) {
|
|
208
|
+
const val = req.headers[header];
|
|
209
|
+
if (val) {
|
|
210
|
+
const ip = typeof val === "string" ? val.split(",")[0].trim() : val[0];
|
|
211
|
+
if (ip && ip.length > 0) return normalizeIp(ip);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const remoteAddr = req.socket?.remoteAddress ?? "127.0.0.1";
|
|
215
|
+
return normalizeIp(remoteAddr);
|
|
216
|
+
}
|
|
217
|
+
function normalizeIp(ip) {
|
|
218
|
+
if (ip === "::1" || ip === "::ffff:127.0.0.1") return "127.0.0.1";
|
|
219
|
+
if (ip.startsWith("::ffff:")) return ip.slice(7);
|
|
220
|
+
return ip;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/utils/Parser.ts
|
|
224
|
+
function parseQueryString(qs) {
|
|
225
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
226
|
+
if (!qs || qs.length === 0) return result;
|
|
227
|
+
let key = "";
|
|
228
|
+
let value = "";
|
|
229
|
+
let startingKey = true;
|
|
230
|
+
let i = qs.charCodeAt(0) === 63 ? 1 : 0;
|
|
231
|
+
for (; i < qs.length; i++) {
|
|
232
|
+
const ch = qs.charCodeAt(i);
|
|
233
|
+
if (ch === 61 && startingKey) {
|
|
234
|
+
startingKey = false;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (ch === 38) {
|
|
238
|
+
if (key.length > 0) {
|
|
239
|
+
const decodedKey = fastDecode(key);
|
|
240
|
+
const decodedVal = fastDecode(value);
|
|
241
|
+
const existing = result[decodedKey];
|
|
242
|
+
if (existing === void 0) {
|
|
243
|
+
result[decodedKey] = decodedVal;
|
|
244
|
+
} else if (typeof existing === "string") {
|
|
245
|
+
result[decodedKey] = [existing, decodedVal];
|
|
246
|
+
} else {
|
|
247
|
+
existing.push(decodedVal);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
key = "";
|
|
251
|
+
value = "";
|
|
252
|
+
startingKey = true;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (startingKey) {
|
|
256
|
+
key += qs[i];
|
|
257
|
+
} else {
|
|
258
|
+
value += qs[i];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (key.length > 0) {
|
|
262
|
+
const decodedKey = fastDecode(key);
|
|
263
|
+
const decodedVal = fastDecode(value);
|
|
264
|
+
const existing = result[decodedKey];
|
|
265
|
+
if (existing === void 0) {
|
|
266
|
+
result[decodedKey] = decodedVal;
|
|
267
|
+
} else if (typeof existing === "string") {
|
|
268
|
+
result[decodedKey] = [existing, decodedVal];
|
|
269
|
+
} else {
|
|
270
|
+
existing.push(decodedVal);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
function fastDecode(str) {
|
|
276
|
+
if (str.indexOf("%") === -1 && str.indexOf("+") === -1) return str;
|
|
277
|
+
try {
|
|
278
|
+
return decodeURIComponent(str.replace(/\+/g, " "));
|
|
279
|
+
} catch {
|
|
280
|
+
return str;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function parseCookies(header) {
|
|
284
|
+
const cookies = /* @__PURE__ */ Object.create(null);
|
|
285
|
+
if (!header) return cookies;
|
|
286
|
+
let i = 0;
|
|
287
|
+
const len = header.length;
|
|
288
|
+
while (i < len) {
|
|
289
|
+
while (i < len && header.charCodeAt(i) === 32) i++;
|
|
290
|
+
let eqIdx = -1;
|
|
291
|
+
let semiIdx = -1;
|
|
292
|
+
for (let j = i; j < len; j++) {
|
|
293
|
+
const ch = header.charCodeAt(j);
|
|
294
|
+
if (ch === 61 && eqIdx === -1) eqIdx = j;
|
|
295
|
+
if (ch === 59) {
|
|
296
|
+
semiIdx = j;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (eqIdx === -1) {
|
|
301
|
+
i = semiIdx === -1 ? len : semiIdx + 1;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const end = semiIdx === -1 ? len : semiIdx;
|
|
305
|
+
const name = header.slice(i, eqIdx).trim();
|
|
306
|
+
let val = header.slice(eqIdx + 1, end).trim();
|
|
307
|
+
if (val.charCodeAt(0) === 34 && val.charCodeAt(val.length - 1) === 34) {
|
|
308
|
+
val = val.slice(1, -1);
|
|
309
|
+
}
|
|
310
|
+
if (cookies[name] === void 0) {
|
|
311
|
+
cookies[name] = fastDecode(val);
|
|
312
|
+
}
|
|
313
|
+
i = end + 1;
|
|
314
|
+
}
|
|
315
|
+
return cookies;
|
|
316
|
+
}
|
|
317
|
+
var CONTENT_TYPE_JSON = "application/json";
|
|
318
|
+
var CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
|
|
319
|
+
async function parseBody(req) {
|
|
320
|
+
const contentType = req.headers["content-type"] ?? "";
|
|
321
|
+
const contentLength = req.headers["content-length"];
|
|
322
|
+
if (req.method === "GET" || req.method === "HEAD" || req.method === "OPTIONS" || contentLength !== void 0 && contentLength === "0") {
|
|
323
|
+
return void 0;
|
|
324
|
+
}
|
|
325
|
+
const chunks = [];
|
|
326
|
+
let totalSize = 0;
|
|
327
|
+
const maxSize = 10 * 1024 * 1024;
|
|
328
|
+
return new Promise((resolve, reject) => {
|
|
329
|
+
req.on("data", (chunk) => {
|
|
330
|
+
totalSize += chunk.length;
|
|
331
|
+
if (totalSize > maxSize) {
|
|
332
|
+
req.destroy();
|
|
333
|
+
reject(new Error("Request body too large"));
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
chunks.push(chunk);
|
|
337
|
+
});
|
|
338
|
+
req.on("end", () => {
|
|
339
|
+
if (chunks.length === 0) {
|
|
340
|
+
resolve(void 0);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
344
|
+
if (contentType.startsWith(CONTENT_TYPE_JSON)) {
|
|
345
|
+
try {
|
|
346
|
+
resolve(JSON.parse(raw));
|
|
347
|
+
} catch {
|
|
348
|
+
resolve(raw);
|
|
349
|
+
}
|
|
350
|
+
} else if (contentType.startsWith(CONTENT_TYPE_FORM)) {
|
|
351
|
+
resolve(parseQueryString(raw));
|
|
352
|
+
} else {
|
|
353
|
+
resolve(raw);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
req.on("error", reject);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function parseUrl(url) {
|
|
360
|
+
let pathname = "";
|
|
361
|
+
let search = "";
|
|
362
|
+
let i = 0;
|
|
363
|
+
for (; i < url.length; i++) {
|
|
364
|
+
if (url.charCodeAt(i) === 63) {
|
|
365
|
+
pathname = url.slice(0, i);
|
|
366
|
+
search = url.slice(i);
|
|
367
|
+
return { pathname, search };
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return { pathname: url, search: "" };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/utils/cookies/CookieManager.ts
|
|
374
|
+
function serializeCookie(name, value, options = {}) {
|
|
375
|
+
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
376
|
+
if (options.maxAge != null) {
|
|
377
|
+
cookie += `; Max-Age=${Math.floor(options.maxAge)}`;
|
|
378
|
+
}
|
|
379
|
+
if (options.expires) {
|
|
380
|
+
cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
381
|
+
}
|
|
382
|
+
if (options.domain) {
|
|
383
|
+
cookie += `; Domain=${options.domain}`;
|
|
384
|
+
}
|
|
385
|
+
cookie += `; Path=${options.path ?? "/"}`;
|
|
386
|
+
if (options.secure) {
|
|
387
|
+
cookie += "; Secure";
|
|
388
|
+
}
|
|
389
|
+
if (options.httpOnly !== false) {
|
|
390
|
+
cookie += "; HttpOnly";
|
|
391
|
+
}
|
|
392
|
+
if (options.sameSite) {
|
|
393
|
+
cookie += `; SameSite=${options.sameSite}`;
|
|
394
|
+
}
|
|
395
|
+
return cookie;
|
|
396
|
+
}
|
|
397
|
+
function clearCookieHeader(name, options = {}) {
|
|
398
|
+
return serializeCookie(name, "", {
|
|
399
|
+
...options,
|
|
400
|
+
maxAge: 0,
|
|
401
|
+
expires: /* @__PURE__ */ new Date(0)
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/utils/validators/DTOValidator.ts
|
|
406
|
+
var DTOValidator = class {
|
|
407
|
+
static validate(data, schema) {
|
|
408
|
+
const errors = [];
|
|
409
|
+
if (data == null || typeof data !== "object") {
|
|
410
|
+
return {
|
|
411
|
+
valid: false,
|
|
412
|
+
errors: [{ field: "_root", message: "Request body must be an object" }]
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
for (const [field, rule] of Object.entries(schema)) {
|
|
416
|
+
const value = data[field];
|
|
417
|
+
if (rule.required && (value === void 0 || value === null || value === "")) {
|
|
418
|
+
errors.push({
|
|
419
|
+
field,
|
|
420
|
+
message: rule.message ?? `${field} is required`,
|
|
421
|
+
value
|
|
422
|
+
});
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (value === void 0 || value === null) continue;
|
|
426
|
+
if (rule.type) {
|
|
427
|
+
const actualType = Array.isArray(value) ? "array" : typeof value;
|
|
428
|
+
if (actualType !== rule.type) {
|
|
429
|
+
errors.push({
|
|
430
|
+
field,
|
|
431
|
+
message: rule.message ?? `${field} must be of type ${rule.type}`,
|
|
432
|
+
value
|
|
433
|
+
});
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (rule.type === "string" || typeof value === "string") {
|
|
438
|
+
if (rule.min !== void 0 && value.length < rule.min) {
|
|
439
|
+
errors.push({
|
|
440
|
+
field,
|
|
441
|
+
message: rule.message ?? `${field} must be at least ${rule.min} characters`,
|
|
442
|
+
value
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
if (rule.max !== void 0 && value.length > rule.max) {
|
|
446
|
+
errors.push({
|
|
447
|
+
field,
|
|
448
|
+
message: rule.message ?? `${field} must be at most ${rule.max} characters`,
|
|
449
|
+
value
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
if (rule.pattern && !rule.pattern.test(value)) {
|
|
453
|
+
errors.push({
|
|
454
|
+
field,
|
|
455
|
+
message: rule.message ?? `${field} has invalid format`,
|
|
456
|
+
value
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (rule.type === "number" || typeof value === "number") {
|
|
461
|
+
if (rule.min !== void 0 && value < rule.min) {
|
|
462
|
+
errors.push({
|
|
463
|
+
field,
|
|
464
|
+
message: rule.message ?? `${field} must be at least ${rule.min}`,
|
|
465
|
+
value
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
if (rule.max !== void 0 && value > rule.max) {
|
|
469
|
+
errors.push({
|
|
470
|
+
field,
|
|
471
|
+
message: rule.message ?? `${field} must be at most ${rule.max}`,
|
|
472
|
+
value
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (rule.type === "array" && Array.isArray(value)) {
|
|
477
|
+
if (rule.min !== void 0 && value.length < rule.min) {
|
|
478
|
+
errors.push({
|
|
479
|
+
field,
|
|
480
|
+
message: rule.message ?? `${field} must have at least ${rule.min} items`,
|
|
481
|
+
value
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (rule.max !== void 0 && value.length > rule.max) {
|
|
485
|
+
errors.push({
|
|
486
|
+
field,
|
|
487
|
+
message: rule.message ?? `${field} must have at most ${rule.max} items`,
|
|
488
|
+
value
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (rule.enum && !rule.enum.includes(value)) {
|
|
493
|
+
errors.push({
|
|
494
|
+
field,
|
|
495
|
+
message: rule.message ?? `${field} must be one of: ${rule.enum.join(", ")}`,
|
|
496
|
+
value
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
if (rule.custom) {
|
|
500
|
+
const customError = rule.custom(value);
|
|
501
|
+
if (customError) {
|
|
502
|
+
errors.push({ field, message: customError, value });
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
valid: errors.length === 0,
|
|
508
|
+
errors,
|
|
509
|
+
data: errors.length === 0 ? data : void 0
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/utils/validators/SchemaValidator.ts
|
|
515
|
+
var SchemaValidator = class {
|
|
516
|
+
static validate(data, schema) {
|
|
517
|
+
if (typeof schema.safeParse === "function") {
|
|
518
|
+
const result = schema.safeParse(data);
|
|
519
|
+
if (result.success) {
|
|
520
|
+
return { valid: true, data: result.data };
|
|
521
|
+
}
|
|
522
|
+
return { valid: false, errors: result.error };
|
|
523
|
+
}
|
|
524
|
+
if (typeof schema.parse === "function") {
|
|
525
|
+
try {
|
|
526
|
+
const parsed = schema.parse(data);
|
|
527
|
+
return { valid: true, data: parsed };
|
|
528
|
+
} catch (err) {
|
|
529
|
+
return { valid: false, errors: err };
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (typeof schema.validate === "function") {
|
|
533
|
+
const result = schema.validate(data);
|
|
534
|
+
if (result.error) {
|
|
535
|
+
return { valid: false, errors: result.error };
|
|
536
|
+
}
|
|
537
|
+
return { valid: true, data: result.value };
|
|
538
|
+
}
|
|
539
|
+
return { valid: true, data };
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
exports.DTOValidator = DTOValidator;
|
|
544
|
+
exports.HttpError = HttpError;
|
|
545
|
+
exports.Logger = Logger;
|
|
546
|
+
exports.SchemaValidator = SchemaValidator;
|
|
547
|
+
exports.clearCookieHeader = clearCookieHeader;
|
|
548
|
+
exports.parseBody = parseBody;
|
|
549
|
+
exports.parseCookies = parseCookies;
|
|
550
|
+
exports.parseQueryString = parseQueryString;
|
|
551
|
+
exports.parseUrl = parseUrl;
|
|
552
|
+
exports.resolveIp = resolveIp;
|
|
553
|
+
exports.serializeCookie = serializeCookie;
|
|
53
554
|
//# sourceMappingURL=index.js.map
|
|
54
555
|
//# sourceMappingURL=index.js.map
|