vafast 0.7.0 → 0.7.1

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 CHANGED
@@ -474,13 +474,74 @@ export default { fetch: server.fetch };" > index.ts && bun index.ts
474
474
  ## 🎯 核心功能
475
475
 
476
476
  - ⚡ **JIT 编译验证器** - Schema 验证器编译缓存,避免重复编译
477
- - 🌲 **Radix Tree 路由** - O(k) 时间复杂度的高效路由匹配
477
+ - 🌲 **Radix Tree 路由** - O(k) 时间复杂度的高效路由匹配(详见[路由规则](#路由匹配规则))
478
478
  - 🎯 **快速请求解析** - 优化的 Query/Cookie 解析,比标准方法快 2x
479
479
  - 🔒 **端到端类型安全** - 完整的 TypeScript 类型推断
480
480
  - 🧩 **灵活中间件系统** - 可组合的中间件架构
481
481
  - 📡 **SSE 流式响应** - 内置 Server-Sent Events 支持,适用于 AI 聊天、进度更新等场景
482
482
  - 📦 **零配置** - 开箱即用,无需复杂配置
483
483
 
484
+ ### 路由匹配规则
485
+
486
+ Vafast 使用 Radix Tree 实现高效路由匹配,支持以下特性:
487
+
488
+ **1. 路由类型**
489
+
490
+ ```typescript
491
+ // 静态路由
492
+ '/users'
493
+ '/api/v1/health'
494
+
495
+ // 动态参数 (:param)
496
+ '/users/:id'
497
+ '/posts/:postId/comments/:commentId'
498
+
499
+ // 通配符 (* 或 *name)
500
+ '/files/*' // 匿名通配符,params['*']
501
+ '/static/*filepath' // 命名通配符,params['filepath']
502
+ ```
503
+
504
+ **2. 优先级规则(与 Hono/Fastify 一致)**
505
+
506
+ ```
507
+ 静态路由 > 动态参数 > 通配符
508
+ ```
509
+
510
+ ```typescript
511
+ // 注册顺序不影响优先级
512
+ router.register('GET', '/users/:id', dynamicHandler);
513
+ router.register('GET', '/users/admin', staticHandler); // 后注册
514
+
515
+ // 匹配结果
516
+ GET /users/admin → staticHandler ✅ 静态优先
517
+ GET /users/123 → dynamicHandler
518
+ ```
519
+
520
+ **3. 同一位置支持不同参数名**
521
+
522
+ 不同路由在同一位置可以使用不同的参数名,每个路由独立返回其定义的参数名:
523
+
524
+ ```typescript
525
+ // 同一位置(/sessions/ 后)使用不同参数名
526
+ router.register('PUT', '/sessions/:id', updateHandler);
527
+ router.register('GET', '/sessions/:sessionId/messages', messagesHandler);
528
+
529
+ // 每个路由返回各自定义的参数名
530
+ PUT /sessions/123 → params = { id: '123' }
531
+ GET /sessions/456/messages → params = { sessionId: '456' }
532
+
533
+ // CRUD 场景完全支持
534
+ router.register('GET', '/users/:userId', getHandler);
535
+ router.register('PUT', '/users/:id', updateHandler);
536
+ router.register('DELETE', '/users/:uid', deleteHandler);
537
+
538
+ GET /users/1 → { userId: '1' }
539
+ PUT /users/2 → { id: '2' }
540
+ DELETE /users/3 → { uid: '3' }
541
+ ```
542
+
543
+ > 💡 参数名冲突时会输出警告(建议保持一致),但不影响功能。
544
+
484
545
  ### 返回值与错误处理
485
546
 
486
547
  Vafast 提供简洁、对称的响应 API:
package/dist/index.mjs CHANGED
@@ -4,11 +4,11 @@ import { c as text, d as composeMiddleware, f as errorHandler, i as json, l as V
4
4
  import { defineMiddleware, defineRoute, defineRoutes, withContext } from "./defineRoute.mjs";
5
5
  import { t as BaseServer } from "./base-server-CE0mfqPY.mjs";
6
6
  import { a as getRoute, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, s as getRoutesByMethod, t as RouteRegistry } from "./route-registry-DsPslV2b.mjs";
7
- import { t as Server } from "./server-DWndB63Z.mjs";
7
+ import { t as Server } from "./server-B4YDcNJy.mjs";
8
8
  import { t as HtmlRenderer } from "./html-renderer-D1zzDVQM.mjs";
9
9
  import { t as DependencyManager } from "./dependency-manager-CGMZJTer.mjs";
10
10
  import { t as ComponentServer } from "./component-server-Cya46YN3.mjs";
11
- import { t as ServerFactory } from "./server-CAhwnEPW.mjs";
11
+ import { t as ServerFactory } from "./server-BNpY3NH6.mjs";
12
12
  import { t as goAwait } from "./go-await-B1U27PgB.mjs";
13
13
  import { n as base64urlEncode, t as base64urlDecode } from "./base64url-Cc77f1ms.mjs";
14
14
  import { Patterns, hasFormat, registerFormat, registerFormats } from "./utils/formats.mjs";
@@ -8,6 +8,12 @@
8
8
  * router.register("GET", "/users/:id", handler);
9
9
  * const result = router.match("GET", "/users/123");
10
10
  * // result.params = { id: "123" }
11
+ *
12
+ * // 支持同一位置使用不同参数名
13
+ * router.register("PUT", "/sessions/:id", updateHandler);
14
+ * router.register("GET", "/sessions/:sessionId/messages", messagesHandler);
15
+ * // PUT /sessions/123 → params = { id: "123" }
16
+ * // GET /sessions/123/messages → params = { sessionId: "123" }
11
17
  * ```
12
18
  */
13
19
  var RadixRouter = class {
@@ -32,17 +38,30 @@ var RadixRouter = class {
32
38
  setCompiler(compiler) {
33
39
  this.compiler = compiler;
34
40
  }
41
+ /**
42
+ * 从路由模式中提取参数名列表
43
+ * @example "/users/:id/posts/:postId" → ["id", "postId"]
44
+ */
45
+ extractParamNames(pattern) {
46
+ const paramNames = [];
47
+ const segments = this.splitPath(pattern);
48
+ for (const segment of segments) if (segment[0] === ":") paramNames.push(segment.substring(1));
49
+ else if (segment[0] === "*") paramNames.push(segment.length > 1 ? segment.substring(1) : "*");
50
+ return paramNames;
51
+ }
35
52
  /** 注册路由 */
36
53
  register(method, pattern, handler, middleware = []) {
37
54
  const segments = this.splitPath(pattern);
55
+ const paramNames = this.extractParamNames(pattern);
38
56
  let node = this.root;
39
57
  for (const segment of segments) {
40
58
  const firstChar = segment[0];
41
59
  if (firstChar === ":") {
60
+ const paramName = segment.substring(1);
42
61
  if (!node.paramChild) {
43
62
  node.paramChild = this.createNode(segment);
44
- node.paramChild.paramName = segment.substring(1);
45
- }
63
+ node.paramChild.paramName = paramName;
64
+ } else if (node.paramChild.paramName !== paramName) console.warn(`⚠️ 路由参数名冲突: 位置 "${node.path || "/"}" 下已有参数 ":${node.paramChild.paramName}",新路由使用 ":${paramName}"。建议使用一致的参数名。`);
46
65
  node = node.paramChild;
47
66
  } else if (firstChar === "*") {
48
67
  if (!node.wildcardChild) {
@@ -58,7 +77,8 @@ var RadixRouter = class {
58
77
  }
59
78
  const routeHandler = {
60
79
  handler,
61
- middleware
80
+ middleware,
81
+ paramNames
62
82
  };
63
83
  if (this.compiler && middleware.length === 0) routeHandler.compiled = this.compiler([], handler);
64
84
  node.handlers[method] = routeHandler;
@@ -83,11 +103,13 @@ var RadixRouter = class {
83
103
  /** 匹配路由 */
84
104
  match(method, path) {
85
105
  const segments = this.splitPath(path);
86
- const params = Object.create(null);
87
- const node = this.matchNode(this.root, segments, 0, params);
106
+ const paramValues = [];
107
+ const node = this.matchNode(this.root, segments, 0, paramValues);
88
108
  if (!node) return null;
89
109
  const routeHandler = node.handlers[method];
90
110
  if (!routeHandler) return null;
111
+ const params = Object.create(null);
112
+ for (let i = 0; i < routeHandler.paramNames.length; i++) params[routeHandler.paramNames[i]] = paramValues[i];
91
113
  return {
92
114
  handler: routeHandler.handler,
93
115
  middleware: routeHandler.middleware,
@@ -96,7 +118,7 @@ var RadixRouter = class {
96
118
  };
97
119
  }
98
120
  /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */
99
- matchNode(node, segments, index, params) {
121
+ matchNode(node, segments, index, paramValues) {
100
122
  if (index === segments.length) {
101
123
  for (const method in node.handlers) if (node.handlers[method]) return node;
102
124
  return null;
@@ -104,20 +126,18 @@ var RadixRouter = class {
104
126
  const segment = segments[index];
105
127
  const staticChild = node.children[segment];
106
128
  if (staticChild) {
107
- const result = this.matchNode(staticChild, segments, index + 1, params);
129
+ const result = this.matchNode(staticChild, segments, index + 1, paramValues);
108
130
  if (result) return result;
109
131
  }
110
132
  if (node.paramChild) {
111
- const paramName = node.paramChild.paramName;
112
- const oldValue = params[paramName];
113
- params[paramName] = segment;
114
- const result = this.matchNode(node.paramChild, segments, index + 1, params);
133
+ const valueIndex = paramValues.length;
134
+ paramValues.push(segment);
135
+ const result = this.matchNode(node.paramChild, segments, index + 1, paramValues);
115
136
  if (result) return result;
116
- if (oldValue === void 0) delete params[paramName];
117
- else params[paramName] = oldValue;
137
+ paramValues.length = valueIndex;
118
138
  }
119
139
  if (node.wildcardChild) {
120
- params[node.wildcardChild.paramName || "*"] = segments.slice(index).join("/");
140
+ paramValues.push(segments.slice(index).join("/"));
121
141
  return node.wildcardChild;
122
142
  }
123
143
  return null;
@@ -160,4 +180,4 @@ var RadixRouter = class {
160
180
 
161
181
  //#endregion
162
182
  export { RadixRouter as t };
163
- //# sourceMappingURL=radix-tree-CccjvyTP.mjs.map
183
+ //# sourceMappingURL=radix-tree-dyn3qDFX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radix-tree-dyn3qDFX.mjs","names":[],"sources":["../src/router/radix-tree.ts"],"sourcesContent":["/**\n * Radix Tree 路由匹配器\n *\n * 高性能路由匹配实现,时间复杂度 O(k),k 为路径段数\n *\n * 支持的路由模式:\n * - 静态路径: /users, /api/v1/health\n * - 动态参数: /users/:id, /posts/:postId/comments/:commentId\n * - 通配符: /files/*, /static/*filepath\n * \n * 特性:\n * - 同一位置支持不同参数名(如 /sessions/:id 和 /sessions/:sessionId/messages)\n * - 参数名冲突时会发出警告,但不影响功能\n */\n\nimport type { Handler, Middleware, Method } from \"../types\";\n\n/** 预编译的处理器类型 */\ntype CompiledHandler = (req: Request) => Promise<Response>;\n\n/** 路由处理信息 */\ninterface RouteHandler {\n handler: Handler;\n middleware: Middleware[];\n /** 预编译后的完整处理链(包含中间件) */\n compiled?: CompiledHandler;\n /** 该路由的参数名列表(按顺序) */\n paramNames: string[];\n}\n\n/** Radix Tree 节点 */\ninterface RadixNode {\n path: string;\n children: Record<string, RadixNode>;\n paramChild?: RadixNode;\n wildcardChild?: RadixNode;\n /** 该位置的参数名(仅用于调试和警告) */\n paramName?: string;\n handlers: Record<Method, RouteHandler | undefined>;\n}\n\n/** 路由匹配结果 */\nexport interface MatchResult {\n handler: Handler;\n middleware: Middleware[];\n params: Record<string, string>;\n /** 预编译后的完整处理链 */\n compiled?: CompiledHandler;\n}\n\n/**\n * Radix Tree 路由器\n *\n * @example\n * ```typescript\n * const router = new RadixRouter();\n * router.register(\"GET\", \"/users/:id\", handler);\n * const result = router.match(\"GET\", \"/users/123\");\n * // result.params = { id: \"123\" }\n * \n * // 支持同一位置使用不同参数名\n * router.register(\"PUT\", \"/sessions/:id\", updateHandler);\n * router.register(\"GET\", \"/sessions/:sessionId/messages\", messagesHandler);\n * // PUT /sessions/123 → params = { id: \"123\" }\n * // GET /sessions/123/messages → params = { sessionId: \"123\" }\n * ```\n */\nexport class RadixRouter {\n private root: RadixNode;\n\n constructor() {\n this.root = this.createNode(\"\");\n }\n\n private createNode(path: string): RadixNode {\n return {\n path,\n children: Object.create(null),\n handlers: Object.create(null),\n };\n }\n\n /** 分割路径 */\n private splitPath(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n }\n\n /** 编译器函数 - 用于预编译中间件链 */\n private compiler?: (\n middleware: Middleware[],\n handler: Handler,\n ) => CompiledHandler;\n\n /** 设置中间件编译器 */\n setCompiler(\n compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler,\n ): void {\n this.compiler = compiler;\n }\n\n /**\n * 从路由模式中提取参数名列表\n * @example \"/users/:id/posts/:postId\" → [\"id\", \"postId\"]\n */\n private extractParamNames(pattern: string): string[] {\n const paramNames: string[] = [];\n const segments = this.splitPath(pattern);\n \n for (const segment of segments) {\n if (segment[0] === \":\") {\n paramNames.push(segment.substring(1));\n } else if (segment[0] === \"*\") {\n paramNames.push(segment.length > 1 ? segment.substring(1) : \"*\");\n }\n }\n \n return paramNames;\n }\n\n /** 注册路由 */\n register(\n method: Method,\n pattern: string,\n handler: Handler,\n middleware: Middleware[] = [],\n ): void {\n const segments = this.splitPath(pattern);\n const paramNames = this.extractParamNames(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n const firstChar = segment[0];\n\n if (firstChar === \":\") {\n // 动态参数节点\n const paramName = segment.substring(1);\n if (!node.paramChild) {\n node.paramChild = this.createNode(segment);\n node.paramChild.paramName = paramName;\n } else if (node.paramChild.paramName !== paramName) {\n // 参数名冲突警告(但不影响功能)\n console.warn(\n `⚠️ 路由参数名冲突: 位置 \"${node.path || '/'}\" 下已有参数 \":${node.paramChild.paramName}\",` +\n `新路由使用 \":${paramName}\"。建议使用一致的参数名。`\n );\n }\n node = node.paramChild;\n } else if (firstChar === \"*\") {\n // 通配符节点\n if (!node.wildcardChild) {\n node.wildcardChild = this.createNode(segment);\n node.wildcardChild.paramName =\n segment.length > 1 ? segment.substring(1) : \"*\";\n }\n node = node.wildcardChild;\n break;\n } else {\n // 静态路径节点\n if (!node.children[segment]) {\n node.children[segment] = this.createNode(segment);\n }\n node = node.children[segment];\n }\n }\n\n const routeHandler: RouteHandler = { handler, middleware, paramNames };\n\n // 如果没有全局中间件且设置了编译器,预编译处理链\n if (this.compiler && middleware.length === 0) {\n routeHandler.compiled = this.compiler([], handler);\n }\n\n node.handlers[method] = routeHandler;\n }\n\n /** 预编译所有路由(在添加全局中间件后调用) */\n precompileAll(globalMiddleware: Middleware[]): void {\n if (!this.compiler) return;\n this.precompileNode(this.root, globalMiddleware);\n }\n\n private precompileNode(\n node: RadixNode,\n globalMiddleware: Middleware[],\n ): void {\n for (const method in node.handlers) {\n const routeHandler = node.handlers[method as Method];\n if (routeHandler) {\n const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];\n routeHandler.compiled = this.compiler!(\n allMiddleware,\n routeHandler.handler,\n );\n }\n }\n\n for (const key in node.children) {\n this.precompileNode(node.children[key], globalMiddleware);\n }\n\n if (node.paramChild) {\n this.precompileNode(node.paramChild, globalMiddleware);\n }\n\n if (node.wildcardChild) {\n this.precompileNode(node.wildcardChild, globalMiddleware);\n }\n }\n\n /** 匹配路由 */\n match(method: Method, path: string): MatchResult | null {\n const segments = this.splitPath(path);\n // 使用数组按位置收集参数值\n const paramValues: string[] = [];\n\n const node = this.matchNode(this.root, segments, 0, paramValues);\n if (!node) return null;\n\n const routeHandler = node.handlers[method];\n if (!routeHandler) return null;\n\n // 根据路由自己的 paramNames 构建 params 对象\n const params: Record<string, string> = Object.create(null);\n for (let i = 0; i < routeHandler.paramNames.length; i++) {\n params[routeHandler.paramNames[i]] = paramValues[i];\n }\n\n return {\n handler: routeHandler.handler,\n middleware: routeHandler.middleware,\n params,\n compiled: routeHandler.compiled,\n };\n }\n\n /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */\n private matchNode(\n node: RadixNode,\n segments: string[],\n index: number,\n paramValues: string[],\n ): RadixNode | null {\n if (index === segments.length) {\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) return node;\n }\n return null;\n }\n\n const segment = segments[index];\n\n // 1. 静态路径\n const staticChild = node.children[segment];\n if (staticChild) {\n const result = this.matchNode(staticChild, segments, index + 1, paramValues);\n if (result) return result;\n }\n\n // 2. 动态参数\n if (node.paramChild) {\n const valueIndex = paramValues.length;\n paramValues.push(segment);\n \n const result = this.matchNode(\n node.paramChild,\n segments,\n index + 1,\n paramValues,\n );\n\n if (result) return result;\n\n // 回溯:移除添加的参数值\n paramValues.length = valueIndex;\n }\n\n // 3. 通配符\n if (node.wildcardChild) {\n paramValues.push(segments.slice(index).join(\"/\"));\n return node.wildcardChild;\n }\n\n return null;\n }\n\n /** 获取路径允许的 HTTP 方法 */\n getAllowedMethods(path: string): Method[] {\n const segments = this.splitPath(path);\n const node = this.findNode(segments);\n if (!node) return [];\n\n const methods: Method[] = [];\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n methods.push(method as Method);\n }\n }\n return methods;\n }\n\n /** 查找节点(不提取参数) */\n private findNode(segments: string[]): RadixNode | null {\n let node = this.root;\n\n for (const segment of segments) {\n if (node.children[segment]) {\n node = node.children[segment];\n } else if (node.paramChild) {\n node = node.paramChild;\n } else if (node.wildcardChild) {\n return node.wildcardChild;\n } else {\n return null;\n }\n }\n\n return node;\n }\n\n /** 获取所有已注册的路由 */\n getRoutes(): Array<{ method: Method; path: string }> {\n const routes: Array<{ method: Method; path: string }> = [];\n this.collectRoutes(this.root, \"\", routes);\n return routes;\n }\n\n private collectRoutes(\n node: RadixNode,\n prefix: string,\n routes: Array<{ method: Method; path: string }>,\n ): void {\n const currentPath = prefix + (node.path ? \"/\" + node.path : \"\");\n\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n routes.push({ method: method as Method, path: currentPath || \"/\" });\n }\n }\n\n for (const key in node.children) {\n this.collectRoutes(node.children[key], currentPath, routes);\n }\n\n if (node.paramChild) {\n this.collectRoutes(node.paramChild, currentPath, routes);\n }\n\n if (node.wildcardChild) {\n this.collectRoutes(node.wildcardChild, currentPath, routes);\n }\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as RadixRouter } from "../radix-tree-CccjvyTP.mjs";
1
+ import { t as RadixRouter } from "../radix-tree-dyn3qDFX.mjs";
2
2
  import { normalizePath } from "../router.mjs";
3
3
 
4
4
  export { RadixRouter, normalizePath };
@@ -21,6 +21,12 @@ interface MatchResult {
21
21
  * router.register("GET", "/users/:id", handler);
22
22
  * const result = router.match("GET", "/users/123");
23
23
  * // result.params = { id: "123" }
24
+ *
25
+ * // 支持同一位置使用不同参数名
26
+ * router.register("PUT", "/sessions/:id", updateHandler);
27
+ * router.register("GET", "/sessions/:sessionId/messages", messagesHandler);
28
+ * // PUT /sessions/123 → params = { id: "123" }
29
+ * // GET /sessions/123/messages → params = { sessionId: "123" }
24
30
  * ```
25
31
  */
26
32
  declare class RadixRouter {
@@ -33,6 +39,11 @@ declare class RadixRouter {
33
39
  private compiler?;
34
40
  /** 设置中间件编译器 */
35
41
  setCompiler(compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler): void;
42
+ /**
43
+ * 从路由模式中提取参数名列表
44
+ * @example "/users/:id/posts/:postId" → ["id", "postId"]
45
+ */
46
+ private extractParamNames;
36
47
  /** 注册路由 */
37
48
  register(method: Method, pattern: string, handler: Handler, middleware?: Middleware[]): void;
38
49
  /** 预编译所有路由(在添加全局中间件后调用) */
@@ -1,3 +1,3 @@
1
- import { t as RadixRouter } from "../radix-tree-CccjvyTP.mjs";
1
+ import { t as RadixRouter } from "../radix-tree-dyn3qDFX.mjs";
2
2
 
3
3
  export { RadixRouter };
@@ -1,8 +1,8 @@
1
1
  import "../response-Bs9GhJz-.mjs";
2
2
  import { t as BaseServer } from "../base-server-CE0mfqPY.mjs";
3
- import { t as Server } from "../server-DWndB63Z.mjs";
3
+ import { t as Server } from "../server-B4YDcNJy.mjs";
4
4
  import "../dependency-manager-CGMZJTer.mjs";
5
5
  import { t as ComponentServer } from "../component-server-Cya46YN3.mjs";
6
- import { t as ServerFactory } from "../server-CAhwnEPW.mjs";
6
+ import { t as ServerFactory } from "../server-BNpY3NH6.mjs";
7
7
 
8
8
  export { BaseServer, ComponentServer, Server, ServerFactory };
@@ -1,7 +1,7 @@
1
1
  import "../response-Bs9GhJz-.mjs";
2
- import "../server-DWndB63Z.mjs";
2
+ import "../server-B4YDcNJy.mjs";
3
3
  import "../dependency-manager-CGMZJTer.mjs";
4
4
  import "../component-server-Cya46YN3.mjs";
5
- import { t as ServerFactory } from "../server-CAhwnEPW.mjs";
5
+ import { t as ServerFactory } from "../server-BNpY3NH6.mjs";
6
6
 
7
7
  export { ServerFactory };
@@ -1,4 +1,4 @@
1
1
  import "../response-Bs9GhJz-.mjs";
2
- import { t as Server } from "../server-DWndB63Z.mjs";
2
+ import { t as Server } from "../server-B4YDcNJy.mjs";
3
3
 
4
4
  export { Server };
@@ -1,6 +1,6 @@
1
1
  import { d as composeMiddleware, f as errorHandler, i as json } from "./response-Bs9GhJz-.mjs";
2
2
  import { t as BaseServer } from "./base-server-CE0mfqPY.mjs";
3
- import { t as RadixRouter } from "./radix-tree-CccjvyTP.mjs";
3
+ import { t as RadixRouter } from "./radix-tree-dyn3qDFX.mjs";
4
4
  import { c as setGlobalRegistry, t as RouteRegistry } from "./route-registry-DsPslV2b.mjs";
5
5
 
6
6
  //#region src/server/server.ts
@@ -113,4 +113,4 @@ var Server = class extends BaseServer {
113
113
 
114
114
  //#endregion
115
115
  export { Server as t };
116
- //# sourceMappingURL=server-DWndB63Z.mjs.map
116
+ //# sourceMappingURL=server-B4YDcNJy.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-DWndB63Z.mjs","names":[],"sources":["../src/server/server.ts"],"sourcesContent":["/**\n * Vafast 核心服务器\n *\n * 基于 Radix Tree 的高性能路由匹配\n * 时间复杂度: O(k),k 为路径段数\n */\n\nimport type { Method, Middleware } from \"../types\";\nimport type { ProcessedRoute } from \"../defineRoute\";\nimport { composeMiddleware, errorHandler } 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 routes = defineRoutes([\n * defineRoute({ method: \"GET\", path: \"/\", handler: () => \"Hello\" }),\n * ])\n * const server = new Server(routes)\n * export default { fetch: server.fetch }\n * ```\n */\nexport class Server extends BaseServer {\n private router: RadixRouter;\n private routes: ProcessedRoute[];\n\n constructor(routes: readonly ProcessedRoute[] = []) {\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: ProcessedRoute[]): void {\n this.routes.push(...routes);\n\n for (const route of routes) {\n this.router.register(\n route.method as Method,\n route.path,\n route.handler,\n (route.middleware || []) as Middleware[],\n );\n }\n\n this.detectRouteConflicts(routes);\n this.logRoutes(routes);\n\n // 自动设置全局 RouteRegistry\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 code: 405,\n message: `Method ${method} not allowed for this endpoint`,\n allowedMethods,\n },\n 405,\n { Allow: allowedMethods.join(\", \") },\n );\n }\n return json({ code: 404, message: \"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 // 洋葱模型:globalMiddleware → errorHandler → routeMiddleware → handler\n // 这样 errorHandler 返回的错误响应也会经过 globalMiddleware(如 CORS)的后处理\n const allMiddleware = [\n ...this.globalMiddleware,\n errorHandler,\n ...match.middleware,\n ];\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 = [\n ...this.globalMiddleware,\n errorHandler,\n ...routeMiddleware,\n ];\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 allMiddleware = [...this.globalMiddleware, errorHandler];\n const handler = composeMiddleware(allMiddleware, () =>\n this.createErrorResponse(method, pathname),\n );\n return handler(req);\n }\n\n return this.createErrorResponse(method, pathname);\n };\n\n /** 动态添加单个路由 */\n addRoute(route: ProcessedRoute): void {\n this.routes.push(route);\n this.router.register(\n route.method as Method,\n route.path,\n route.handler,\n (route.middleware || []) as Middleware[],\n );\n }\n\n /** 动态添加多个路由 */\n addRoutes(routes: readonly ProcessedRoute[]): void {\n this.registerRoutes([...routes]);\n }\n\n /** 获取路由列表 */\n getRoutes(): Array<{ method: Method; path: string }> {\n return this.router.getRoutes();\n }\n\n /**\n * 获取完整的路由元信息\n *\n * 用于 API 文档生成、Webhook 事件注册、权限检查等场景\n */\n getRoutesWithMeta(): ProcessedRoute[] {\n return this.routes;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BA,IAAa,SAAb,cAA4B,WAAW;CACrC,AAAQ;CACR,AAAQ;CAER,YAAY,SAAoC,EAAE,EAAE;AAClD,SAAO;AACP,OAAK,SAAS,IAAI,aAAa;AAC/B,OAAK,SAAS,EAAE;AAEhB,MAAI,OAAO,SAAS,EAClB,MAAK,eAAe,CAAC,GAAG,OAAO,CAAC;;CAIpC,AAAQ,eAAe,QAAgC;AACrD,OAAK,OAAO,KAAK,GAAG,OAAO;AAE3B,OAAK,MAAM,SAAS,OAClB,MAAK,OAAO,SACV,MAAM,QACN,MAAM,MACN,MAAM,SACL,MAAM,cAAc,EAAE,CACxB;AAGH,OAAK,qBAAqB,OAAO;AACjC,OAAK,UAAU,OAAO;AAGtB,oBAAkB,IAAI,cAAc,KAAK,OAAO,CAAC;;;CAInD,AAAQ,gBAAgB,KAAqB;EAC3C,IAAI,QAAQ,IAAI,QAAQ,MAAM;AAC9B,UAAQ,UAAU,KAAK,IAAI,QAAQ;EAEnC,MAAM,YAAY,IAAI,QAAQ,KAAK,MAAM;AACzC,MAAI,cAAc,GAAI,QAAO;EAE7B,IAAI,MAAM,IAAI,QAAQ,KAAK,UAAU;AACrC,MAAI,QAAQ,GAAI,OAAM,IAAI,QAAQ,KAAK,UAAU;AACjD,MAAI,QAAQ,GAAI,OAAM,IAAI;AAE1B,SAAO,IAAI,UAAU,WAAW,IAAI,IAAI;;;CAI1C,AAAQ,oBAAoB,QAAgB,UAA4B;EACtE,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,SAAS;AAC9D,MAAI,eAAe,SAAS,EAC1B,QAAO,KACL;GACE,MAAM;GACN,SAAS,UAAU,OAAO;GAC1B;GACD,EACD,KACA,EAAE,OAAO,eAAe,KAAK,KAAK,EAAE,CACrC;AAEH,SAAO,KAAK;GAAE,MAAM;GAAK,SAAS;GAAa,EAAE,IAAI;;;CAIvD,QAAQ,OAAO,QAAoC;EACjD,MAAM,WAAW,KAAK,gBAAgB,IAAI,IAAI;EAC9C,MAAM,SAAS,IAAI;EAEnB,MAAM,QAAQ,KAAK,OAAO,MAAM,QAAQ,SAAS;AAEjD,MAAI,OAAO;AACT,GAAC,IAA2C,SAAS,MAAM;AAY3D,UAFgB,kBALM;IACpB,GAAG,KAAK;IACR;IACA,GAAG,MAAM;IACV,EACgD,MAAM,QAAQ,CAEhD,IAAI;;AAKrB,MAAI,WAAW,WAAW;GACxB,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,SAAS;AAC9D,OAAI,eAAe,SAAS,GAAG;IAM7B,MAAM,kBAJW,KAAK,OAAO,MAC3B,eAAe,IACf,SACD,EACiC,cAAc,EAAE;IAClD,MAAM,gBAAgB;KACpB,GAAG,KAAK;KACR;KACA,GAAG;KACJ;IAGD,MAAM,uBACJ,IAAI,SAAS,MAAM;KACjB,QAAQ;KACR,SAAS,EAAE,OAAO,eAAe,KAAK,KAAK,EAAE;KAC9C,CAAC;AAGJ,WADgB,kBAAkB,eAAe,eAAe,CACjD,IAAI;;;AAKvB,MAAI,KAAK,iBAAiB,SAAS,EAKjC,QAHgB,kBADM,CAAC,GAAG,KAAK,kBAAkB,aAAa,QAE5D,KAAK,oBAAoB,QAAQ,SAAS,CAC3C,CACc,IAAI;AAGrB,SAAO,KAAK,oBAAoB,QAAQ,SAAS;;;CAInD,SAAS,OAA6B;AACpC,OAAK,OAAO,KAAK,MAAM;AACvB,OAAK,OAAO,SACV,MAAM,QACN,MAAM,MACN,MAAM,SACL,MAAM,cAAc,EAAE,CACxB;;;CAIH,UAAU,QAAyC;AACjD,OAAK,eAAe,CAAC,GAAG,OAAO,CAAC;;;CAIlC,YAAqD;AACnD,SAAO,KAAK,OAAO,WAAW;;;;;;;CAQhC,oBAAsC;AACpC,SAAO,KAAK"}
1
+ {"version":3,"file":"server-B4YDcNJy.mjs","names":[],"sources":["../src/server/server.ts"],"sourcesContent":["/**\n * Vafast 核心服务器\n *\n * 基于 Radix Tree 的高性能路由匹配\n * 时间复杂度: O(k),k 为路径段数\n */\n\nimport type { Method, Middleware } from \"../types\";\nimport type { ProcessedRoute } from \"../defineRoute\";\nimport { composeMiddleware, errorHandler } 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 routes = defineRoutes([\n * defineRoute({ method: \"GET\", path: \"/\", handler: () => \"Hello\" }),\n * ])\n * const server = new Server(routes)\n * export default { fetch: server.fetch }\n * ```\n */\nexport class Server extends BaseServer {\n private router: RadixRouter;\n private routes: ProcessedRoute[];\n\n constructor(routes: readonly ProcessedRoute[] = []) {\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: ProcessedRoute[]): void {\n this.routes.push(...routes);\n\n for (const route of routes) {\n this.router.register(\n route.method as Method,\n route.path,\n route.handler,\n (route.middleware || []) as Middleware[],\n );\n }\n\n this.detectRouteConflicts(routes);\n this.logRoutes(routes);\n\n // 自动设置全局 RouteRegistry\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 code: 405,\n message: `Method ${method} not allowed for this endpoint`,\n allowedMethods,\n },\n 405,\n { Allow: allowedMethods.join(\", \") },\n );\n }\n return json({ code: 404, message: \"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 // 洋葱模型:globalMiddleware → errorHandler → routeMiddleware → handler\n // 这样 errorHandler 返回的错误响应也会经过 globalMiddleware(如 CORS)的后处理\n const allMiddleware = [\n ...this.globalMiddleware,\n errorHandler,\n ...match.middleware,\n ];\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 = [\n ...this.globalMiddleware,\n errorHandler,\n ...routeMiddleware,\n ];\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 allMiddleware = [...this.globalMiddleware, errorHandler];\n const handler = composeMiddleware(allMiddleware, () =>\n this.createErrorResponse(method, pathname),\n );\n return handler(req);\n }\n\n return this.createErrorResponse(method, pathname);\n };\n\n /** 动态添加单个路由 */\n addRoute(route: ProcessedRoute): void {\n this.routes.push(route);\n this.router.register(\n route.method as Method,\n route.path,\n route.handler,\n (route.middleware || []) as Middleware[],\n );\n }\n\n /** 动态添加多个路由 */\n addRoutes(routes: readonly ProcessedRoute[]): void {\n this.registerRoutes([...routes]);\n }\n\n /** 获取路由列表 */\n getRoutes(): Array<{ method: Method; path: string }> {\n return this.router.getRoutes();\n }\n\n /**\n * 获取完整的路由元信息\n *\n * 用于 API 文档生成、Webhook 事件注册、权限检查等场景\n */\n getRoutesWithMeta(): ProcessedRoute[] {\n return this.routes;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BA,IAAa,SAAb,cAA4B,WAAW;CACrC,AAAQ;CACR,AAAQ;CAER,YAAY,SAAoC,EAAE,EAAE;AAClD,SAAO;AACP,OAAK,SAAS,IAAI,aAAa;AAC/B,OAAK,SAAS,EAAE;AAEhB,MAAI,OAAO,SAAS,EAClB,MAAK,eAAe,CAAC,GAAG,OAAO,CAAC;;CAIpC,AAAQ,eAAe,QAAgC;AACrD,OAAK,OAAO,KAAK,GAAG,OAAO;AAE3B,OAAK,MAAM,SAAS,OAClB,MAAK,OAAO,SACV,MAAM,QACN,MAAM,MACN,MAAM,SACL,MAAM,cAAc,EAAE,CACxB;AAGH,OAAK,qBAAqB,OAAO;AACjC,OAAK,UAAU,OAAO;AAGtB,oBAAkB,IAAI,cAAc,KAAK,OAAO,CAAC;;;CAInD,AAAQ,gBAAgB,KAAqB;EAC3C,IAAI,QAAQ,IAAI,QAAQ,MAAM;AAC9B,UAAQ,UAAU,KAAK,IAAI,QAAQ;EAEnC,MAAM,YAAY,IAAI,QAAQ,KAAK,MAAM;AACzC,MAAI,cAAc,GAAI,QAAO;EAE7B,IAAI,MAAM,IAAI,QAAQ,KAAK,UAAU;AACrC,MAAI,QAAQ,GAAI,OAAM,IAAI,QAAQ,KAAK,UAAU;AACjD,MAAI,QAAQ,GAAI,OAAM,IAAI;AAE1B,SAAO,IAAI,UAAU,WAAW,IAAI,IAAI;;;CAI1C,AAAQ,oBAAoB,QAAgB,UAA4B;EACtE,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,SAAS;AAC9D,MAAI,eAAe,SAAS,EAC1B,QAAO,KACL;GACE,MAAM;GACN,SAAS,UAAU,OAAO;GAC1B;GACD,EACD,KACA,EAAE,OAAO,eAAe,KAAK,KAAK,EAAE,CACrC;AAEH,SAAO,KAAK;GAAE,MAAM;GAAK,SAAS;GAAa,EAAE,IAAI;;;CAIvD,QAAQ,OAAO,QAAoC;EACjD,MAAM,WAAW,KAAK,gBAAgB,IAAI,IAAI;EAC9C,MAAM,SAAS,IAAI;EAEnB,MAAM,QAAQ,KAAK,OAAO,MAAM,QAAQ,SAAS;AAEjD,MAAI,OAAO;AACT,GAAC,IAA2C,SAAS,MAAM;AAY3D,UAFgB,kBALM;IACpB,GAAG,KAAK;IACR;IACA,GAAG,MAAM;IACV,EACgD,MAAM,QAAQ,CAEhD,IAAI;;AAKrB,MAAI,WAAW,WAAW;GACxB,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,SAAS;AAC9D,OAAI,eAAe,SAAS,GAAG;IAM7B,MAAM,kBAJW,KAAK,OAAO,MAC3B,eAAe,IACf,SACD,EACiC,cAAc,EAAE;IAClD,MAAM,gBAAgB;KACpB,GAAG,KAAK;KACR;KACA,GAAG;KACJ;IAGD,MAAM,uBACJ,IAAI,SAAS,MAAM;KACjB,QAAQ;KACR,SAAS,EAAE,OAAO,eAAe,KAAK,KAAK,EAAE;KAC9C,CAAC;AAGJ,WADgB,kBAAkB,eAAe,eAAe,CACjD,IAAI;;;AAKvB,MAAI,KAAK,iBAAiB,SAAS,EAKjC,QAHgB,kBADM,CAAC,GAAG,KAAK,kBAAkB,aAAa,QAE5D,KAAK,oBAAoB,QAAQ,SAAS,CAC3C,CACc,IAAI;AAGrB,SAAO,KAAK,oBAAoB,QAAQ,SAAS;;;CAInD,SAAS,OAA6B;AACpC,OAAK,OAAO,KAAK,MAAM;AACvB,OAAK,OAAO,SACV,MAAM,QACN,MAAM,MACN,MAAM,SACL,MAAM,cAAc,EAAE,CACxB;;;CAIH,UAAU,QAAyC;AACjD,OAAK,eAAe,CAAC,GAAG,OAAO,CAAC;;;CAIlC,YAAqD;AACnD,SAAO,KAAK,OAAO,WAAW;;;;;;;CAQhC,oBAAsC;AACpC,SAAO,KAAK"}
@@ -1,4 +1,4 @@
1
- import { t as Server } from "./server-DWndB63Z.mjs";
1
+ import { t as Server } from "./server-B4YDcNJy.mjs";
2
2
  import { t as ComponentServer } from "./component-server-Cya46YN3.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-CAhwnEPW.mjs.map
70
+ //# sourceMappingURL=server-BNpY3NH6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-CAhwnEPW.mjs","names":[],"sources":["../src/server/server-factory.ts"],"sourcesContent":["import type { ProcessedRoute } from \"../defineRoute\";\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: ProcessedRoute[]): 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,QAAkC;EACjD,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
+ {"version":3,"file":"server-BNpY3NH6.mjs","names":[],"sources":["../src/server/server-factory.ts"],"sourcesContent":["import type { ProcessedRoute } from \"../defineRoute\";\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: ProcessedRoute[]): 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,QAAkC;EACjD,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vafast",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "极简结构化Web框架,支持 Bun 和 Node.js。Go风格,函数优先。",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"radix-tree-CccjvyTP.mjs","names":[],"sources":["../src/router/radix-tree.ts"],"sourcesContent":["/**\n * Radix Tree 路由匹配器\n *\n * 高性能路由匹配实现,时间复杂度 O(k),k 为路径段数\n *\n * 支持的路由模式:\n * - 静态路径: /users, /api/v1/health\n * - 动态参数: /users/:id, /posts/:postId/comments/:commentId\n * - 通配符: /files/*, /static/*filepath\n */\n\nimport type { Handler, Middleware, Method } from \"../types\";\n\n/** 预编译的处理器类型 */\ntype CompiledHandler = (req: Request) => Promise<Response>;\n\n/** 路由处理信息 */\ninterface RouteHandler {\n handler: Handler;\n middleware: Middleware[];\n /** 预编译后的完整处理链(包含中间件) */\n compiled?: CompiledHandler;\n}\n\n/** Radix Tree 节点 */\ninterface RadixNode {\n path: string;\n children: Record<string, RadixNode>;\n paramChild?: RadixNode;\n wildcardChild?: RadixNode;\n paramName?: string;\n handlers: Record<Method, RouteHandler | undefined>;\n}\n\n/** 路由匹配结果 */\nexport interface MatchResult {\n handler: Handler;\n middleware: Middleware[];\n params: Record<string, string>;\n /** 预编译后的完整处理链 */\n compiled?: CompiledHandler;\n}\n\n/**\n * Radix Tree 路由器\n *\n * @example\n * ```typescript\n * const router = new RadixRouter();\n * router.register(\"GET\", \"/users/:id\", handler);\n * const result = router.match(\"GET\", \"/users/123\");\n * // result.params = { id: \"123\" }\n * ```\n */\nexport class RadixRouter {\n private root: RadixNode;\n\n constructor() {\n this.root = this.createNode(\"\");\n }\n\n private createNode(path: string): RadixNode {\n return {\n path,\n children: Object.create(null),\n handlers: Object.create(null),\n };\n }\n\n /** 分割路径 */\n private splitPath(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n }\n\n /** 编译器函数 - 用于预编译中间件链 */\n private compiler?: (\n middleware: Middleware[],\n handler: Handler,\n ) => CompiledHandler;\n\n /** 设置中间件编译器 */\n setCompiler(\n compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler,\n ): void {\n this.compiler = compiler;\n }\n\n /** 注册路由 */\n register(\n method: Method,\n pattern: string,\n handler: Handler,\n middleware: Middleware[] = [],\n ): void {\n const segments = this.splitPath(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n const firstChar = segment[0];\n\n if (firstChar === \":\") {\n // 动态参数节点\n if (!node.paramChild) {\n node.paramChild = this.createNode(segment);\n node.paramChild.paramName = segment.substring(1);\n }\n node = node.paramChild;\n } else if (firstChar === \"*\") {\n // 通配符节点\n if (!node.wildcardChild) {\n node.wildcardChild = this.createNode(segment);\n node.wildcardChild.paramName =\n segment.length > 1 ? segment.substring(1) : \"*\";\n }\n node = node.wildcardChild;\n break;\n } else {\n // 静态路径节点\n if (!node.children[segment]) {\n node.children[segment] = this.createNode(segment);\n }\n node = node.children[segment];\n }\n }\n\n const routeHandler: RouteHandler = { handler, middleware };\n\n // 如果没有全局中间件且设置了编译器,预编译处理链\n if (this.compiler && middleware.length === 0) {\n routeHandler.compiled = this.compiler([], handler);\n }\n\n node.handlers[method] = routeHandler;\n }\n\n /** 预编译所有路由(在添加全局中间件后调用) */\n precompileAll(globalMiddleware: Middleware[]): void {\n if (!this.compiler) return;\n this.precompileNode(this.root, globalMiddleware);\n }\n\n private precompileNode(\n node: RadixNode,\n globalMiddleware: Middleware[],\n ): void {\n for (const method in node.handlers) {\n const routeHandler = node.handlers[method as Method];\n if (routeHandler) {\n const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];\n routeHandler.compiled = this.compiler!(\n allMiddleware,\n routeHandler.handler,\n );\n }\n }\n\n for (const key in node.children) {\n this.precompileNode(node.children[key], globalMiddleware);\n }\n\n if (node.paramChild) {\n this.precompileNode(node.paramChild, globalMiddleware);\n }\n\n if (node.wildcardChild) {\n this.precompileNode(node.wildcardChild, globalMiddleware);\n }\n }\n\n /** 匹配路由 */\n match(method: Method, path: string): MatchResult | null {\n const segments = this.splitPath(path);\n const params: Record<string, string> = Object.create(null);\n\n const node = this.matchNode(this.root, segments, 0, params);\n if (!node) return null;\n\n const routeHandler = node.handlers[method];\n if (!routeHandler) return null;\n\n return {\n handler: routeHandler.handler,\n middleware: routeHandler.middleware,\n params,\n compiled: routeHandler.compiled,\n };\n }\n\n /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */\n private matchNode(\n node: RadixNode,\n segments: string[],\n index: number,\n params: Record<string, string>,\n ): RadixNode | null {\n if (index === segments.length) {\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) return node;\n }\n return null;\n }\n\n const segment = segments[index];\n\n // 1. 静态路径\n const staticChild = node.children[segment];\n if (staticChild) {\n const result = this.matchNode(staticChild, segments, index + 1, params);\n if (result) return result;\n }\n\n // 2. 动态参数\n if (node.paramChild) {\n const paramName = node.paramChild.paramName!;\n const oldValue = params[paramName];\n\n params[paramName] = segment;\n const result = this.matchNode(\n node.paramChild,\n segments,\n index + 1,\n params,\n );\n\n if (result) return result;\n\n // 回溯\n if (oldValue === undefined) {\n delete params[paramName];\n } else {\n params[paramName] = oldValue;\n }\n }\n\n // 3. 通配符\n if (node.wildcardChild) {\n params[node.wildcardChild.paramName || \"*\"] = segments\n .slice(index)\n .join(\"/\");\n return node.wildcardChild;\n }\n\n return null;\n }\n\n /** 获取路径允许的 HTTP 方法 */\n getAllowedMethods(path: string): Method[] {\n const segments = this.splitPath(path);\n const node = this.findNode(segments);\n if (!node) return [];\n\n const methods: Method[] = [];\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n methods.push(method as Method);\n }\n }\n return methods;\n }\n\n /** 查找节点(不提取参数) */\n private findNode(segments: string[]): RadixNode | null {\n let node = this.root;\n\n for (const segment of segments) {\n if (node.children[segment]) {\n node = node.children[segment];\n } else if (node.paramChild) {\n node = node.paramChild;\n } else if (node.wildcardChild) {\n return node.wildcardChild;\n } else {\n return null;\n }\n }\n\n return node;\n }\n\n /** 获取所有已注册的路由 */\n getRoutes(): Array<{ method: Method; path: string }> {\n const routes: Array<{ method: Method; path: string }> = [];\n this.collectRoutes(this.root, \"\", routes);\n return routes;\n }\n\n private collectRoutes(\n node: RadixNode,\n prefix: string,\n routes: Array<{ method: Method; path: string }>,\n ): void {\n const currentPath = prefix + (node.path ? \"/\" + node.path : \"\");\n\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n routes.push({ method: method as Method, path: currentPath || \"/\" });\n }\n }\n\n for (const key in node.children) {\n this.collectRoutes(node.children[key], currentPath, routes);\n }\n\n if (node.paramChild) {\n this.collectRoutes(node.paramChild, currentPath, routes);\n }\n\n if (node.wildcardChild) {\n this.collectRoutes(node.wildcardChild, currentPath, routes);\n }\n }\n}\n"],"mappings":"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"}