tezx 2.0.11 → 3.0.0
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/README.md +122 -89
- package/bun/getConnInfo.d.ts +21 -0
- package/bun/getConnInfo.js +9 -0
- package/bun/index.d.ts +10 -4
- package/bun/index.js +8 -4
- package/bun/ws.d.ts +48 -0
- package/bun/ws.js +58 -0
- package/cjs/bun/getConnInfo.js +12 -0
- package/cjs/bun/index.js +35 -7
- package/cjs/bun/ws.js +63 -0
- package/cjs/core/config.js +2 -12
- package/cjs/core/context.js +131 -379
- package/cjs/core/error.js +49 -0
- package/cjs/core/request.js +79 -131
- package/cjs/core/router.js +54 -387
- package/cjs/core/server.js +83 -202
- package/cjs/deno/env.js +4 -4
- package/cjs/deno/getConnInfo.js +18 -0
- package/cjs/deno/index.js +11 -18
- package/cjs/deno/serveStatic.js +53 -0
- package/cjs/deno/ws.js +39 -0
- package/cjs/helper/index.js +46 -10
- package/cjs/index.js +5 -7
- package/cjs/jwt/node.js +94 -0
- package/cjs/jwt/web.js +178 -0
- package/cjs/middleware/basic-auth.js +42 -0
- package/cjs/middleware/bearer-auth.js +34 -0
- package/cjs/middleware/cache-control.js +44 -0
- package/cjs/middleware/cors.js +11 -21
- package/cjs/middleware/detect-bot.js +57 -0
- package/cjs/middleware/i18n.js +73 -60
- package/cjs/middleware/index.js +8 -46
- package/cjs/middleware/logger.js +9 -4
- package/cjs/middleware/pagination.js +3 -2
- package/cjs/middleware/powered-by.js +3 -2
- package/cjs/middleware/rate-limiter.js +38 -0
- package/cjs/middleware/request-id.js +4 -5
- package/cjs/middleware/sanitize-headers.js +22 -0
- package/cjs/middleware/secure-headers copy.js +143 -0
- package/cjs/middleware/secure-headers.js +157 -0
- package/cjs/middleware/{xssProtection.js → xss-protection.js} +5 -8
- package/cjs/node/env.js +7 -7
- package/cjs/node/getConnInfo.js +16 -0
- package/cjs/node/index.js +17 -18
- package/cjs/node/mount-node.js +59 -0
- package/cjs/node/serveStatic.js +56 -0
- package/cjs/node/toWebRequest.js +25 -0
- package/cjs/node/ws.js +82 -0
- package/cjs/registry/RadixRouter.js +148 -0
- package/cjs/registry/index.js +17 -0
- package/cjs/types/headers.js +2 -0
- package/cjs/types/index.js +13 -0
- package/cjs/utils/buffer.js +17 -0
- package/cjs/utils/colors.js +2 -0
- package/cjs/utils/cookie.js +59 -0
- package/cjs/utils/file.js +136 -0
- package/cjs/utils/formData.js +60 -10
- package/cjs/utils/generateID.js +37 -0
- package/cjs/utils/low-level.js +115 -0
- package/cjs/utils/{staticFile.js → mimeTypes.js} +0 -87
- package/cjs/utils/rateLimit.js +41 -0
- package/cjs/utils/response.js +65 -0
- package/cjs/{core/environment.js → utils/runtime.js} +2 -1
- package/cjs/utils/url.js +65 -30
- package/core/config.d.ts +2 -7
- package/core/config.js +2 -12
- package/core/context.d.ts +209 -164
- package/core/context.js +131 -346
- package/core/error.d.ts +96 -0
- package/core/error.js +44 -0
- package/core/request.d.ts +67 -107
- package/core/request.js +78 -130
- package/core/router.d.ts +138 -133
- package/core/router.js +53 -352
- package/core/server.d.ts +99 -38
- package/core/server.js +83 -202
- package/deno/env.js +3 -3
- package/deno/getConnInfo.d.ts +21 -0
- package/deno/getConnInfo.js +15 -0
- package/deno/index.d.ts +9 -4
- package/deno/index.js +7 -4
- package/deno/serveStatic.d.ts +28 -0
- package/deno/serveStatic.js +49 -0
- package/deno/ws.d.ts +42 -0
- package/deno/ws.js +36 -0
- package/helper/index.d.ts +29 -15
- package/helper/index.js +27 -7
- package/index.d.ts +10 -8
- package/index.js +4 -5
- package/jwt/node.d.ts +39 -0
- package/jwt/node.js +87 -0
- package/jwt/web.d.ts +14 -0
- package/jwt/web.js +174 -0
- package/middleware/basic-auth.d.ts +56 -0
- package/middleware/basic-auth.js +38 -0
- package/middleware/bearer-auth.d.ts +53 -0
- package/middleware/bearer-auth.js +30 -0
- package/middleware/cache-control.d.ts +30 -0
- package/middleware/cache-control.js +40 -0
- package/middleware/cors.d.ts +30 -3
- package/middleware/cors.js +12 -22
- package/middleware/detect-bot.d.ts +113 -0
- package/middleware/detect-bot.js +53 -0
- package/middleware/i18n.d.ts +166 -73
- package/middleware/i18n.js +73 -60
- package/middleware/index.d.ts +8 -32
- package/middleware/index.js +8 -44
- package/middleware/logger.d.ts +5 -2
- package/middleware/logger.js +9 -4
- package/middleware/pagination.d.ts +9 -6
- package/middleware/pagination.js +3 -2
- package/middleware/powered-by.d.ts +2 -1
- package/middleware/powered-by.js +3 -2
- package/middleware/{rateLimiter.d.ts → rate-limiter.d.ts} +15 -9
- package/middleware/rate-limiter.js +34 -0
- package/middleware/request-id.d.ts +2 -1
- package/middleware/request-id.js +5 -6
- package/middleware/{sanitizeHeader.d.ts → sanitize-headers.d.ts} +5 -19
- package/middleware/sanitize-headers.js +18 -0
- package/middleware/secure-headers copy.d.ts +15 -0
- package/middleware/secure-headers copy.js +136 -0
- package/middleware/secure-headers.d.ts +132 -0
- package/middleware/secure-headers.js +153 -0
- package/middleware/{xssProtection.d.ts → xss-protection.d.ts} +2 -1
- package/middleware/xss-protection.js +19 -0
- package/node/env.js +4 -4
- package/node/getConnInfo.d.ts +21 -0
- package/node/getConnInfo.js +13 -0
- package/node/index.d.ts +13 -4
- package/node/index.js +11 -4
- package/node/mount-node.d.ts +11 -0
- package/node/mount-node.js +56 -0
- package/node/serveStatic.d.ts +36 -0
- package/node/serveStatic.js +52 -0
- package/node/toWebRequest.js +22 -0
- package/node/ws.d.ts +56 -0
- package/node/ws.js +46 -0
- package/package.json +39 -30
- package/registry/RadixRouter.d.ts +40 -0
- package/registry/RadixRouter.js +144 -0
- package/registry/index.d.ts +2 -0
- package/registry/index.js +1 -0
- package/types/headers.d.ts +2 -0
- package/types/headers.js +1 -0
- package/types/index.d.ts +318 -18
- package/types/index.js +12 -1
- package/utils/buffer.d.ts +1 -0
- package/utils/buffer.js +14 -0
- package/utils/colors.d.ts +24 -0
- package/utils/colors.js +2 -0
- package/utils/cookie.d.ts +55 -0
- package/utils/cookie.js +53 -0
- package/utils/file.d.ts +38 -0
- package/utils/file.js +96 -0
- package/utils/formData.d.ts +41 -1
- package/utils/formData.js +58 -9
- package/utils/generateID.d.ts +42 -0
- package/utils/generateID.js +32 -0
- package/utils/httpStatusMap.d.ts +14 -0
- package/utils/low-level.d.ts +58 -0
- package/utils/low-level.js +108 -0
- package/utils/mimeTypes.d.ts +4 -0
- package/utils/{staticFile.js → mimeTypes.js} +0 -53
- package/utils/rateLimit.d.ts +18 -0
- package/utils/rateLimit.js +37 -0
- package/utils/response.d.ts +18 -0
- package/utils/response.js +58 -0
- package/{core/environment.d.ts → utils/runtime.d.ts} +1 -0
- package/{core/environment.js → utils/runtime.js} +1 -0
- package/utils/url.d.ts +42 -14
- package/utils/url.js +61 -27
- package/bun/adapter.d.ts +0 -127
- package/bun/adapter.js +0 -97
- package/cjs/bun/adapter.js +0 -100
- package/cjs/core/MiddlewareConfigure.js +0 -68
- package/cjs/core/common.js +0 -15
- package/cjs/deno/adpater.js +0 -67
- package/cjs/helper/common.js +0 -17
- package/cjs/middleware/basicAuth.js +0 -71
- package/cjs/middleware/cacheControl.js +0 -90
- package/cjs/middleware/detectBot.js +0 -104
- package/cjs/middleware/detectLocale.js +0 -43
- package/cjs/middleware/lazyLoadModules.js +0 -73
- package/cjs/middleware/rateLimiter.js +0 -24
- package/cjs/middleware/requestTimeout.js +0 -42
- package/cjs/middleware/sanitizeHeader.js +0 -51
- package/cjs/middleware/secureHeaders.js +0 -42
- package/cjs/node/adapter.js +0 -138
- package/cjs/utils/regexRouter.js +0 -58
- package/cjs/utils/state.js +0 -34
- package/cjs/utils/toWebRequest.js +0 -35
- package/cjs/ws/deno.js +0 -20
- package/cjs/ws/index.js +0 -53
- package/cjs/ws/node.js +0 -65
- package/core/MiddlewareConfigure.d.ts +0 -15
- package/core/MiddlewareConfigure.js +0 -63
- package/core/common.d.ts +0 -21
- package/core/common.js +0 -11
- package/deno/adpater.d.ts +0 -38
- package/deno/adpater.js +0 -64
- package/helper/common.d.ts +0 -5
- package/helper/common.js +0 -14
- package/middleware/basicAuth.d.ts +0 -81
- package/middleware/basicAuth.js +0 -67
- package/middleware/cacheControl.d.ts +0 -48
- package/middleware/cacheControl.js +0 -53
- package/middleware/detectBot.d.ts +0 -121
- package/middleware/detectBot.js +0 -98
- package/middleware/detectLocale.d.ts +0 -55
- package/middleware/detectLocale.js +0 -39
- package/middleware/lazyLoadModules.d.ts +0 -72
- package/middleware/lazyLoadModules.js +0 -69
- package/middleware/rateLimiter.js +0 -20
- package/middleware/requestTimeout.d.ts +0 -25
- package/middleware/requestTimeout.js +0 -38
- package/middleware/sanitizeHeader.js +0 -47
- package/middleware/secureHeaders.d.ts +0 -78
- package/middleware/secureHeaders.js +0 -38
- package/middleware/xssProtection.js +0 -22
- package/node/adapter.d.ts +0 -46
- package/node/adapter.js +0 -102
- package/utils/regexRouter.d.ts +0 -66
- package/utils/regexRouter.js +0 -53
- package/utils/state.d.ts +0 -50
- package/utils/state.js +0 -30
- package/utils/staticFile.d.ts +0 -10
- package/utils/toWebRequest.js +0 -32
- package/ws/deno.d.ts +0 -6
- package/ws/deno.js +0 -16
- package/ws/index.d.ts +0 -180
- package/ws/index.js +0 -50
- package/ws/node.d.ts +0 -7
- package/ws/node.js +0 -28
- /package/{utils → node}/toWebRequest.d.ts +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { extensionExtract, sanitizePathSplitBasePath, } from "../utils/low-level.js";
|
|
4
|
+
import { TezXError } from "../core/error.js";
|
|
5
|
+
export function serveStatic(...args) {
|
|
6
|
+
let route = "";
|
|
7
|
+
let dir;
|
|
8
|
+
let options = {};
|
|
9
|
+
switch (args.length) {
|
|
10
|
+
case 3:
|
|
11
|
+
[route, dir, options] = args;
|
|
12
|
+
break;
|
|
13
|
+
case 2:
|
|
14
|
+
if (typeof args[1] === "object") {
|
|
15
|
+
[dir, options] = args;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
[route, dir] = args;
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
case 1:
|
|
22
|
+
[dir] = args;
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
throw new TezXError(`\x1b[1;31m404 Not Found\x1b[0m \x1b[1;32mInvalid arguments\x1b[0m`);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
files: getFiles(dir, route, options),
|
|
29
|
+
options,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function getFiles(dir, basePath = "/", option = {}) {
|
|
33
|
+
const files = [];
|
|
34
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
const fullPath = join(dir, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
files.push(...getFiles(fullPath, `${basePath}/${entry.name}`, option));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const ext = extensionExtract(entry.name);
|
|
42
|
+
if (option?.extensions?.length && !option.extensions.includes(ext)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
files.push({
|
|
46
|
+
fileSource: fullPath,
|
|
47
|
+
route: `/${sanitizePathSplitBasePath(basePath, entry.name).join("/")}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return files;
|
|
52
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
export function toWebRequest(req, method = "GET") {
|
|
3
|
+
const protocol = req.socket && req.socket.encrypted ? "https:" : "http:";
|
|
4
|
+
const upperMethod = method.length === 3
|
|
5
|
+
? method === "get"
|
|
6
|
+
? "GET"
|
|
7
|
+
: method === "put"
|
|
8
|
+
? "PUT"
|
|
9
|
+
: method.toUpperCase()
|
|
10
|
+
: method.toUpperCase();
|
|
11
|
+
let host = req.headers.host || "localhost";
|
|
12
|
+
const hasBody = upperMethod !== "GET" && upperMethod !== "HEAD";
|
|
13
|
+
const abortController = new AbortController();
|
|
14
|
+
req?.once("close", () => abortController.abort());
|
|
15
|
+
return new Request(protocol + "//" + host + (req.url ?? "/"), {
|
|
16
|
+
method,
|
|
17
|
+
headers: req?.headers,
|
|
18
|
+
body: hasBody ? Readable.toWeb(req) : undefined,
|
|
19
|
+
signal: abortController.signal,
|
|
20
|
+
duplex: hasBody ? "half" : undefined,
|
|
21
|
+
});
|
|
22
|
+
}
|
package/node/ws.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { PerMessageDeflateOptions } from "ws";
|
|
2
|
+
import { Middleware, WebSocketCallback, WebSocketOptions } from "../types/index.js";
|
|
3
|
+
export type nodeWebSocketOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* Enables per-message deflate compression. Can be a boolean or a detailed config. (Node.js only)
|
|
6
|
+
*/
|
|
7
|
+
perMessageDeflate?: boolean | PerMessageDeflateOptions;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum allowed message size in bytes. Default is 1MB if not provided. (Node.js only)
|
|
10
|
+
*/
|
|
11
|
+
maxPayload?: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Node.js-specific WebSocket upgrade middleware.
|
|
15
|
+
*
|
|
16
|
+
* This middleware validates WebSocket upgrade headers and upgrades the HTTP connection
|
|
17
|
+
* to a WebSocket connection using the `ws` library. It binds event handlers
|
|
18
|
+
* (`open`, `message`, `close`, `error`, `ping`, `pong`) based on the provided callback.
|
|
19
|
+
*
|
|
20
|
+
* @template T - Context type extending object with `wsProtocol` property ("ws" or "wss").
|
|
21
|
+
* @template Path - Route path type (string).
|
|
22
|
+
*
|
|
23
|
+
* @param {WebSocketCallback} callback - Function that returns WebSocket event handlers.
|
|
24
|
+
* @param {WebSocketOptions} [options={}] - Options for WebSocket upgrade behavior.
|
|
25
|
+
* @param {(error: TezXError, ctx: T) => any} [options.onUpgradeError] - Custom error handler for upgrade failures.
|
|
26
|
+
* @param {number} [options.maxPayload=1048576] - Maximum allowed payload size (in bytes).
|
|
27
|
+
* @param {boolean} [options.perMessageDeflate=false] - Whether to enable per-message deflate.
|
|
28
|
+
*
|
|
29
|
+
* @returns {Middleware<T, Path>} Middleware function for handling WebSocket upgrade requests.
|
|
30
|
+
*
|
|
31
|
+
* @throws Will return a 401 response if WebSocket upgrade headers are invalid.
|
|
32
|
+
* @throws Will return a 500 response if Node.js HTTP server instance is missing in context arguments.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { upgradeWebSocket } from "./nodeWebSocket.js";
|
|
37
|
+
*
|
|
38
|
+
* const wsMiddleware = upgradeWebSocket(ctx => ({
|
|
39
|
+
* open(ws) {
|
|
40
|
+
* console.log("WebSocket connection opened");
|
|
41
|
+
* },
|
|
42
|
+
* message(ws, data) {
|
|
43
|
+
* console.log("Received message:", data);
|
|
44
|
+
* },
|
|
45
|
+
* close(ws, event) {
|
|
46
|
+
* console.log("Connection closed:", event.code, event.reason);
|
|
47
|
+
* },
|
|
48
|
+
* error(ws, err) {
|
|
49
|
+
* console.error("WebSocket error:", err);
|
|
50
|
+
* },
|
|
51
|
+
* }));
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function upgradeWebSocket<T extends Record<string, any> & {
|
|
55
|
+
wsProtocol: "wss" | "ws";
|
|
56
|
+
}, Path extends string = any>(callback: WebSocketCallback, options?: WebSocketOptions & nodeWebSocketOptions): Middleware<T, Path>;
|
package/node/ws.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TezXError } from "../core/error.js";
|
|
2
|
+
export function upgradeWebSocket(callback, options = {}) {
|
|
3
|
+
const { onUpgradeError = (error, ctx) => {
|
|
4
|
+
ctx.setStatus = 401;
|
|
5
|
+
return ctx.text(error.message);
|
|
6
|
+
}, } = options;
|
|
7
|
+
return async (ctx, next) => {
|
|
8
|
+
const upgrade = ctx.req.header("upgrade")?.toLowerCase();
|
|
9
|
+
const connection = ctx.req.header("connection")?.toLowerCase();
|
|
10
|
+
const key = ctx.req.header("sec-websocket-key");
|
|
11
|
+
if (upgrade !== "websocket" || !connection?.includes("upgrade") || !key) {
|
|
12
|
+
if (next) {
|
|
13
|
+
ctx.body = { error: "401 Bad Request: Invalid WebSocket headers" };
|
|
14
|
+
return next();
|
|
15
|
+
}
|
|
16
|
+
ctx.setStatus = 401;
|
|
17
|
+
return onUpgradeError(new TezXError("401 Bad Request: Invalid WebSocket headers", 401), ctx);
|
|
18
|
+
}
|
|
19
|
+
ctx.wsProtocol = ctx.url?.startsWith("https") ? "wss" : "ws";
|
|
20
|
+
const server = ctx.args?.[2];
|
|
21
|
+
if (!server?.on) {
|
|
22
|
+
ctx.setStatus = 500;
|
|
23
|
+
return onUpgradeError(new TezXError("Node server instance missing for WebSocket", 426), ctx);
|
|
24
|
+
}
|
|
25
|
+
const { WebSocketServer } = await import("ws");
|
|
26
|
+
const wss = new WebSocketServer({
|
|
27
|
+
noServer: true,
|
|
28
|
+
maxPayload: options.maxPayload ?? 1048576,
|
|
29
|
+
perMessageDeflate: options.perMessageDeflate ?? false,
|
|
30
|
+
});
|
|
31
|
+
server.on("upgrade", (request, socket, head) => {
|
|
32
|
+
wss?.handleUpgrade(request, socket, head, (ws) => {
|
|
33
|
+
wss?.emit("connection", ws, request);
|
|
34
|
+
let event = callback(ctx);
|
|
35
|
+
event.open?.(ws);
|
|
36
|
+
ws.on("open", () => event.open?.(ws));
|
|
37
|
+
ws.on("message", (data) => event.message?.(ws, data));
|
|
38
|
+
ws.on("close", (code, reason) => event.close?.(ws, { code, reason }));
|
|
39
|
+
ws.on("error", (err) => event.error?.(ws, err));
|
|
40
|
+
ws.on("ping", (data) => event.ping?.(ws, data));
|
|
41
|
+
ws.on("pong", (data) => event.pong?.(ws, data));
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
return next();
|
|
45
|
+
};
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tezx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "TezX is a high-performance, lightweight JavaScript framework designed for speed, scalability, and flexibility. It enables efficient routing, middleware management, and static file serving with minimal configuration. Fully compatible with Node.js, Deno, and Bun.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "cjs/index.js",
|
|
6
7
|
"module": "index.js",
|
|
7
8
|
"types": "index.d.ts",
|
|
@@ -19,60 +20,68 @@
|
|
|
19
20
|
".": {
|
|
20
21
|
"import": "./index.js",
|
|
21
22
|
"require": "./cjs/index.js",
|
|
22
|
-
"types": "./index.d.ts"
|
|
23
|
-
"default": "./index.js"
|
|
23
|
+
"types": "./index.d.ts"
|
|
24
24
|
},
|
|
25
|
-
"./
|
|
26
|
-
"import": "./
|
|
27
|
-
"require": "./cjs/
|
|
28
|
-
"types": "./
|
|
29
|
-
"default": "./middleware/index.js"
|
|
25
|
+
"./bun": {
|
|
26
|
+
"import": "./bun/index.js",
|
|
27
|
+
"require": "./cjs/bun/index.js",
|
|
28
|
+
"types": "./bun/index.d.ts"
|
|
30
29
|
},
|
|
31
30
|
"./node": {
|
|
32
31
|
"import": "./node/index.js",
|
|
33
32
|
"require": "./cjs/node/index.js",
|
|
34
|
-
"types": "./node/index.d.ts"
|
|
35
|
-
"default": "./node/index.js"
|
|
36
|
-
},
|
|
37
|
-
"./bun": {
|
|
38
|
-
"import": "./bun/index.js",
|
|
39
|
-
"require": "./cjs/bun/index.js",
|
|
40
|
-
"types": "./bun/index.d.ts",
|
|
41
|
-
"default": "./bun/index.js"
|
|
33
|
+
"types": "./node/index.d.ts"
|
|
42
34
|
},
|
|
43
35
|
"./deno": {
|
|
44
36
|
"import": "./deno/index.js",
|
|
45
37
|
"require": "./cjs/deno/index.js",
|
|
46
|
-
"types": "./deno/index.d.ts"
|
|
47
|
-
"default": "./deno/index.js"
|
|
38
|
+
"types": "./deno/index.d.ts"
|
|
48
39
|
},
|
|
49
40
|
"./helper": {
|
|
50
41
|
"import": "./helper/index.js",
|
|
51
42
|
"require": "./cjs/helper/index.js",
|
|
52
|
-
"types": "./helper/index.d.ts"
|
|
53
|
-
"default": "./helper/index.js"
|
|
43
|
+
"types": "./helper/index.d.ts"
|
|
54
44
|
},
|
|
55
|
-
"./
|
|
56
|
-
"import": "./
|
|
57
|
-
"require": "./cjs/
|
|
58
|
-
"types": "./
|
|
59
|
-
|
|
45
|
+
"./jwt/node": {
|
|
46
|
+
"import": "./jwt/node.js",
|
|
47
|
+
"require": "./cjs/jwt/node.js",
|
|
48
|
+
"types": "./jwt/node.d.ts"
|
|
49
|
+
},
|
|
50
|
+
"./jwt/web": {
|
|
51
|
+
"import": "./jwt/web.js",
|
|
52
|
+
"require": "./cjs/jwt/web.js",
|
|
53
|
+
"types": "./jwt/web.d.ts"
|
|
54
|
+
},
|
|
55
|
+
"./registry": {
|
|
56
|
+
"import": "./registry/index.js",
|
|
57
|
+
"require": "./cjs/registry/index.js",
|
|
58
|
+
"types": "./registry/index.d.ts"
|
|
59
|
+
},
|
|
60
|
+
"./middleware": {
|
|
61
|
+
"import": "./middleware/index.js",
|
|
62
|
+
"require": "./cjs/middleware/index.js",
|
|
63
|
+
"types": "./middleware/index.d.ts"
|
|
64
|
+
},
|
|
65
|
+
"./middleware/*": {
|
|
66
|
+
"import": "./middleware/*.js",
|
|
67
|
+
"require": "./cjs/middleware/*.js",
|
|
68
|
+
"types": "./middleware/*.d.ts"
|
|
60
69
|
}
|
|
61
70
|
},
|
|
62
71
|
"files": [
|
|
63
|
-
"adapter/",
|
|
64
72
|
"bun/",
|
|
65
73
|
"cjs/",
|
|
66
74
|
"core/",
|
|
67
75
|
"deno/",
|
|
68
76
|
"helper/",
|
|
69
|
-
"
|
|
77
|
+
"jwt/",
|
|
70
78
|
"middleware/",
|
|
79
|
+
"node/",
|
|
80
|
+
"registry/",
|
|
71
81
|
"types/",
|
|
72
82
|
"utils/",
|
|
73
|
-
"
|
|
74
|
-
"index.js"
|
|
75
|
-
"index.d.ts"
|
|
83
|
+
"index.d.ts",
|
|
84
|
+
"index.js"
|
|
76
85
|
],
|
|
77
86
|
"keywords": [
|
|
78
87
|
"server",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Callback, HTTPMethod, Middleware, RouteMatchResult, RouteRegistry } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Radix-based router implementation for efficient route matching.
|
|
4
|
+
* Supports static, dynamic, optional, and wildcard parameters.
|
|
5
|
+
*/
|
|
6
|
+
export declare class RadixRouter implements RouteRegistry {
|
|
7
|
+
private root;
|
|
8
|
+
name: string;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Adds a new route to the radix tree.
|
|
12
|
+
*
|
|
13
|
+
* @param method - HTTP method (GET, POST, etc.)
|
|
14
|
+
* @param path - Route path, e.g., "/users/:id?"
|
|
15
|
+
* @param handlers - Array of handler functions or middleware
|
|
16
|
+
* @throws Error if conflicting parameter definitions are detected
|
|
17
|
+
*/
|
|
18
|
+
addRoute(method: HTTPMethod, path: string, handlers: (Callback | Middleware)[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Searches for a route match based on HTTP method and URL path.
|
|
21
|
+
*
|
|
22
|
+
* @param method - HTTP method to match
|
|
23
|
+
* @param path - Request path
|
|
24
|
+
* @returns RouteMatchResult containing handlers, middlewares, and parameters
|
|
25
|
+
*/
|
|
26
|
+
search(method: HTTPMethod, path: string): RouteMatchResult;
|
|
27
|
+
/**
|
|
28
|
+
* Recursively matches the route path segments.
|
|
29
|
+
*
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
private _match;
|
|
33
|
+
/**
|
|
34
|
+
* Parses a route pattern into structured segments.
|
|
35
|
+
*
|
|
36
|
+
* @param pattern - The route string (e.g., "/users/:id?")
|
|
37
|
+
* @returns Parsed segments containing type, value, paramName, and optionality
|
|
38
|
+
*/
|
|
39
|
+
private parsePattern;
|
|
40
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { TezXError } from "../core/error.js";
|
|
2
|
+
import { sanitizePathSplit } from "../helper/index.js";
|
|
3
|
+
export class RadixRouter {
|
|
4
|
+
root = { children: {} };
|
|
5
|
+
name;
|
|
6
|
+
constructor() {
|
|
7
|
+
this.name = "RadixRouter";
|
|
8
|
+
}
|
|
9
|
+
addRoute(method, path, handlers) {
|
|
10
|
+
const segments = this.parsePattern(path);
|
|
11
|
+
let node = this.root;
|
|
12
|
+
for (let i = 0; i < segments.length; i++) {
|
|
13
|
+
const { type, value, paramName, isOptional } = segments[i];
|
|
14
|
+
if (type === "static") {
|
|
15
|
+
node = node.children[value] ??= { children: {} };
|
|
16
|
+
}
|
|
17
|
+
else if (type === "dynamic") {
|
|
18
|
+
if (!node.children[":"]) {
|
|
19
|
+
node.children[":"] = { children: {}, paramName, isOptional };
|
|
20
|
+
}
|
|
21
|
+
else if (node.children[":"]?.paramName !== paramName ||
|
|
22
|
+
node.children[":"]?.isOptional !== isOptional) {
|
|
23
|
+
throw new TezXError(`Conflicting param definition for ${paramName}`);
|
|
24
|
+
}
|
|
25
|
+
node = node.children[":"];
|
|
26
|
+
}
|
|
27
|
+
else if (type === "wildcard") {
|
|
28
|
+
node = node.children["*"] ??= { children: {}, paramName };
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
node.isEndpoint = true;
|
|
33
|
+
node.handlers ??= {};
|
|
34
|
+
node.handlers[method] ??= [];
|
|
35
|
+
node.handlers[method].push(...(handlers || []));
|
|
36
|
+
}
|
|
37
|
+
search(method, path) {
|
|
38
|
+
let params = {};
|
|
39
|
+
let middlewares = [];
|
|
40
|
+
const { success, node } = this._match(method, this.root, path?.split("/")?.filter(Boolean), 0, params, middlewares);
|
|
41
|
+
if (success && node) {
|
|
42
|
+
const handlers = node.handlers?.[method] ?? [];
|
|
43
|
+
return { method, params, handlers, middlewares };
|
|
44
|
+
}
|
|
45
|
+
return { method, params: {}, handlers: [], middlewares };
|
|
46
|
+
}
|
|
47
|
+
_match(method, node, segments, index, params, middlewares) {
|
|
48
|
+
if (node?.handlers?.ALL) {
|
|
49
|
+
const mw = node.handlers?.ALL;
|
|
50
|
+
for (let i = 0; i < mw.length; i++) {
|
|
51
|
+
middlewares.push(mw[i]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (index === segments.length) {
|
|
55
|
+
if (node.isEndpoint && node.handlers?.[method])
|
|
56
|
+
return { success: true, node };
|
|
57
|
+
const opt = node.children[":"];
|
|
58
|
+
if (opt?.isOptional) {
|
|
59
|
+
params[opt.paramName] = null;
|
|
60
|
+
return this._match(method, opt, segments, index, params, middlewares);
|
|
61
|
+
}
|
|
62
|
+
return { success: false, node: node };
|
|
63
|
+
}
|
|
64
|
+
const wc = node.children["*"];
|
|
65
|
+
const seg = segments[index];
|
|
66
|
+
if (node.children[seg]) {
|
|
67
|
+
const res = this._match(method, node.children[seg], segments, index + 1, params, middlewares);
|
|
68
|
+
if (res.success) {
|
|
69
|
+
if (wc?.handlers?.ALL) {
|
|
70
|
+
const mw = wc.handlers?.ALL;
|
|
71
|
+
for (let i = 0; i < mw.length; i++) {
|
|
72
|
+
middlewares.push(mw[i]);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return res;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const dyn = node.children[":"];
|
|
79
|
+
if (dyn) {
|
|
80
|
+
params[dyn.paramName] = seg;
|
|
81
|
+
const res = this._match(method, dyn, segments, index + 1, params, middlewares);
|
|
82
|
+
if (res.success) {
|
|
83
|
+
if (wc?.handlers?.ALL) {
|
|
84
|
+
const mw = wc.handlers?.ALL;
|
|
85
|
+
for (let i = 0; i < mw.length; i++) {
|
|
86
|
+
middlewares.push(mw[i]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return res;
|
|
90
|
+
}
|
|
91
|
+
if (dyn.isOptional) {
|
|
92
|
+
params[dyn.paramName] = null;
|
|
93
|
+
const skip = this._match(method, dyn, segments, index, params, middlewares);
|
|
94
|
+
if (skip.success) {
|
|
95
|
+
if (wc?.handlers?.ALL) {
|
|
96
|
+
const mw = wc.handlers?.ALL;
|
|
97
|
+
for (let i = 0; i < mw.length; i++) {
|
|
98
|
+
middlewares.push(mw[i]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return skip;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (wc) {
|
|
106
|
+
let wildcard = segments.slice(index).join("/");
|
|
107
|
+
if (wc?.handlers?.ALL) {
|
|
108
|
+
const mw = wc.handlers?.ALL;
|
|
109
|
+
for (let i = 0; i < mw.length; i++) {
|
|
110
|
+
middlewares.push(mw[i]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (wildcard) {
|
|
114
|
+
params[wc.paramName] = wildcard;
|
|
115
|
+
return { node: wc, success: true };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { success: false, node };
|
|
119
|
+
}
|
|
120
|
+
parsePattern(pattern) {
|
|
121
|
+
const segments = sanitizePathSplit(pattern);
|
|
122
|
+
const result = [];
|
|
123
|
+
for (const segment of segments) {
|
|
124
|
+
if (segment === "*") {
|
|
125
|
+
result.push({ type: "wildcard", paramName: "*" });
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
else if (segment.startsWith("*")) {
|
|
129
|
+
const paramName = segment.slice(1) || "*";
|
|
130
|
+
result.push({ type: "wildcard", paramName });
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
else if (segment.startsWith(":")) {
|
|
134
|
+
const isOptional = segment.endsWith("?");
|
|
135
|
+
const paramName = isOptional ? segment.slice(1, -1) : segment.slice(1);
|
|
136
|
+
result.push({ type: "dynamic", paramName, isOptional });
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
result.push({ type: "static", value: segment });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./RadixRouter.js";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type RequestHeader = "A-IM" | "Accept" | "Accept-Additions" | "Accept-CH" | "Accept-Charset" | "Accept-Datetime" | "Accept-Encoding" | "Accept-Features" | "Accept-Language" | "Accept-Patch" | "Accept-Post" | "Accept-Ranges" | "Accept-Signature" | "Access-Control" | "Access-Control-Allow-Credentials" | "Access-Control-Allow-Headers" | "Access-Control-Allow-Methods" | "Access-Control-Allow-Origin" | "Access-Control-Expose-Headers" | "Access-Control-Max-Age" | "Access-Control-Request-Headers" | "Access-Control-Request-Method" | "Age" | "Allow" | "ALPN" | "Alt-Svc" | "Alt-Used" | "Alternates" | "AMP-Cache-Transform" | "Apply-To-Redirect-Ref" | "Authentication-Control" | "Authentication-Info" | "Authorization" | "Available-Dictionary" | "C-Ext" | "C-Man" | "C-Opt" | "C-PEP" | "C-PEP-Info" | "Cache-Control" | "Cache-Status" | "Cal-Managed-ID" | "CalDAV-Timezones" | "Capsule-Protocol" | "CDN-Cache-Control" | "CDN-Loop" | "Cert-Not-After" | "Cert-Not-Before" | "Clear-Site-Data" | "Client-Cert" | "Client-Cert-Chain" | "Close" | "CMCD-Object" | "CMCD-Request" | "CMCD-Session" | "CMCD-Status" | "CMSD-Dynamic" | "CMSD-Static" | "Concealed-Auth-Export" | "Configuration-Context" | "Connection" | "Content-Base" | "Content-Digest" | "Content-Disposition" | "Content-Encoding" | "Content-ID" | "Content-Language" | "Content-Length" | "Content-Location" | "Content-MD5" | "Content-Range" | "Content-Script-Type" | "Content-Security-Policy" | "Content-Security-Policy-Report-Only" | "Content-Style-Type" | "Content-Type" | "Content-Version" | "Cookie" | "Cookie2" | "Cross-Origin-Embedder-Policy" | "Cross-Origin-Embedder-Policy-Report-Only" | "Cross-Origin-Opener-Policy" | "Cross-Origin-Opener-Policy-Report-Only" | "Cross-Origin-Resource-Policy" | "CTA-Common-Access-Token" | "DASL" | "Date" | "DAV" | "Default-Style" | "Delta-Base" | "Deprecation" | "Depth" | "Derived-From" | "Destination" | "Differential-ID" | "Dictionary-ID" | "Digest" | "DPoP" | "DPoP-Nonce" | "Early-Data" | "EDIINT-Features" | "ETag" | "Expect" | "Expect-CT" | "Expires" | "Ext" | "Forwarded" | "From" | "GetProfile" | "Hobareg" | "Host" | "HTTP2-Settings" | "If" | "If-Match" | "If-Modified-Since" | "If-None-Match" | "If-Range" | "If-Schedule-Tag-Match" | "If-Unmodified-Since" | "IM" | "Include-Referred-Token-Binding-ID" | "Isolation" | "Keep-Alive" | "Label" | "Last-Event-ID" | "Last-Modified" | "Link" | "Link-Template" | "Location" | "Lock-Token" | "Man" | "Max-Forwards" | "Memento-Datetime" | "Meter" | "Method-Check" | "Method-Check-Expires" | "MIME-Version" | "Negotiate" | "NEL" | "OData-EntityId" | "OData-Isolation" | "OData-MaxVersion" | "OData-Version" | "Opt" | "Optional-WWW-Authenticate" | "Ordering-Type" | "Origin" | "Origin-Agent-Cluster" | "OSCORE" | "OSLC-Core-Version" | "Overwrite" | "P3P" | "PEP" | "PEP-Info" | "Permissions-Policy" | "PICS-Label" | "Ping-From" | "Ping-To" | "Position" | "Pragma" | "Prefer" | "Preference-Applied" | "Priority" | "ProfileObject" | "Protocol" | "Protocol-Info" | "Protocol-Query" | "Protocol-Request" | "Proxy-Authenticate" | "Proxy-Authentication-Info" | "Proxy-Authorization" | "Proxy-Features" | "Proxy-Instruction" | "Proxy-Status" | "Public" | "Public-Key-Pins" | "Public-Key-Pins-Report-Only" | "Range" | "Redirect-Ref" | "Referer" | "Referer-Root" | "Referrer-Policy" | "Refresh" | "Repeatability-Client-ID" | "Repeatability-First-Sent" | "Repeatability-Request-ID" | "Repeatability-Result" | "Replay-Nonce" | "Reporting-Endpoints" | "Repr-Digest" | "Retry-After" | "Safe" | "Schedule-Reply" | "Schedule-Tag" | "Sec-GPC" | "Sec-Purpose" | "Sec-Token-Binding" | "Sec-WebSocket-Accept" | "Sec-WebSocket-Extensions" | "Sec-WebSocket-Key" | "Sec-WebSocket-Protocol" | "Sec-WebSocket-Version" | "Security-Scheme" | "Server" | "Server-Timing" | "Set-Cookie" | "Set-Cookie2" | "SetProfile" | "Signature" | "Signature-Input" | "SLUG" | "SoapAction" | "Status-URI" | "Strict-Transport-Security" | "Sunset" | "Surrogate-Capability" | "Surrogate-Control" | "TCN" | "TE" | "Timeout" | "Timing-Allow-Origin" | "Topic" | "Traceparent" | "Tracestate" | "Trailer" | "Transfer-Encoding" | "TTL" | "Upgrade" | "Urgency" | "URI" | "Use-As-Dictionary" | "User-Agent" | "Variant-Vary" | "Vary" | "Via" | "Want-Content-Digest" | "Want-Digest" | "Want-Repr-Digest" | "Warning" | "WWW-Authenticate" | "X-Content-Type-Options" | "X-Frame-Options";
|
|
2
|
+
export type ResponseHeader = "Access-Control-Allow-Credentials" | "Access-Control-Allow-Headers" | "Access-Control-Allow-Methods" | "Access-Control-Allow-Origin" | "Access-Control-Expose-Headers" | "Access-Control-Max-Age" | "Age" | "Allow" | "Cache-Control" | "Clear-Site-Data" | "Content-Disposition" | "Content-Encoding" | "Content-Language" | "Content-Length" | "Content-Location" | "Content-Range" | "Content-Security-Policy" | "Content-Security-Policy-Report-Only" | "Content-Type" | "Cookie" | "Cross-Origin-Embedder-Policy" | "Cross-Origin-Opener-Policy" | "Cross-Origin-Resource-Policy" | "Date" | "ETag" | "Expires" | "Last-Modified" | "Location" | "Permissions-Policy" | "Pragma" | "Retry-After" | "Save-Data" | "Sec-CH-Prefers-Color-Scheme" | "Sec-CH-Prefers-Reduced-Motion" | "Sec-CH-UA" | "Sec-CH-UA-Arch" | "Sec-CH-UA-Bitness" | "Sec-CH-UA-Form-Factor" | "Sec-CH-UA-Full-Version" | "Sec-CH-UA-Full-Version-List" | "Sec-CH-UA-Mobile" | "Sec-CH-UA-Model" | "Sec-CH-UA-Platform" | "Sec-CH-UA-Platform-Version" | "Sec-CH-UA-WoW64" | "Sec-Fetch-Dest" | "Sec-Fetch-Mode" | "Sec-Fetch-Site" | "Sec-Fetch-User" | "Sec-GPC" | "Server" | "Server-Timing" | "Service-Worker-Navigation-Preload" | "Set-Cookie" | "Strict-Transport-Security" | "Timing-Allow-Origin" | "Trailer" | "Transfer-Encoding" | "Upgrade" | "Vary" | "WWW-Authenticate" | "Warning" | "X-Content-Type-Options" | "X-DNS-Prefetch-Control" | "X-Frame-Options" | "X-Permitted-Cross-Domain-Policies" | "X-Powered-By" | "X-Robots-Tag" | "X-XSS-Protection";
|
package/types/headers.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|