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
package/core/router.js
CHANGED
|
@@ -1,28 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { GlobalConfig } from "./config.js";
|
|
5
|
-
import MiddlewareConfigure, { TriMiddleware, } from "./MiddlewareConfigure.js";
|
|
6
|
-
export class TrieRouter {
|
|
7
|
-
children = new Map();
|
|
8
|
-
handlers = new Map();
|
|
9
|
-
pathname;
|
|
10
|
-
paramName;
|
|
11
|
-
isParam = false;
|
|
12
|
-
constructor(pathname = "/") {
|
|
13
|
-
this.children = new Map();
|
|
14
|
-
this.pathname = pathname;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export class Router extends MiddlewareConfigure {
|
|
18
|
-
routers = new Map();
|
|
1
|
+
import { sanitizePathSplitBasePath } from "../utils/low-level.js";
|
|
2
|
+
import { TezXError } from "./error.js";
|
|
3
|
+
export class Router {
|
|
19
4
|
env = {};
|
|
20
|
-
|
|
5
|
+
router;
|
|
6
|
+
route = [];
|
|
7
|
+
staticFile = Object.create(null);
|
|
8
|
+
basePath;
|
|
21
9
|
constructor({ basePath = "/", env = {} } = {}) {
|
|
22
|
-
super(basePath);
|
|
23
10
|
this.basePath = basePath;
|
|
24
11
|
this.env = { ...env };
|
|
25
|
-
this.triRouter = new TrieRouter(basePath);
|
|
26
12
|
this.get = this.get.bind(this);
|
|
27
13
|
this.post = this.post.bind(this);
|
|
28
14
|
this.put = this.put.bind(this);
|
|
@@ -31,57 +17,30 @@ export class Router extends MiddlewareConfigure {
|
|
|
31
17
|
this.addRouter = this.addRouter.bind(this);
|
|
32
18
|
this.group = this.group.bind(this);
|
|
33
19
|
}
|
|
34
|
-
static(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
[dir] = args;
|
|
52
|
-
break;
|
|
53
|
-
default:
|
|
54
|
-
throw new Error(`\x1b[1;31m404 Not Found\x1b[0m \x1b[1;32mInvalid arguments\x1b[0m`);
|
|
20
|
+
static(serveStatic) {
|
|
21
|
+
if (Array.isArray(serveStatic?.files)) {
|
|
22
|
+
serveStatic?.files.forEach((r) => {
|
|
23
|
+
this.staticFile[`GET ${r?.route}`] = (ctx) => {
|
|
24
|
+
if (serveStatic?.options?.cacheControl) {
|
|
25
|
+
ctx.setHeader("Cache-Control", serveStatic?.options.cacheControl);
|
|
26
|
+
}
|
|
27
|
+
let headers = serveStatic?.options?.headers;
|
|
28
|
+
if (headers) {
|
|
29
|
+
for (const key in headers) {
|
|
30
|
+
let value = headers?.[key];
|
|
31
|
+
ctx.headers.set(key, value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return ctx.sendFile(r.fileSource);
|
|
35
|
+
};
|
|
36
|
+
});
|
|
55
37
|
}
|
|
56
|
-
getFiles(dir, route, this, options);
|
|
57
38
|
return this;
|
|
58
39
|
}
|
|
59
40
|
get(path, ...args) {
|
|
60
41
|
this.#registerRoute("GET", path, ...args);
|
|
61
42
|
return this;
|
|
62
43
|
}
|
|
63
|
-
sse(path, handler) {
|
|
64
|
-
this.get(path, async (ctx) => {
|
|
65
|
-
let res = await handler(ctx);
|
|
66
|
-
const headersMap = {};
|
|
67
|
-
if (res instanceof Response) {
|
|
68
|
-
for (const [key, value] of res.headers.entries()) {
|
|
69
|
-
headersMap[key.toLowerCase()] = value;
|
|
70
|
-
}
|
|
71
|
-
res = res.body;
|
|
72
|
-
}
|
|
73
|
-
const headers = {
|
|
74
|
-
...headersMap,
|
|
75
|
-
"content-type": "text/event-stream",
|
|
76
|
-
"cache-control": "no-cache",
|
|
77
|
-
connection: "keep-alive",
|
|
78
|
-
};
|
|
79
|
-
return new Response(res, {
|
|
80
|
-
status: 200,
|
|
81
|
-
headers,
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
44
|
post(path, ...args) {
|
|
86
45
|
this.#registerRoute("POST", path, ...args);
|
|
87
46
|
return this;
|
|
@@ -102,27 +61,26 @@ export class Router extends MiddlewareConfigure {
|
|
|
102
61
|
this.#registerRoute("OPTIONS", path, ...args);
|
|
103
62
|
return this;
|
|
104
63
|
}
|
|
105
|
-
head(path, ...args) {
|
|
106
|
-
this.#registerRoute("HEAD", path, ...args);
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
109
64
|
all(path, ...args) {
|
|
110
65
|
this.#registerRoute("ALL", path, ...args);
|
|
111
66
|
return this;
|
|
112
67
|
}
|
|
113
|
-
|
|
114
|
-
|
|
68
|
+
when(methods, path, ...args) {
|
|
69
|
+
const methodList = Array.isArray(methods) ? methods : [methods];
|
|
70
|
+
for (const method of methodList) {
|
|
71
|
+
this.#registerRoute(method.toUpperCase(), path, ...args);
|
|
72
|
+
}
|
|
115
73
|
return this;
|
|
116
74
|
}
|
|
117
75
|
addRouter(path, router) {
|
|
118
|
-
return this.#
|
|
76
|
+
return this.#addRouterInstance(path, router);
|
|
119
77
|
}
|
|
120
78
|
group(prefix, callback) {
|
|
121
79
|
const router = new Router({
|
|
122
80
|
basePath: prefix,
|
|
123
81
|
});
|
|
124
82
|
callback(router);
|
|
125
|
-
this.#
|
|
83
|
+
this.#addRouterInstance("/", router);
|
|
126
84
|
return this;
|
|
127
85
|
}
|
|
128
86
|
use(...args) {
|
|
@@ -159,15 +117,26 @@ export class Router extends MiddlewareConfigure {
|
|
|
159
117
|
else if (args[0] instanceof Router) {
|
|
160
118
|
router = args[0];
|
|
161
119
|
}
|
|
162
|
-
|
|
120
|
+
if (middlewares?.length) {
|
|
121
|
+
this.#addRoute("ALL", path, middlewares);
|
|
122
|
+
}
|
|
163
123
|
if (router && router instanceof Router) {
|
|
164
124
|
this.addRouter(path, router);
|
|
165
125
|
}
|
|
166
126
|
return this;
|
|
167
127
|
}
|
|
128
|
+
#addRoute(method, path, handlers) {
|
|
129
|
+
let pattern = `/${sanitizePathSplitBasePath(this.basePath, path).join("/")}`;
|
|
130
|
+
this.router?.addRoute(method, pattern, handlers);
|
|
131
|
+
this.route.push({
|
|
132
|
+
method: method,
|
|
133
|
+
pattern: pattern,
|
|
134
|
+
handlers: handlers,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
168
137
|
#registerRoute(method, path, ...args) {
|
|
169
138
|
if (args.length === 0) {
|
|
170
|
-
throw new
|
|
139
|
+
throw new TezXError("At least one handler is required.");
|
|
171
140
|
}
|
|
172
141
|
let middlewares = [];
|
|
173
142
|
let callback;
|
|
@@ -184,289 +153,21 @@ export class Router extends MiddlewareConfigure {
|
|
|
184
153
|
callback = args[0];
|
|
185
154
|
}
|
|
186
155
|
if (typeof callback !== "function") {
|
|
187
|
-
throw new
|
|
156
|
+
throw new TezXError("Route callback function is missing or invalid.");
|
|
188
157
|
}
|
|
189
158
|
if (!middlewares.every((middleware) => typeof middleware === "function")) {
|
|
190
|
-
throw new
|
|
191
|
-
}
|
|
192
|
-
this.#addRoute(method, path, callback, middlewares);
|
|
193
|
-
}
|
|
194
|
-
#addRoute(method, path, callback, middlewares) {
|
|
195
|
-
let finalMiddleware = middlewares;
|
|
196
|
-
if (!GlobalConfig.allowDuplicateMw) {
|
|
197
|
-
finalMiddleware = new Set(middlewares);
|
|
198
|
-
}
|
|
199
|
-
if (path instanceof RegExp) {
|
|
200
|
-
let regex = addBaseToRegex(this.basePath, path);
|
|
201
|
-
let regexPath = `regex://${regex?.source}`;
|
|
202
|
-
let handler = this.routers.get(regexPath);
|
|
203
|
-
if (!handler) {
|
|
204
|
-
handler = new Map();
|
|
205
|
-
handler.set(method, {
|
|
206
|
-
callback: callback,
|
|
207
|
-
paramNames: [],
|
|
208
|
-
regex: regex,
|
|
209
|
-
middlewares: finalMiddleware,
|
|
210
|
-
});
|
|
211
|
-
return this.routers.set(regexPath, handler);
|
|
212
|
-
}
|
|
213
|
-
if (!GlobalConfig.overwriteMethod && handler.has(method))
|
|
214
|
-
return;
|
|
215
|
-
return handler.set(method, {
|
|
216
|
-
callback: callback,
|
|
217
|
-
paramNames: [],
|
|
218
|
-
regex: regex,
|
|
219
|
-
middlewares: finalMiddleware
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
const parts = sanitizePathSplit(this.basePath, path);
|
|
223
|
-
let p = parts.join("/");
|
|
224
|
-
if (wildcardOrOptionalParamRegex.test(`/${p}`)) {
|
|
225
|
-
let strPath = `string://${p}`;
|
|
226
|
-
let { paramNames, regex } = compileRegexRoute(parts);
|
|
227
|
-
let handler = this.routers.get(strPath);
|
|
228
|
-
if (!handler) {
|
|
229
|
-
handler = new Map();
|
|
230
|
-
handler.set(method, {
|
|
231
|
-
callback: callback,
|
|
232
|
-
regex: regex,
|
|
233
|
-
paramNames: paramNames,
|
|
234
|
-
middlewares: finalMiddleware,
|
|
235
|
-
});
|
|
236
|
-
return this.routers.set(strPath, handler);
|
|
237
|
-
}
|
|
238
|
-
if (!GlobalConfig.overwriteMethod && handler.has(method))
|
|
239
|
-
return;
|
|
240
|
-
return handler.set(method, {
|
|
241
|
-
callback: callback,
|
|
242
|
-
regex: regex,
|
|
243
|
-
paramNames: paramNames,
|
|
244
|
-
middlewares: finalMiddleware
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
let node = this.triRouter;
|
|
248
|
-
for (const part of parts) {
|
|
249
|
-
if (part.startsWith(":")) {
|
|
250
|
-
if (!node.children.has(":")) {
|
|
251
|
-
node.children.set(":", new TrieRouter());
|
|
252
|
-
}
|
|
253
|
-
node = node.children.get(":");
|
|
254
|
-
node.isParam = true;
|
|
255
|
-
if (!node.paramName) {
|
|
256
|
-
node.paramName = part.slice(1);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
if (!node.children.has(part)) {
|
|
261
|
-
node.children.set(part, new TrieRouter());
|
|
262
|
-
}
|
|
263
|
-
node = node.children.get(part);
|
|
264
|
-
}
|
|
159
|
+
throw new TezXError("Middleware must be a function or an array of functions.");
|
|
265
160
|
}
|
|
266
|
-
|
|
267
|
-
return;
|
|
268
|
-
node.handlers.set(method, {
|
|
269
|
-
callback: callback,
|
|
270
|
-
middlewares: finalMiddleware,
|
|
271
|
-
});
|
|
272
|
-
node.pathname = `/${p}`;
|
|
273
|
-
}
|
|
274
|
-
#addRouteMiddleware(path, middlewareFunctions) {
|
|
275
|
-
this.addMiddleware(path, middlewareFunctions);
|
|
161
|
+
this.#addRoute(method, path, [...middlewares, callback]);
|
|
276
162
|
}
|
|
277
|
-
#
|
|
163
|
+
#addRouterInstance(path, router) {
|
|
278
164
|
this.env = { ...this.env, ...router.env };
|
|
279
165
|
if (!(router instanceof Router)) {
|
|
280
|
-
throw new
|
|
281
|
-
}
|
|
282
|
-
const parts = sanitizePathSplit(this.basePath, path);
|
|
283
|
-
if (router.routers.size) {
|
|
284
|
-
for (const [segment, handlers] of router.routers) {
|
|
285
|
-
if (segment.indexOf("string://") == 0) {
|
|
286
|
-
let pattern = segment.replace(/^string:\/\//, "");
|
|
287
|
-
let joined = [...parts, pattern].join("/");
|
|
288
|
-
let strPath = `string://${joined}`;
|
|
289
|
-
if (this.routers.has(strPath)) {
|
|
290
|
-
const baseRouter = this.routers.get(strPath);
|
|
291
|
-
for (const [method, handler] of handlers) {
|
|
292
|
-
let { regex, paramNames } = baseRouter?.get(method);
|
|
293
|
-
handler.regex = regex;
|
|
294
|
-
handler.paramNames = paramNames;
|
|
295
|
-
if (!GlobalConfig.overwriteMethod && baseRouter.has(method))
|
|
296
|
-
continue;
|
|
297
|
-
baseRouter.set(method, handler);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
let h = new Map();
|
|
302
|
-
for (const [method, { callback, middlewares }] of handlers) {
|
|
303
|
-
let { paramNames, regex } = compileRegexRoute(joined);
|
|
304
|
-
h.set(method, {
|
|
305
|
-
callback: callback,
|
|
306
|
-
middlewares: middlewares,
|
|
307
|
-
paramNames,
|
|
308
|
-
regex
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
this.routers.set(strPath, h);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
let pattern = segment.replace("regex://", "");
|
|
316
|
-
let base = parts?.join("/");
|
|
317
|
-
let regex = addBaseToRegex(base, new RegExp(pattern));
|
|
318
|
-
let regexPath = `regex://${regex.source}`;
|
|
319
|
-
if (this.routers.has(regexPath)) {
|
|
320
|
-
const baseRouter = this.routers.get(regexPath);
|
|
321
|
-
for (const [method, handler] of handlers) {
|
|
322
|
-
handler.regex = regex;
|
|
323
|
-
handler.paramNames = [];
|
|
324
|
-
if (!GlobalConfig.overwriteMethod && baseRouter.has(method))
|
|
325
|
-
continue;
|
|
326
|
-
baseRouter.set(method, handler);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
let h = new Map();
|
|
331
|
-
for (const [method, { callback, middlewares }] of handlers) {
|
|
332
|
-
h.set(method, {
|
|
333
|
-
callback: callback,
|
|
334
|
-
middlewares: middlewares,
|
|
335
|
-
paramNames: [],
|
|
336
|
-
regex
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
this.routers.set(regexPath, h);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
let rootNode = this.triRouter;
|
|
345
|
-
let rootMiddlewares = this.triMiddlewares;
|
|
346
|
-
if (parts.length == 0) {
|
|
347
|
-
this.#addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router);
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
for (const part of parts) {
|
|
351
|
-
if (part.startsWith(":")) {
|
|
352
|
-
if (!rootNode.children.has(":")) {
|
|
353
|
-
rootNode.children.set(":", new TrieRouter());
|
|
354
|
-
}
|
|
355
|
-
rootNode = rootNode.children.get(":");
|
|
356
|
-
rootNode.isParam = true;
|
|
357
|
-
if (!rootNode.paramName) {
|
|
358
|
-
rootNode.paramName = part.slice(1);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
if (!rootNode.children.has(part)) {
|
|
363
|
-
rootNode.children.set(part, new TrieRouter());
|
|
364
|
-
}
|
|
365
|
-
rootNode = rootNode.children.get(part);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
for (const part of parts) {
|
|
369
|
-
if (part.startsWith("*")) {
|
|
370
|
-
if (!rootMiddlewares.children.has("*")) {
|
|
371
|
-
rootMiddlewares.children.set("*", new TriMiddleware());
|
|
372
|
-
}
|
|
373
|
-
rootMiddlewares = rootMiddlewares.children.get("*");
|
|
374
|
-
}
|
|
375
|
-
else if (part.startsWith(":")) {
|
|
376
|
-
const isOptional = part?.endsWith("?");
|
|
377
|
-
if (isOptional) {
|
|
378
|
-
rootMiddlewares.isOptional = isOptional;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
if (!rootMiddlewares.children.has(":")) {
|
|
382
|
-
rootMiddlewares.children.set(":", new TriMiddleware());
|
|
383
|
-
}
|
|
384
|
-
rootMiddlewares = rootMiddlewares.children.get(":");
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
if (!rootMiddlewares.children.has(part)) {
|
|
388
|
-
rootMiddlewares.children.set(part, new TriMiddleware());
|
|
389
|
-
}
|
|
390
|
-
rootMiddlewares = rootMiddlewares.children.get(part);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
this.#addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
#addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router) {
|
|
397
|
-
function addSubRouter(children, node) {
|
|
398
|
-
let rtN = node;
|
|
399
|
-
for (const element of children) {
|
|
400
|
-
const pathSegment = element[0];
|
|
401
|
-
const subRouter = element[1];
|
|
402
|
-
if (rtN.children.has(pathSegment)) {
|
|
403
|
-
let findNode = rtN.children.get(pathSegment);
|
|
404
|
-
for (const [method, handlers] of subRouter.handlers) {
|
|
405
|
-
if (!GlobalConfig.overwriteMethod && node.handlers.has(method))
|
|
406
|
-
return;
|
|
407
|
-
findNode.handlers.set(method, handlers);
|
|
408
|
-
}
|
|
409
|
-
if (subRouter.children.size) {
|
|
410
|
-
addSubRouter(subRouter.children, findNode);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
rtN.children.set(pathSegment, subRouter);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
let routerNode = router.triRouter;
|
|
419
|
-
const routerMiddlewares = router.triMiddlewares;
|
|
420
|
-
for (const [method, handlers] of routerNode.handlers) {
|
|
421
|
-
if (!GlobalConfig.overwriteMethod) {
|
|
422
|
-
rootNode.handlers.set(method, handlers);
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
if (!rootNode.handlers.has(method)) {
|
|
426
|
-
rootNode.handlers.set(method, handlers);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
if (routerNode.children.size > 0) {
|
|
430
|
-
addSubRouter(routerNode.children, rootNode);
|
|
431
|
-
}
|
|
432
|
-
function addMiddleware(children, node) {
|
|
433
|
-
let n = node;
|
|
434
|
-
for (const [path, middlewareNode] of children) {
|
|
435
|
-
if (n.children.has(path)) {
|
|
436
|
-
let findNode = n.children.get(path);
|
|
437
|
-
if (GlobalConfig.allowDuplicateMw) {
|
|
438
|
-
findNode.middlewares.push(...middlewareNode.middlewares);
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
for (const mw of middlewareNode.middlewares) {
|
|
442
|
-
if (findNode.middlewares.has(mw)) {
|
|
443
|
-
middlewareNode.middlewares.delete(mw);
|
|
444
|
-
}
|
|
445
|
-
findNode.middlewares.add(mw);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
if (middlewareNode.children.size) {
|
|
449
|
-
addMiddleware(middlewareNode.children, findNode);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
n.children.set(path, middlewareNode);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
if (GlobalConfig.allowDuplicateMw) {
|
|
458
|
-
rootMiddlewares.middlewares.push(...routerMiddlewares.middlewares);
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
for (const mw of routerMiddlewares.middlewares) {
|
|
462
|
-
if (rootMiddlewares.middlewares.has(mw)) {
|
|
463
|
-
routerMiddlewares.middlewares.delete(mw);
|
|
464
|
-
}
|
|
465
|
-
rootMiddlewares.middlewares.add(mw);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
if (routerMiddlewares.children.size > 0) {
|
|
469
|
-
addMiddleware(routerMiddlewares.children, rootMiddlewares);
|
|
166
|
+
throw new TezXError("Router instance is required.");
|
|
470
167
|
}
|
|
168
|
+
router.route.forEach((r) => {
|
|
169
|
+
this.#addRoute(r?.method, `/${sanitizePathSplitBasePath(path, r?.pattern).join("/")}`, r?.handlers);
|
|
170
|
+
});
|
|
171
|
+
Object.assign(this.staticFile, router.staticFile);
|
|
471
172
|
}
|
|
472
173
|
}
|
package/core/server.d.ts
CHANGED
|
@@ -1,33 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Context } from "./context.js";
|
|
1
|
+
import { Callback, ErrorHandler, RouteRegistry } from "../types/index.js";
|
|
3
2
|
import { Router, RouterConfig } from "./router.js";
|
|
4
|
-
export type TezXServeOptions = {
|
|
5
|
-
connInfo: ConnAddress;
|
|
6
|
-
};
|
|
7
3
|
export type TezXConfig = {
|
|
8
|
-
/**
|
|
9
|
-
* `allowDuplicateMw` determines whether duplicate middleware functions
|
|
10
|
-
* are allowed in the router.
|
|
11
|
-
*
|
|
12
|
-
* - When `true`: The same middleware can be added multiple times.
|
|
13
|
-
* - When `false`: Ensures each middleware is registered only once
|
|
14
|
-
* per route or application context.
|
|
15
|
-
*
|
|
16
|
-
* @default false
|
|
17
|
-
*/
|
|
18
|
-
allowDuplicateMw?: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* `overwriteMethod` controls whether existing route handlers
|
|
21
|
-
* should be overwritten when a new handler for the same
|
|
22
|
-
* HTTP method and path is added.
|
|
23
|
-
*
|
|
24
|
-
* - When `true`: The new handler replaces the existing one.
|
|
25
|
-
* - When `false`: Prevents overwriting, ensuring that the
|
|
26
|
-
* first registered handler remains active.
|
|
27
|
-
*
|
|
28
|
-
* @default true
|
|
29
|
-
*/
|
|
30
|
-
overwriteMethod?: boolean;
|
|
31
4
|
/**
|
|
32
5
|
* 🔄 Hook to transform or normalize the incoming request pathname before routing.
|
|
33
6
|
*
|
|
@@ -47,6 +20,11 @@ export type TezXConfig = {
|
|
|
47
20
|
* @returns The transformed or resolved path used for routing (e.g., `/api/users`)
|
|
48
21
|
*/
|
|
49
22
|
onPathResolve?: (pathname: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Custom route registry instance used internally to store routes.
|
|
25
|
+
* If not provided, the router will use the default CombineRouteRegistry.
|
|
26
|
+
*/
|
|
27
|
+
routeRegistry?: RouteRegistry;
|
|
50
28
|
/**
|
|
51
29
|
* Enables or disables debugging for the middleware.
|
|
52
30
|
* When set to `true`, detailed debug logs will be output,
|
|
@@ -56,16 +34,99 @@ export type TezXConfig = {
|
|
|
56
34
|
*/
|
|
57
35
|
debugMode?: boolean;
|
|
58
36
|
} & RouterConfig;
|
|
37
|
+
/**
|
|
38
|
+
* TezX is an ultra-fast, flexible request router and server handler.
|
|
39
|
+
* It supports plug-and-play for Bun, and Node runtimes.
|
|
40
|
+
*
|
|
41
|
+
* @template T - The environment object shared across requests.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const app = new TezX();
|
|
46
|
+
*
|
|
47
|
+
* app.get("/hello", (ctx) => ctx.text("Hello TezX"));
|
|
48
|
+
* bunAdapter(app).listen();
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
59
51
|
export declare class TezX<T extends Record<string, any> = {}> extends Router<T> {
|
|
60
52
|
#private;
|
|
61
|
-
|
|
62
|
-
protected
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
/** Internal route registry to hold all routes */
|
|
54
|
+
protected router?: RouteRegistry;
|
|
55
|
+
constructor({ basePath, env, debugMode, onPathResolve, routeRegistry, }?: TezXConfig);
|
|
56
|
+
/**
|
|
57
|
+
* Register a custom 404 (not found) handler.
|
|
58
|
+
*
|
|
59
|
+
* @param callback - Function to handle unmatched routes.
|
|
60
|
+
* @returns The current TezX instance (for chaining).
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* app.notFound((ctx) => ctx.status(404).text("Oops! Page not found."));
|
|
64
|
+
*/
|
|
65
|
+
notFound(callback: Callback<T>): this;
|
|
66
|
+
/**
|
|
67
|
+
* Register a global error handler for uncaught route errors.
|
|
68
|
+
*
|
|
69
|
+
* @param callback - Function to handle thrown exceptions or failed routes.
|
|
70
|
+
* @returns The current TezX instance (for chaining).
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* app.onError((err, ctx) => {
|
|
74
|
+
* return ctx.status(500).text("Server crashed!");
|
|
75
|
+
* });
|
|
76
|
+
*/
|
|
77
|
+
onError(callback: ErrorHandler<T>): this;
|
|
78
|
+
/**
|
|
79
|
+
* Main request handler compatible with multiple runtimes (Node.js, Deno, Bun).
|
|
80
|
+
*
|
|
81
|
+
* This function can be passed directly to native HTTP servers to handle incoming requests.
|
|
82
|
+
*
|
|
83
|
+
* ### Usage examples:
|
|
84
|
+
*
|
|
85
|
+
* #### Bun
|
|
86
|
+
* ```ts
|
|
87
|
+
* // Simple usage with Bun's built-in HTTP server
|
|
88
|
+
* app.serve(request, server);
|
|
89
|
+
*
|
|
90
|
+
* // Or with WebSocket support (required for ws handling)
|
|
91
|
+
* Bun.serve({
|
|
92
|
+
* port: 3001,
|
|
93
|
+
* reusePort: true, // enables SO_REUSEPORT for clustering
|
|
94
|
+
* fetch: app.serve,
|
|
95
|
+
* websocket: wsHandlers()
|
|
96
|
+
* });
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* #### Deno
|
|
100
|
+
* ```ts
|
|
101
|
+
* // Using Deno’s serve method with connection info
|
|
102
|
+
* serve((req, connInfo) => app.serve(req, connInfo));
|
|
103
|
+
*
|
|
104
|
+
* // Or using Deno’s built-in Deno.serve with options
|
|
105
|
+
* Deno.serve({ port: 8080 }, app.serve);
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* #### Node.js
|
|
109
|
+
* ```ts
|
|
110
|
+
* import { createServer } from "http";
|
|
111
|
+
* import { mountTezXOnNode } from "tezx/node";
|
|
112
|
+
*
|
|
113
|
+
* // Option 1: Manually convert and forward request/response
|
|
114
|
+
* const response = await app.serve(toWebRequest(req, req.method), req, res, server);
|
|
115
|
+
*
|
|
116
|
+
* // Option 2: Use provided utility to mount TezX app onto native HTTP server
|
|
117
|
+
* const server = createServer();
|
|
118
|
+
* mountTezXOnNode(app, server);
|
|
119
|
+
* server.listen(3000);
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @param {Request} req - Native Fetch API Request object.
|
|
123
|
+
* @param {...any} args - Runtime-specific arguments such as connection info (Deno), server instances, or response objects.
|
|
124
|
+
* @returns {Promise<Response>} The final response to be sent back to the client or the result of WebSocket handlers.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* const response = await app.serve(new Request("http://localhost/hello"));
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
serve(req: Request, ...args: any[]): Promise<Response>;
|
|
71
132
|
}
|