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
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import type { SessionOptions, PluginHandler, SessionStore } from "../types/plugins/plugin.type.js";
|
|
3
|
+
|
|
4
|
+
class MemorySessionStore implements SessionStore {
|
|
5
|
+
private sessions = new Map<string, { data: Record<string, any>; expires: number }>();
|
|
6
|
+
private cleanupTimer: ReturnType<typeof setInterval>;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this.cleanupTimer = setInterval(() => {
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
for (const [id, session] of this.sessions) {
|
|
12
|
+
if (now >= session.expires) this.sessions.delete(id);
|
|
13
|
+
}
|
|
14
|
+
}, 60_000);
|
|
15
|
+
if (this.cleanupTimer.unref) this.cleanupTimer.unref();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async get(id: string): Promise<Record<string, any> | null> {
|
|
19
|
+
const session = this.sessions.get(id);
|
|
20
|
+
if (!session) return null;
|
|
21
|
+
if (Date.now() >= session.expires) {
|
|
22
|
+
this.sessions.delete(id);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return session.data;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async set(id: string, data: Record<string, any>, maxAge: number): Promise<void> {
|
|
29
|
+
this.sessions.set(id, { data, expires: Date.now() + maxAge });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async destroy(id: string): Promise<void> {
|
|
33
|
+
this.sessions.delete(id);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async touch(id: string, maxAge: number): Promise<void> {
|
|
37
|
+
const session = this.sessions.get(id);
|
|
38
|
+
if (session) session.expires = Date.now() + maxAge;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function generateSessionId(): string {
|
|
43
|
+
return randomBytes(24).toString("hex");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function SessionPlugin(options: SessionOptions): PluginHandler {
|
|
47
|
+
const {
|
|
48
|
+
secret: _secret,
|
|
49
|
+
name = "azura.sid",
|
|
50
|
+
maxAge = 86400_000,
|
|
51
|
+
secure = false,
|
|
52
|
+
httpOnly = true,
|
|
53
|
+
sameSite = "Lax",
|
|
54
|
+
store = new MemorySessionStore(),
|
|
55
|
+
} = options;
|
|
56
|
+
|
|
57
|
+
return async (ctx, next) => {
|
|
58
|
+
const { req, res } = ctx;
|
|
59
|
+
|
|
60
|
+
let sessionId = req.cookies[name];
|
|
61
|
+
let sessionData: Record<string, any> | null = null;
|
|
62
|
+
|
|
63
|
+
if (sessionId) {
|
|
64
|
+
sessionData = await store.get(sessionId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!sessionData) {
|
|
68
|
+
sessionId = generateSessionId();
|
|
69
|
+
sessionData = {};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
req.session = sessionData;
|
|
73
|
+
|
|
74
|
+
const originalEnd = res.end;
|
|
75
|
+
(res as any).end = async function (...args: any[]) {
|
|
76
|
+
await store.set(sessionId!, req.session ?? {}, maxAge);
|
|
77
|
+
|
|
78
|
+
const cookieParts = [
|
|
79
|
+
`${name}=${sessionId}`,
|
|
80
|
+
`Path=/`,
|
|
81
|
+
`Max-Age=${Math.floor(maxAge / 1000)}`,
|
|
82
|
+
`SameSite=${sameSite}`,
|
|
83
|
+
];
|
|
84
|
+
if (httpOnly) cookieParts.push("HttpOnly");
|
|
85
|
+
if (secure) cookieParts.push("Secure");
|
|
86
|
+
|
|
87
|
+
const existing = res.getHeader("Set-Cookie");
|
|
88
|
+
const cookies = existing
|
|
89
|
+
? [...(Array.isArray(existing) ? existing : [String(existing)]), cookieParts.join("; ")]
|
|
90
|
+
: [cookieParts.join("; ")];
|
|
91
|
+
res.setHeader("Set-Cookie", cookies);
|
|
92
|
+
|
|
93
|
+
return (originalEnd as any).apply(this, args);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
next();
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { createReadStream, statSync, existsSync } from "node:fs";
|
|
2
|
+
import { join, extname, resolve } from "node:path";
|
|
3
|
+
import type { StaticOptions, PluginHandler } from "../types/plugins/plugin.type.js";
|
|
4
|
+
|
|
5
|
+
const MIME_TYPES: Record<string, string> = {
|
|
6
|
+
".html": "text/html; charset=utf-8",
|
|
7
|
+
".htm": "text/html; charset=utf-8",
|
|
8
|
+
".css": "text/css; charset=utf-8",
|
|
9
|
+
".js": "application/javascript; charset=utf-8",
|
|
10
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
11
|
+
".json": "application/json; charset=utf-8",
|
|
12
|
+
".xml": "application/xml; charset=utf-8",
|
|
13
|
+
".txt": "text/plain; charset=utf-8",
|
|
14
|
+
".csv": "text/csv; charset=utf-8",
|
|
15
|
+
".png": "image/png",
|
|
16
|
+
".jpg": "image/jpeg",
|
|
17
|
+
".jpeg": "image/jpeg",
|
|
18
|
+
".gif": "image/gif",
|
|
19
|
+
".svg": "image/svg+xml",
|
|
20
|
+
".ico": "image/x-icon",
|
|
21
|
+
".webp": "image/webp",
|
|
22
|
+
".avif": "image/avif",
|
|
23
|
+
".woff": "font/woff",
|
|
24
|
+
".woff2": "font/woff2",
|
|
25
|
+
".ttf": "font/ttf",
|
|
26
|
+
".otf": "font/otf",
|
|
27
|
+
".eot": "application/vnd.ms-fontobject",
|
|
28
|
+
".mp4": "video/mp4",
|
|
29
|
+
".webm": "video/webm",
|
|
30
|
+
".mp3": "audio/mpeg",
|
|
31
|
+
".ogg": "audio/ogg",
|
|
32
|
+
".wav": "audio/wav",
|
|
33
|
+
".pdf": "application/pdf",
|
|
34
|
+
".zip": "application/zip",
|
|
35
|
+
".gz": "application/gzip",
|
|
36
|
+
".wasm": "application/wasm",
|
|
37
|
+
".map": "application/json",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function StaticPlugin(options: StaticOptions): PluginHandler {
|
|
41
|
+
const {
|
|
42
|
+
root,
|
|
43
|
+
prefix = "/",
|
|
44
|
+
index = ["index.html"],
|
|
45
|
+
dotfiles = "ignore",
|
|
46
|
+
maxAge = 0,
|
|
47
|
+
etag = true,
|
|
48
|
+
lastModified = true,
|
|
49
|
+
fallthrough = true,
|
|
50
|
+
immutable = false,
|
|
51
|
+
} = options;
|
|
52
|
+
|
|
53
|
+
const resolvedRoot = resolve(root);
|
|
54
|
+
const indexFiles = Array.isArray(index) ? index : [index];
|
|
55
|
+
const normalizedPrefix = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
56
|
+
|
|
57
|
+
return (ctx, next) => {
|
|
58
|
+
const { req, res } = ctx;
|
|
59
|
+
|
|
60
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
61
|
+
next();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const path = req.pathname;
|
|
66
|
+
if (!path.startsWith(normalizedPrefix)) {
|
|
67
|
+
next();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const relativePath = path.slice(normalizedPrefix.length) || "/";
|
|
72
|
+
|
|
73
|
+
if (relativePath.includes("..")) {
|
|
74
|
+
next();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (dotfiles !== "allow" && relativePath.split("/").some((s) => s.startsWith("."))) {
|
|
79
|
+
if (dotfiles === "deny") {
|
|
80
|
+
res.statusCode = 403;
|
|
81
|
+
res.end("Forbidden");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
next();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let filePath = join(resolvedRoot, relativePath);
|
|
89
|
+
|
|
90
|
+
if (!existsSync(filePath)) {
|
|
91
|
+
if (fallthrough) { next(); return; }
|
|
92
|
+
res.statusCode = 404;
|
|
93
|
+
res.end("Not Found");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let stat = statSync(filePath);
|
|
98
|
+
|
|
99
|
+
if (stat.isDirectory()) {
|
|
100
|
+
let found = false;
|
|
101
|
+
for (const idx of indexFiles) {
|
|
102
|
+
const candidate = join(filePath, idx);
|
|
103
|
+
if (existsSync(candidate)) {
|
|
104
|
+
filePath = candidate;
|
|
105
|
+
stat = statSync(filePath);
|
|
106
|
+
found = true;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!found) {
|
|
111
|
+
if (fallthrough) { next(); return; }
|
|
112
|
+
res.statusCode = 404;
|
|
113
|
+
res.end("Not Found");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const ext = extname(filePath).toLowerCase();
|
|
119
|
+
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
120
|
+
|
|
121
|
+
res.setHeader("Content-Type", contentType);
|
|
122
|
+
res.setHeader("Content-Length", stat.size);
|
|
123
|
+
|
|
124
|
+
if (lastModified) {
|
|
125
|
+
res.setHeader("Last-Modified", stat.mtime.toUTCString());
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (etag) {
|
|
129
|
+
const etagValue = `W/"${stat.size.toString(16)}-${stat.mtime.getTime().toString(16)}"`;
|
|
130
|
+
res.setHeader("ETag", etagValue);
|
|
131
|
+
|
|
132
|
+
const ifNoneMatch = req.headers["if-none-match"];
|
|
133
|
+
if (ifNoneMatch === etagValue) {
|
|
134
|
+
res.statusCode = 304;
|
|
135
|
+
res.end();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let cacheControl = `public, max-age=${maxAge}`;
|
|
141
|
+
if (immutable) cacheControl += ", immutable";
|
|
142
|
+
res.setHeader("Cache-Control", cacheControl);
|
|
143
|
+
|
|
144
|
+
if (req.method === "HEAD") {
|
|
145
|
+
res.end();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const stream = createReadStream(filePath);
|
|
150
|
+
stream.pipe(res);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TimeoutOptions, PluginHandler } from "../types/plugins/plugin.type.js";
|
|
2
|
+
|
|
3
|
+
export function TimeoutPlugin(options: TimeoutOptions): PluginHandler {
|
|
4
|
+
const {
|
|
5
|
+
timeout,
|
|
6
|
+
message = { error: { statusCode: 408, message: "Request Timeout" } },
|
|
7
|
+
statusCode = 408,
|
|
8
|
+
} = options;
|
|
9
|
+
|
|
10
|
+
return (ctx, next) => {
|
|
11
|
+
const { res } = ctx;
|
|
12
|
+
let timedOut = false;
|
|
13
|
+
|
|
14
|
+
const timer = setTimeout(() => {
|
|
15
|
+
timedOut = true;
|
|
16
|
+
if (!res.headersSent) {
|
|
17
|
+
res.statusCode = statusCode;
|
|
18
|
+
res.setHeader("Content-Type", typeof message === "string" ? "text/plain" : "application/json");
|
|
19
|
+
res.end(typeof message === "string" ? message : JSON.stringify(message));
|
|
20
|
+
}
|
|
21
|
+
}, timeout);
|
|
22
|
+
|
|
23
|
+
const originalEnd = res.end;
|
|
24
|
+
(res as any).end = function (...args: any[]) {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
if (!timedOut) {
|
|
27
|
+
return (originalEnd as any).apply(this, args);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
next();
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { CORSPlugin } from "./CORSPlugin.js";
|
|
2
|
+
export { RateLimitPlugin } from "./RateLimitPlugin.js";
|
|
3
|
+
export { HelmetPlugin } from "./HelmetPlugin.js";
|
|
4
|
+
export { JWTPlugin, signJWT, verifyJWT } from "./JWTPlugin.js";
|
|
5
|
+
export type { JWTPayload } from "./JWTPlugin.js";
|
|
6
|
+
export { SessionPlugin } from "./SessionPlugin.js";
|
|
7
|
+
export { CompressionPlugin } from "./CompressionPlugin.js";
|
|
8
|
+
export { StaticPlugin } from "./StaticPlugin.js";
|
|
9
|
+
export { ETagPlugin } from "./ETagPlugin.js";
|
|
10
|
+
export { RequestIdPlugin } from "./RequestIdPlugin.js";
|
|
11
|
+
export { TimeoutPlugin } from "./TimeoutPlugin.js";
|
|
12
|
+
export { HealthCheckPlugin } from "./HealthCheckPlugin.js";
|
|
13
|
+
export { CircuitBreakerPlugin } from "./CircuitBreakerPlugin.js";
|
|
14
|
+
export { SSEPlugin, SSEManager } from "./SSEPlugin.js";
|
|
15
|
+
export type { SSEClient } from "./SSEPlugin.js";
|
|
16
|
+
export { ProxyPlugin } from "./ProxyPlugin.js";
|
|
17
|
+
export { MultipartPlugin } from "./MultipartPlugin.js";
|
|
18
|
+
export type { UploadedFile } from "./MultipartPlugin.js";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
|
|
3
|
+
export interface AzuraRequest extends IncomingMessage {
|
|
4
|
+
pathname: string;
|
|
5
|
+
query: Record<string, string | string[]>;
|
|
6
|
+
params: Record<string, string>;
|
|
7
|
+
body: any;
|
|
8
|
+
cookies: Record<string, string>;
|
|
9
|
+
ip: string;
|
|
10
|
+
protocol: "http" | "https";
|
|
11
|
+
secure: boolean;
|
|
12
|
+
hostname: string;
|
|
13
|
+
requestId?: string;
|
|
14
|
+
startTime: bigint;
|
|
15
|
+
session?: Record<string, any>;
|
|
16
|
+
user?: any;
|
|
17
|
+
raw: IncomingMessage;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CookieOptions {
|
|
21
|
+
maxAge?: number;
|
|
22
|
+
expires?: Date;
|
|
23
|
+
path?: string;
|
|
24
|
+
domain?: string;
|
|
25
|
+
secure?: boolean;
|
|
26
|
+
httpOnly?: boolean;
|
|
27
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
28
|
+
signed?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface AzuraResponse extends ServerResponse {
|
|
32
|
+
status(code: number): AzuraResponse;
|
|
33
|
+
json(data: unknown): void;
|
|
34
|
+
send(body: string | Buffer): void;
|
|
35
|
+
html(body: string): void;
|
|
36
|
+
redirect(url: string, code?: number): void;
|
|
37
|
+
cookie(name: string, value: string, options?: CookieOptions): AzuraResponse;
|
|
38
|
+
clearCookie(name: string, options?: CookieOptions): AzuraResponse;
|
|
39
|
+
header(name: string, value: string | number | string[]): AzuraResponse;
|
|
40
|
+
type(contentType: string): AzuraResponse;
|
|
41
|
+
attachment(filename?: string): AzuraResponse;
|
|
42
|
+
download(path: string, filename?: string): void;
|
|
43
|
+
locals: Record<string, any>;
|
|
44
|
+
sent: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type NextFunction = (err?: Error | unknown) => void;
|
|
48
|
+
|
|
49
|
+
export type MiddlewareHandler = (
|
|
50
|
+
req: AzuraRequest,
|
|
51
|
+
res: AzuraResponse,
|
|
52
|
+
next: NextFunction,
|
|
53
|
+
) => void | Promise<void>;
|
|
54
|
+
|
|
55
|
+
export type RouteHandler = (
|
|
56
|
+
req: AzuraRequest,
|
|
57
|
+
res: AzuraResponse,
|
|
58
|
+
...args: any[]
|
|
59
|
+
) => any | Promise<any>;
|
|
60
|
+
|
|
61
|
+
export type ErrorHandler = (
|
|
62
|
+
err: Error | unknown,
|
|
63
|
+
req: AzuraRequest,
|
|
64
|
+
res: AzuraResponse,
|
|
65
|
+
next: NextFunction,
|
|
66
|
+
) => void | Promise<void>;
|
|
67
|
+
|
|
68
|
+
export type HttpMethod =
|
|
69
|
+
| "GET"
|
|
70
|
+
| "POST"
|
|
71
|
+
| "PUT"
|
|
72
|
+
| "DELETE"
|
|
73
|
+
| "PATCH"
|
|
74
|
+
| "HEAD"
|
|
75
|
+
| "OPTIONS";
|
|
76
|
+
|
|
77
|
+
export interface RouteMatch {
|
|
78
|
+
handler: RouteHandler;
|
|
79
|
+
params: Record<string, string>;
|
|
80
|
+
middlewares: MiddlewareHandler[];
|
|
81
|
+
meta?: Record<string, any>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CORSOptions,
|
|
3
|
+
RateLimitOptions,
|
|
4
|
+
HelmetOptions,
|
|
5
|
+
JWTOptions,
|
|
6
|
+
SessionOptions,
|
|
7
|
+
CompressionOptions,
|
|
8
|
+
StaticOptions,
|
|
9
|
+
HealthCheckOptions,
|
|
10
|
+
CircuitBreakerOptions,
|
|
11
|
+
} from "./plugins/plugin.type.js";
|
|
12
|
+
|
|
13
|
+
export interface AzuraConfig {
|
|
14
|
+
environment?: "development" | "production" | "test";
|
|
15
|
+
server?: ServerConfig;
|
|
16
|
+
logging?: LoggingConfig;
|
|
17
|
+
plugins?: PluginsConfig;
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ServerConfig {
|
|
22
|
+
port?: number;
|
|
23
|
+
host?: string;
|
|
24
|
+
cluster?: boolean;
|
|
25
|
+
clusterInstances?: number;
|
|
26
|
+
https?: HttpsConfig | false;
|
|
27
|
+
keepAliveTimeout?: number;
|
|
28
|
+
headersTimeout?: number;
|
|
29
|
+
maxHeaderSize?: number;
|
|
30
|
+
requestTimeout?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface HttpsConfig {
|
|
34
|
+
key: string;
|
|
35
|
+
cert: string;
|
|
36
|
+
ca?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface LoggingConfig {
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
level?: "debug" | "info" | "warn" | "error" | "silent";
|
|
42
|
+
timestamp?: boolean;
|
|
43
|
+
colors?: boolean;
|
|
44
|
+
requestLogging?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface PluginsConfig {
|
|
48
|
+
cors?: CORSOptions & { enabled?: boolean };
|
|
49
|
+
rateLimit?: RateLimitOptions & { enabled?: boolean };
|
|
50
|
+
helmet?: HelmetOptions & { enabled?: boolean };
|
|
51
|
+
jwt?: JWTOptions & { enabled?: boolean };
|
|
52
|
+
session?: SessionOptions & { enabled?: boolean };
|
|
53
|
+
compression?: CompressionOptions & { enabled?: boolean };
|
|
54
|
+
static?: StaticOptions & { enabled?: boolean };
|
|
55
|
+
healthCheck?: HealthCheckOptions & { enabled?: boolean };
|
|
56
|
+
circuitBreaker?: CircuitBreakerOptions & { enabled?: boolean };
|
|
57
|
+
}
|
|
@@ -1,51 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
//# sourceMappingURL=chunk-OWUGAI5V.mjs.map
|
|
51
|
-
//# sourceMappingURL=chunk-OWUGAI5V.mjs.map
|
|
1
|
+
export const HttpStatus = {
|
|
2
|
+
OK: 200,
|
|
3
|
+
CREATED: 201,
|
|
4
|
+
ACCEPTED: 202,
|
|
5
|
+
NO_CONTENT: 204,
|
|
6
|
+
MOVED_PERMANENTLY: 301,
|
|
7
|
+
FOUND: 302,
|
|
8
|
+
NOT_MODIFIED: 304,
|
|
9
|
+
BAD_REQUEST: 400,
|
|
10
|
+
UNAUTHORIZED: 401,
|
|
11
|
+
FORBIDDEN: 403,
|
|
12
|
+
NOT_FOUND: 404,
|
|
13
|
+
METHOD_NOT_ALLOWED: 405,
|
|
14
|
+
CONFLICT: 409,
|
|
15
|
+
GONE: 410,
|
|
16
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
17
|
+
TOO_MANY_REQUESTS: 429,
|
|
18
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
19
|
+
NOT_IMPLEMENTED: 501,
|
|
20
|
+
BAD_GATEWAY: 502,
|
|
21
|
+
SERVICE_UNAVAILABLE: 503,
|
|
22
|
+
GATEWAY_TIMEOUT: 504,
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
export type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus];
|
|
26
|
+
|
|
27
|
+
export const HttpStatusText: Record<number, string> = {
|
|
28
|
+
200: "OK",
|
|
29
|
+
201: "Created",
|
|
30
|
+
202: "Accepted",
|
|
31
|
+
204: "No Content",
|
|
32
|
+
301: "Moved Permanently",
|
|
33
|
+
302: "Found",
|
|
34
|
+
304: "Not Modified",
|
|
35
|
+
400: "Bad Request",
|
|
36
|
+
401: "Unauthorized",
|
|
37
|
+
403: "Forbidden",
|
|
38
|
+
404: "Not Found",
|
|
39
|
+
405: "Method Not Allowed",
|
|
40
|
+
409: "Conflict",
|
|
41
|
+
410: "Gone",
|
|
42
|
+
422: "Unprocessable Entity",
|
|
43
|
+
429: "Too Many Requests",
|
|
44
|
+
500: "Internal Server Error",
|
|
45
|
+
501: "Not Implemented",
|
|
46
|
+
502: "Bad Gateway",
|
|
47
|
+
503: "Service Unavailable",
|
|
48
|
+
504: "Gateway Timeout",
|
|
49
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
AzuraRequest,
|
|
3
|
+
AzuraResponse,
|
|
4
|
+
NextFunction,
|
|
5
|
+
MiddlewareHandler,
|
|
6
|
+
RouteHandler,
|
|
7
|
+
ErrorHandler,
|
|
8
|
+
HttpMethod,
|
|
9
|
+
RouteMatch,
|
|
10
|
+
CookieOptions,
|
|
11
|
+
} from "./common.type.js";
|
|
12
|
+
|
|
13
|
+
export type {
|
|
14
|
+
RouteDefinition,
|
|
15
|
+
RouteMeta,
|
|
16
|
+
ParameterMeta,
|
|
17
|
+
ResponseMeta,
|
|
18
|
+
ParamType,
|
|
19
|
+
ParamMetadata,
|
|
20
|
+
ControllerMetadata,
|
|
21
|
+
RouteMetadata,
|
|
22
|
+
} from "./routes.type.js";
|
|
23
|
+
|
|
24
|
+
export type {
|
|
25
|
+
AzuraConfig,
|
|
26
|
+
ServerConfig,
|
|
27
|
+
LoggingConfig,
|
|
28
|
+
PluginsConfig,
|
|
29
|
+
} from "./config.type.js";
|
|
30
|
+
|
|
31
|
+
export { HttpStatus, HttpStatusText } from "./http/status.js";
|
|
32
|
+
export type { HttpStatusCode } from "./http/status.js";
|
|
33
|
+
|
|
34
|
+
export type {
|
|
35
|
+
PluginContext,
|
|
36
|
+
PluginHandler,
|
|
37
|
+
PluginFactory,
|
|
38
|
+
PluginDefinition,
|
|
39
|
+
CORSOptions,
|
|
40
|
+
RateLimitOptions,
|
|
41
|
+
HelmetOptions,
|
|
42
|
+
JWTOptions,
|
|
43
|
+
SessionOptions,
|
|
44
|
+
CompressionOptions,
|
|
45
|
+
StaticOptions,
|
|
46
|
+
ETagOptions,
|
|
47
|
+
RequestIdOptions,
|
|
48
|
+
TimeoutOptions,
|
|
49
|
+
HealthCheckOptions,
|
|
50
|
+
CircuitBreakerOptions,
|
|
51
|
+
CircuitBreakerState,
|
|
52
|
+
ProxyOptions,
|
|
53
|
+
SSEOptions,
|
|
54
|
+
MultipartOptions,
|
|
55
|
+
} from "./plugins/plugin.type.js";
|