vafast 0.4.23 → 0.4.24
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 +1 -18
- package/dist/index.mjs +3 -3
- package/dist/router/index.mjs +1 -1
- package/dist/{router-xWzwz_1a.mjs → router-CgYfGB4J.mjs} +33 -3
- package/dist/router-CgYfGB4J.mjs.map +1 -0
- package/dist/router.d.mts +0 -24
- package/dist/router.mjs +1 -1
- package/dist/server/index.mjs +2 -2
- package/dist/server/server-factory.mjs +2 -2
- package/dist/server/server.mjs +1 -1
- package/dist/{server-CezB-92R.mjs → server-BUom6ISO.mjs} +2 -2
- package/dist/{server-CezB-92R.mjs.map → server-BUom6ISO.mjs.map} +1 -1
- package/dist/{server-DdIIf4co.mjs → server-OUUug5DR.mjs} +2 -2
- package/dist/{server-DdIIf4co.mjs.map → server-OUUug5DR.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/router-xWzwz_1a.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -324,7 +324,7 @@ export default { fetch: server.fetch };" > index.ts && bun index.ts
|
|
|
324
324
|
## 🎯 核心功能
|
|
325
325
|
|
|
326
326
|
- ⚡ **JIT 编译验证器** - Schema 验证器编译缓存,避免重复编译
|
|
327
|
-
-
|
|
327
|
+
- 🌲 **Radix Tree 路由** - O(k) 时间复杂度的高效路由匹配
|
|
328
328
|
- 🎯 **快速请求解析** - 优化的 Query/Cookie 解析,比标准方法快 2x
|
|
329
329
|
- 🔒 **端到端类型安全** - 完整的 TypeScript 类型推断
|
|
330
330
|
- 🧩 **灵活中间件系统** - 可组合的中间件架构
|
|
@@ -521,23 +521,6 @@ registerFormat('order-id', (v) => /^ORD-\d{8}$/.test(v));
|
|
|
521
521
|
const isEmail = Patterns.EMAIL.test('test@example.com');
|
|
522
522
|
```
|
|
523
523
|
|
|
524
|
-
### 中间件预编译
|
|
525
|
-
|
|
526
|
-
Vafast 自动在路由注册时预编译中间件链,消除运行时组合开销:
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
529
|
-
const server = new Server(routes);
|
|
530
|
-
|
|
531
|
-
// 添加全局中间件后,手动触发预编译
|
|
532
|
-
server.use(authMiddleware);
|
|
533
|
-
server.use(logMiddleware);
|
|
534
|
-
server.compile(); // 预编译所有路由的处理链
|
|
535
|
-
|
|
536
|
-
// 预编译后,每次请求直接执行编译好的处理链,无需运行时组合
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
**性能效果:1000 次请求仅需 ~4ms,平均每次 0.004ms**
|
|
540
|
-
|
|
541
524
|
### 路由注册表 (RouteRegistry)
|
|
542
525
|
|
|
543
526
|
Vafast 提供 `RouteRegistry` 用于路由元信息的收集和查询,适用于 API 文档生成、Webhook 事件注册、权限检查等场景:
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { defineRoutes } from "./defineRoute.mjs";
|
|
2
|
-
import { n as normalizePath, t as flattenNestedRoutes } from "./router-
|
|
2
|
+
import { n as normalizePath, t as flattenNestedRoutes } from "./router-CgYfGB4J.mjs";
|
|
3
3
|
import { a as html, c as redirect, i as err, l as stream, n as composeMiddleware, o as json, r as empty, t as VafastError, u as text } from "./middleware-CewKbtb4.mjs";
|
|
4
4
|
import { t as BaseServer } from "./base-server-B7MYJNsl.mjs";
|
|
5
5
|
import { a as getRoute, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, t as RouteRegistry } from "./route-registry-emTmRrWQ.mjs";
|
|
6
|
-
import { t as Server } from "./server-
|
|
6
|
+
import { t as Server } from "./server-OUUug5DR.mjs";
|
|
7
7
|
import { t as HtmlRenderer } from "./html-renderer-DTtJ_Yic.mjs";
|
|
8
8
|
import { t as DependencyManager } from "./dependency-manager-DCmh7xFc.mjs";
|
|
9
9
|
import { t as ComponentServer } from "./component-server-DomPJ_7S.mjs";
|
|
10
|
-
import { t as ServerFactory } from "./server-
|
|
10
|
+
import { t as ServerFactory } from "./server-BUom6ISO.mjs";
|
|
11
11
|
import { a as parseCookies, d as parseQueryFast, l as parseHeaders, n as getHeader, o as parseCookiesFast, r as parseBody, t as getCookie, u as parseQuery } from "./parsers-DpH_mD0H.mjs";
|
|
12
12
|
import { t as goAwait } from "./go-await-C4ZdEUwY.mjs";
|
|
13
13
|
import { a as validateAllSchemas, c as validateSchemaOrThrow, i as precompileSchemas, n as createValidator, o as validateFast, r as getValidatorCacheStats, s as validateSchema } from "./validators-DBkyw6BG.mjs";
|
package/dist/router/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as normalizePath, t as flattenNestedRoutes } from "../router-
|
|
1
|
+
import { n as normalizePath, t as flattenNestedRoutes } from "../router-CgYfGB4J.mjs";
|
|
2
2
|
import { t as RadixRouter } from "../radix-tree-qqSjnVXF.mjs";
|
|
3
3
|
|
|
4
4
|
export { RadixRouter, flattenNestedRoutes, normalizePath };
|
|
@@ -23,21 +23,51 @@
|
|
|
23
23
|
* // ]
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
+
/** 标准路由属性(不继承) */
|
|
27
|
+
const STANDARD_ROUTE_PROPS = new Set([
|
|
28
|
+
"path",
|
|
29
|
+
"method",
|
|
30
|
+
"handler",
|
|
31
|
+
"middleware",
|
|
32
|
+
"children",
|
|
33
|
+
"name",
|
|
34
|
+
"description"
|
|
35
|
+
]);
|
|
36
|
+
/**
|
|
37
|
+
* 提取路由的自定义属性(用于继承)
|
|
38
|
+
* 排除标准属性,保留 log, webhook, auth 等自定义配置
|
|
39
|
+
*/
|
|
40
|
+
function extractCustomProps(route) {
|
|
41
|
+
const custom = {};
|
|
42
|
+
for (const key of Object.keys(route)) if (!STANDARD_ROUTE_PROPS.has(key)) custom[key] = route[key];
|
|
43
|
+
return custom;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 合并自定义属性(子路由覆盖父路由)
|
|
47
|
+
*/
|
|
48
|
+
function mergeCustomProps(parentProps, childProps) {
|
|
49
|
+
return {
|
|
50
|
+
...parentProps,
|
|
51
|
+
...childProps
|
|
52
|
+
};
|
|
53
|
+
}
|
|
26
54
|
function flattenNestedRoutes(routes) {
|
|
27
55
|
const flattened = [];
|
|
28
|
-
function processRoute(route, parentPath = "", parentMiddleware = [], parentName) {
|
|
56
|
+
function processRoute(route, parentPath = "", parentMiddleware = [], parentName, parentCustomProps = {}) {
|
|
29
57
|
const currentPath = normalizePath(parentPath + route.path);
|
|
30
58
|
const currentMiddleware = [...parentMiddleware, ...route.middleware || []];
|
|
31
59
|
const currentName = route.name || parentName;
|
|
60
|
+
const currentCustomProps = mergeCustomProps(parentCustomProps, extractCustomProps(route));
|
|
32
61
|
if ("method" in route && "handler" in route) {
|
|
33
62
|
const leafRoute = route;
|
|
34
63
|
flattened.push({
|
|
64
|
+
...currentCustomProps,
|
|
35
65
|
...leafRoute,
|
|
36
66
|
fullPath: currentPath,
|
|
37
67
|
middlewareChain: currentMiddleware,
|
|
38
68
|
parentName
|
|
39
69
|
});
|
|
40
|
-
} else if ("children" in route && route.children) for (const child of route.children) processRoute(child, currentPath, currentMiddleware, currentName);
|
|
70
|
+
} else if ("children" in route && route.children) for (const child of route.children) processRoute(child, currentPath, currentMiddleware, currentName, currentCustomProps);
|
|
41
71
|
}
|
|
42
72
|
for (const route of routes) processRoute(route);
|
|
43
73
|
return flattened;
|
|
@@ -65,4 +95,4 @@ function normalizePath(path) {
|
|
|
65
95
|
|
|
66
96
|
//#endregion
|
|
67
97
|
export { normalizePath as n, flattenNestedRoutes as t };
|
|
68
|
-
//# sourceMappingURL=router-
|
|
98
|
+
//# sourceMappingURL=router-CgYfGB4J.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-CgYfGB4J.mjs","names":[],"sources":["../src/router.ts"],"sourcesContent":["/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\n/** 标准路由属性(不继承) */\nconst STANDARD_ROUTE_PROPS = new Set([\n 'path', 'method', 'handler', 'middleware', 'children', 'name', 'description',\n]);\n\n/**\n * 提取路由的自定义属性(用于继承)\n * 排除标准属性,保留 log, webhook, auth 等自定义配置\n */\nfunction extractCustomProps(route: Route | NestedRoute): Record<string, unknown> {\n const custom: Record<string, unknown> = {};\n for (const key of Object.keys(route)) {\n if (!STANDARD_ROUTE_PROPS.has(key)) {\n custom[key] = (route as Record<string, unknown>)[key];\n }\n }\n return custom;\n}\n\n/**\n * 合并自定义属性(子路由覆盖父路由)\n */\nfunction mergeCustomProps(\n parentProps: Record<string, unknown>,\n childProps: Record<string, unknown>,\n): Record<string, unknown> {\n return { ...parentProps, ...childProps };\n}\n\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n parentName?: string,\n parentCustomProps: Record<string, unknown> = {},\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n // 当前路由的 name(用于传递给子路由)\n const currentName = route.name || parentName;\n // 合并自定义属性(子路由可覆盖父路由设置)\n const currentCustomProps = mergeCustomProps(parentCustomProps, extractCustomProps(route));\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n const leafRoute = route as Route;\n flattened.push({\n ...currentCustomProps, // 继承的自定义属性放在前面\n ...leafRoute, // 叶子路由自身属性覆盖\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n parentName: parentName,\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware, currentName, currentCustomProps);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,uBAAuB,IAAI,IAAI;CACnC;CAAQ;CAAU;CAAW;CAAc;CAAY;CAAQ;CAChE,CAAC;;;;;AAMF,SAAS,mBAAmB,OAAqD;CAC/E,MAAM,SAAkC,EAAE;AAC1C,MAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,KAAI,CAAC,qBAAqB,IAAI,IAAI,CAChC,QAAO,OAAQ,MAAkC;AAGrD,QAAO;;;;;AAMT,SAAS,iBACP,aACA,YACyB;AACzB,QAAO;EAAE,GAAG;EAAa,GAAG;EAAY;;AAG1C,SAAgB,oBACd,QACkB;CAClB,MAAM,YAA8B,EAAE;CAEtC,SAAS,aACP,OACA,aAAa,IACb,mBAAiC,EAAE,EACnC,YACA,oBAA6C,EAAE,EACzC;EAEN,MAAM,cAAc,cAAc,aAAa,MAAM,KAAK;EAE1D,MAAM,oBAAoB,CACxB,GAAG,kBACH,GAAI,MAAM,cAAc,EAAE,CAC3B;EAED,MAAM,cAAc,MAAM,QAAQ;EAElC,MAAM,qBAAqB,iBAAiB,mBAAmB,mBAAmB,MAAM,CAAC;AAEzF,MAAI,YAAY,SAAS,aAAa,OAAO;GAE3C,MAAM,YAAY;AAClB,aAAU,KAAK;IACb,GAAG;IACH,GAAG;IACH,UAAU;IACV,iBAAiB;IACL;IACb,CAAC;aACO,cAAc,SAAS,MAAM,SAEtC,MAAK,MAAM,SAAS,MAAM,SACxB,cAAa,OAAO,aAAa,mBAAmB,aAAa,mBAAmB;;AAK1F,MAAK,MAAM,SAAS,OAClB,cAAa,MAAM;AAGrB,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,cAAc,MAAsB;CAElD,IAAI,aAAa,mBAAmB,KAAK;AAGzC,cAAa,WAAW,QAAQ,QAAQ,IAAI;AAG5C,KAAI,eAAe,GAAI,QAAO;AAG9B,KAAI,eAAe,OAAO,WAAW,SAAS,IAAI,CAChD,cAAa,WAAW,MAAM,GAAG,GAAG;AAGtC,QAAO"}
|
package/dist/router.d.mts
CHANGED
|
@@ -4,30 +4,6 @@ import "./index-CREkvfw9.mjs";
|
|
|
4
4
|
|
|
5
5
|
//#region src/router.d.ts
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* 扁平化嵌套路由
|
|
9
|
-
*
|
|
10
|
-
* 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* const routes = flattenNestedRoutes([
|
|
15
|
-
* {
|
|
16
|
-
* path: "/api",
|
|
17
|
-
* middleware: [authMiddleware],
|
|
18
|
-
* children: [
|
|
19
|
-
* { path: "/users", method: "GET", handler: getUsers },
|
|
20
|
-
* { path: "/users/:id", method: "GET", handler: getUser },
|
|
21
|
-
* ],
|
|
22
|
-
* },
|
|
23
|
-
* ]);
|
|
24
|
-
* // 结果:
|
|
25
|
-
* // [
|
|
26
|
-
* // { fullPath: "/api/users", method: "GET", ... },
|
|
27
|
-
* // { fullPath: "/api/users/:id", method: "GET", ... },
|
|
28
|
-
* // ]
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
7
|
declare function flattenNestedRoutes(routes: (Route | NestedRoute)[]): FlattenedRoute[];
|
|
32
8
|
/**
|
|
33
9
|
* 标准化路径
|
package/dist/router.mjs
CHANGED
package/dist/server/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "../middleware-CewKbtb4.mjs";
|
|
2
2
|
import { t as BaseServer } from "../base-server-B7MYJNsl.mjs";
|
|
3
|
-
import { t as Server } from "../server-
|
|
3
|
+
import { t as Server } from "../server-OUUug5DR.mjs";
|
|
4
4
|
import "../dependency-manager-DCmh7xFc.mjs";
|
|
5
5
|
import { t as ComponentServer } from "../component-server-DomPJ_7S.mjs";
|
|
6
|
-
import { t as ServerFactory } from "../server-
|
|
6
|
+
import { t as ServerFactory } from "../server-BUom6ISO.mjs";
|
|
7
7
|
|
|
8
8
|
export { BaseServer, ComponentServer, Server, ServerFactory };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../middleware-CewKbtb4.mjs";
|
|
2
|
-
import "../server-
|
|
2
|
+
import "../server-OUUug5DR.mjs";
|
|
3
3
|
import "../dependency-manager-DCmh7xFc.mjs";
|
|
4
4
|
import "../component-server-DomPJ_7S.mjs";
|
|
5
|
-
import { t as ServerFactory } from "../server-
|
|
5
|
+
import { t as ServerFactory } from "../server-BUom6ISO.mjs";
|
|
6
6
|
|
|
7
7
|
export { ServerFactory };
|
package/dist/server/server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Server } from "./server-
|
|
1
|
+
import { t as Server } from "./server-OUUug5DR.mjs";
|
|
2
2
|
import { t as ComponentServer } from "./component-server-DomPJ_7S.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/server/server-factory.ts
|
|
@@ -67,4 +67,4 @@ var ServerFactory = class {
|
|
|
67
67
|
|
|
68
68
|
//#endregion
|
|
69
69
|
export { ServerFactory as t };
|
|
70
|
-
//# sourceMappingURL=server-
|
|
70
|
+
//# sourceMappingURL=server-BUom6ISO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-
|
|
1
|
+
{"version":3,"file":"server-BUom6ISO.mjs","names":[],"sources":["../src/server/server-factory.ts"],"sourcesContent":["import type { Route, NestedRoute } from \"../types\";\nimport type {\n ComponentRoute,\n NestedComponentRoute,\n} from \"../types/component-route\";\nimport { Server } from \"../server\";\nimport { ComponentServer } from \"./component-server\";\n\n/**\n * 服务器工厂类\n * 用于创建和管理不同类型的服务器\n */\nexport class ServerFactory {\n private servers: Map<string, Server | ComponentServer> = new Map();\n\n /**\n * 创建标准REST API服务器\n */\n createRestServer(routes: (Route | NestedRoute)[]): Server {\n const server = new Server(routes);\n this.servers.set(\"rest\", server);\n return server;\n }\n\n /**\n * 创建组件服务器\n */\n createComponentServer(\n routes: (ComponentRoute | NestedComponentRoute)[],\n ): ComponentServer {\n const server = new ComponentServer(routes);\n this.servers.set(\"component\", server);\n return server;\n }\n\n /**\n * 获取指定类型的服务器\n */\n getServer(type: \"rest\" | \"component\"): Server | ComponentServer | undefined {\n return this.servers.get(type);\n }\n\n /**\n * 获取所有服务器\n */\n getAllServers(): Map<string, Server | ComponentServer> {\n return this.servers;\n }\n\n /**\n * 移除指定类型的服务器\n */\n removeServer(type: string): boolean {\n return this.servers.delete(type);\n }\n\n /**\n * 清除所有服务器\n */\n clearServers(): void {\n this.servers.clear();\n }\n\n /**\n * 获取服务器状态信息\n */\n getServerStatus(): Record<string, { type: string; routes: number }> {\n const status: Record<string, { type: string; routes: number }> = {};\n\n for (const [name, server] of this.servers) {\n if (server instanceof Server) {\n status[name] = {\n type: \"REST API\",\n routes: (server as any).routes?.length || 0,\n };\n } else if (server instanceof ComponentServer) {\n status[name] = {\n type: \"Component\",\n routes: (server as any).routes?.length || 0,\n };\n }\n }\n\n return status;\n }\n}\n"],"mappings":";;;;;;;;AAYA,IAAa,gBAAb,MAA2B;CACzB,AAAQ,0BAAiD,IAAI,KAAK;;;;CAKlE,iBAAiB,QAAyC;EACxD,MAAM,SAAS,IAAI,OAAO,OAAO;AACjC,OAAK,QAAQ,IAAI,QAAQ,OAAO;AAChC,SAAO;;;;;CAMT,sBACE,QACiB;EACjB,MAAM,SAAS,IAAI,gBAAgB,OAAO;AAC1C,OAAK,QAAQ,IAAI,aAAa,OAAO;AACrC,SAAO;;;;;CAMT,UAAU,MAAkE;AAC1E,SAAO,KAAK,QAAQ,IAAI,KAAK;;;;;CAM/B,gBAAuD;AACrD,SAAO,KAAK;;;;;CAMd,aAAa,MAAuB;AAClC,SAAO,KAAK,QAAQ,OAAO,KAAK;;;;;CAMlC,eAAqB;AACnB,OAAK,QAAQ,OAAO;;;;;CAMtB,kBAAoE;EAClE,MAAM,SAA2D,EAAE;AAEnE,OAAK,MAAM,CAAC,MAAM,WAAW,KAAK,QAChC,KAAI,kBAAkB,OACpB,QAAO,QAAQ;GACb,MAAM;GACN,QAAS,OAAe,QAAQ,UAAU;GAC3C;WACQ,kBAAkB,gBAC3B,QAAO,QAAQ;GACb,MAAM;GACN,QAAS,OAAe,QAAQ,UAAU;GAC3C;AAIL,SAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as flattenNestedRoutes } from "./router-
|
|
1
|
+
import { t as flattenNestedRoutes } from "./router-CgYfGB4J.mjs";
|
|
2
2
|
import { n as composeMiddleware, o as json } from "./middleware-CewKbtb4.mjs";
|
|
3
3
|
import { t as BaseServer } from "./base-server-B7MYJNsl.mjs";
|
|
4
4
|
import { t as RadixRouter } from "./radix-tree-qqSjnVXF.mjs";
|
|
@@ -117,4 +117,4 @@ var Server = class extends BaseServer {
|
|
|
117
117
|
|
|
118
118
|
//#endregion
|
|
119
119
|
export { Server as t };
|
|
120
|
-
//# sourceMappingURL=server-
|
|
120
|
+
//# sourceMappingURL=server-OUUug5DR.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-
|
|
1
|
+
{"version":3,"file":"server-OUUug5DR.mjs","names":[],"sources":["../src/server/server.ts"],"sourcesContent":["/**\n * Vafast 核心服务器\n *\n * 基于 Radix Tree 的高性能路由匹配\n * 时间复杂度: O(k),k 为路径段数\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Method } from \"../types\";\nimport { flattenNestedRoutes } from \"../router\";\nimport { composeMiddleware } from \"../middleware\";\nimport { json } from \"../utils/response\";\nimport { BaseServer } from \"./base-server\";\nimport { RadixRouter } from \"../router/radix-tree\";\nimport { RouteRegistry, setGlobalRegistry } from \"../utils/route-registry\";\n\n/**\n * Vafast 服务器\n *\n * @example\n * ```typescript\n * const server = new Server([\n * { method: \"GET\", path: \"/\", handler: () => new Response(\"Hello\") },\n * ]);\n * export default { fetch: server.fetch };\n * ```\n */\nexport class Server extends BaseServer {\n private router: RadixRouter;\n private routes: FlattenedRoute[];\n\n constructor(routes: readonly (Route | NestedRoute)[] = []) {\n super();\n this.router = new RadixRouter();\n this.routes = [];\n\n if (routes.length > 0) {\n this.registerRoutes([...routes]);\n }\n }\n\n private registerRoutes(routes: (Route | NestedRoute)[]): void {\n const flattened = flattenNestedRoutes(routes);\n this.routes.push(...flattened);\n\n for (const route of flattened) {\n this.router.register(\n route.method as Method,\n route.fullPath,\n route.handler,\n route.middlewareChain || [],\n );\n }\n\n this.detectRouteConflicts(flattened);\n this.logFlattenedRoutes(flattened);\n\n // 自动设置全局 RouteRegistry(支持在任意位置通过 getRouteRegistry() 访问)\n setGlobalRegistry(new RouteRegistry(this.routes));\n }\n\n /** 快速提取 pathname */\n private extractPathname(url: string): string {\n let start = url.indexOf(\"://\");\n start = start === -1 ? 0 : start + 3;\n\n const pathStart = url.indexOf(\"/\", start);\n if (pathStart === -1) return \"/\";\n\n let end = url.indexOf(\"?\", pathStart);\n if (end === -1) end = url.indexOf(\"#\", pathStart);\n if (end === -1) end = url.length;\n\n return url.substring(pathStart, end) || \"/\";\n }\n\n /** 生成 404/405 响应 */\n private createErrorResponse(method: string, pathname: string): Response {\n const allowedMethods = this.router.getAllowedMethods(pathname);\n if (allowedMethods.length > 0) {\n return json(\n {\n success: false,\n error: \"Method Not Allowed\",\n message: `Method ${method} not allowed for this endpoint`,\n allowedMethods,\n },\n 405,\n { Allow: allowedMethods.join(\", \") },\n );\n }\n return json({ success: false, error: \"Not Found\" }, 404);\n }\n\n /** 处理请求 */\n fetch = async (req: Request): Promise<Response> => {\n const pathname = this.extractPathname(req.url);\n const method = req.method as Method;\n\n const match = this.router.match(method, pathname);\n\n if (match) {\n (req as unknown as Record<string, unknown>).params = match.params;\n\n // 运行时组合中间件\n const allMiddleware = [...this.globalMiddleware, ...match.middleware];\n const handler = composeMiddleware(allMiddleware, match.handler);\n\n return handler(req);\n }\n\n // OPTIONS 预检请求特殊处理:查找同路径其他方法的路由,使用其中间件\n // 这允许路由级 CORS 中间件正常工作\n if (method === \"OPTIONS\") {\n const allowedMethods = this.router.getAllowedMethods(pathname);\n if (allowedMethods.length > 0) {\n // 尝试获取该路径任意方法的路由中间件\n const anyMatch = this.router.match(\n allowedMethods[0] as Method,\n pathname,\n );\n const routeMiddleware = anyMatch?.middleware || [];\n const allMiddleware = [...this.globalMiddleware, ...routeMiddleware];\n\n // OPTIONS 请求默认返回 204(中间件如 CORS 可能会提前响应)\n const optionsHandler = () =>\n new Response(null, {\n status: 204,\n headers: { Allow: allowedMethods.join(\", \") },\n });\n\n const handler = composeMiddleware(allMiddleware, optionsHandler);\n return handler(req);\n }\n }\n\n // 未匹配路由时,仍执行全局中间件(如 CORS 处理 OPTIONS 预检)\n if (this.globalMiddleware.length > 0) {\n const handler = composeMiddleware(this.globalMiddleware, () =>\n this.createErrorResponse(method, pathname),\n );\n return handler(req);\n }\n\n return this.createErrorResponse(method, pathname);\n };\n\n addRoute(route: Route): void {\n const flattenedRoute: FlattenedRoute = {\n ...route,\n fullPath: route.path,\n middlewareChain: route.middleware || [],\n };\n\n this.routes.push(flattenedRoute);\n this.router.register(\n route.method as Method,\n route.path,\n route.handler,\n route.middleware || [],\n );\n }\n\n addRoutes(routes: readonly (Route | NestedRoute)[]): void {\n this.registerRoutes([...routes]);\n }\n\n getRoutes(): Array<{ method: Method; path: string }> {\n return this.router.getRoutes();\n }\n\n /**\n * 获取完整的路由元信息(不含 handler 和 middleware)\n *\n * 用于 API 文档生成、Webhook 事件注册、权限检查等场景\n *\n * @example\n * ```typescript\n * const routes = server.getRoutesWithMeta()\n * for (const route of routes) {\n * console.log(route.fullPath, route.name, route.description)\n * }\n * ```\n */\n getRoutesWithMeta(): FlattenedRoute[] {\n return this.routes;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router-xWzwz_1a.mjs","names":[],"sources":["../src/router.ts"],"sourcesContent":["/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n parentName?: string,\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n // 当前路由的 name(用于传递给子路由)\n const currentName = route.name || parentName;\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n const leafRoute = route as Route;\n flattened.push({\n ...leafRoute,\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n parentName: parentName, // 保存父级名称\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware, currentName);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,oBACd,QACkB;CAClB,MAAM,YAA8B,EAAE;CAEtC,SAAS,aACP,OACA,aAAa,IACb,mBAAiC,EAAE,EACnC,YACM;EAEN,MAAM,cAAc,cAAc,aAAa,MAAM,KAAK;EAE1D,MAAM,oBAAoB,CACxB,GAAG,kBACH,GAAI,MAAM,cAAc,EAAE,CAC3B;EAED,MAAM,cAAc,MAAM,QAAQ;AAElC,MAAI,YAAY,SAAS,aAAa,OAAO;GAE3C,MAAM,YAAY;AAClB,aAAU,KAAK;IACb,GAAG;IACH,UAAU;IACV,iBAAiB;IACL;IACb,CAAC;aACO,cAAc,SAAS,MAAM,SAEtC,MAAK,MAAM,SAAS,MAAM,SACxB,cAAa,OAAO,aAAa,mBAAmB,YAAY;;AAKtE,MAAK,MAAM,SAAS,OAClB,cAAa,MAAM;AAGrB,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,cAAc,MAAsB;CAElD,IAAI,aAAa,mBAAmB,KAAK;AAGzC,cAAa,WAAW,QAAQ,QAAQ,IAAI;AAG5C,KAAI,eAAe,GAAI,QAAO;AAG9B,KAAI,eAAe,OAAO,WAAW,SAAS,IAAI,CAChD,cAAa,WAAW,MAAM,GAAG,GAAG;AAGtC,QAAO"}
|