vafast 0.4.4 → 0.4.6

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.
Files changed (131) hide show
  1. package/dist/{base-server-DvGS6ATg.d.mts → base-server-CtA1bZSg.d.mts} +2 -2
  2. package/dist/{base-server-CSkyjEaY.mjs → base-server-DMhpmq5v.mjs} +1 -1
  3. package/dist/{base-server-CSkyjEaY.mjs.map → base-server-DMhpmq5v.mjs.map} +1 -1
  4. package/dist/{base64url-CwQnvZyp.mjs → base64url-DUtluDF0.mjs} +1 -1
  5. package/dist/{base64url-CwQnvZyp.mjs.map → base64url-DUtluDF0.mjs.map} +1 -1
  6. package/dist/{component-route-CZawYn61.d.mts → component-route-DF5feXJI.d.mts} +2 -2
  7. package/dist/{component-router-CErbGh2A.mjs → component-router-uSylkByf.mjs} +1 -1
  8. package/dist/{component-router-CErbGh2A.mjs.map → component-router-uSylkByf.mjs.map} +1 -1
  9. package/dist/{component-server-DAbIyIPI.mjs → component-server-DIgykV0F.mjs} +6 -6
  10. package/dist/{component-server-DAbIyIPI.mjs.map → component-server-DIgykV0F.mjs.map} +1 -1
  11. package/dist/{component-server-CGzU4bss.d.mts → component-server-DvcPVnL4.d.mts} +4 -4
  12. package/dist/{create-handler-Bo-hvWp-.d.mts → create-handler-DRcJRkx9.d.mts} +2 -2
  13. package/dist/{create-handler-B_pfxh3m.mjs → create-handler-IzOE24L5.mjs} +5 -5
  14. package/dist/{create-handler-B_pfxh3m.mjs.map → create-handler-IzOE24L5.mjs.map} +1 -1
  15. package/dist/defineRoute.d.mts +3 -3
  16. package/dist/{dependency-manager-Czg7Po2j.mjs → dependency-manager-BpN2YufZ.mjs} +1 -1
  17. package/dist/{dependency-manager-Czg7Po2j.mjs.map → dependency-manager-BpN2YufZ.mjs.map} +1 -1
  18. package/dist/{dependency-manager-C6vFWP2L.d.mts → dependency-manager-C_qZvkaw.d.mts} +1 -1
  19. package/dist/{go-await-BGAGJfrB.mjs → go-await-2Pzj4snS.mjs} +1 -1
  20. package/dist/{go-await-BGAGJfrB.mjs.map → go-await-2Pzj4snS.mjs.map} +1 -1
  21. package/dist/{handle-Csjtywdc.mjs → handle-s4V-E2RE.mjs} +2 -2
  22. package/dist/{handle-Csjtywdc.mjs.map → handle-s4V-E2RE.mjs.map} +1 -1
  23. package/dist/{html-renderer-CczE8mwC.mjs → html-renderer-CuakkPIt.mjs} +1 -1
  24. package/dist/{html-renderer-CczE8mwC.mjs.map → html-renderer-CuakkPIt.mjs.map} +1 -1
  25. package/dist/{index-Ci52vt55.d.mts → index-CdOYxwDQ.d.mts} +5 -5
  26. package/dist/index.d.mts +16 -16
  27. package/dist/index.mjs +20 -21
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/middleware/component-router.d.mts +1 -1
  30. package/dist/middleware/component-router.mjs +1 -1
  31. package/dist/middleware-5PjaxPMA.d.mts +23 -0
  32. package/dist/middleware-CV5o-4wk.mjs +189 -0
  33. package/dist/middleware-CV5o-4wk.mjs.map +1 -0
  34. package/dist/middleware.d.mts +4 -25
  35. package/dist/middleware.mjs +1 -1
  36. package/dist/monitoring/index.d.mts +6 -6
  37. package/dist/monitoring/index.mjs +5 -3
  38. package/dist/monitoring/index.mjs.map +1 -1
  39. package/dist/monitoring/native-monitor.d.mts +6 -6
  40. package/dist/monitoring/native-monitor.mjs +5 -3
  41. package/dist/monitoring/native-monitor.mjs.map +1 -1
  42. package/dist/node-server/index.mjs +3 -3
  43. package/dist/node-server/request.mjs +1 -1
  44. package/dist/node-server/response.mjs +1 -1
  45. package/dist/node-server/serve.mjs +2 -2
  46. package/dist/{parsers-CI_TZ7pO.mjs → parsers-BQ63b0YE.mjs} +1 -1
  47. package/dist/{parsers-CI_TZ7pO.mjs.map → parsers-BQ63b0YE.mjs.map} +1 -1
  48. package/dist/{path-matcher-73cJd5Y7.mjs → path-matcher-BNaaJgI3.mjs} +1 -1
  49. package/dist/{path-matcher-73cJd5Y7.mjs.map → path-matcher-BNaaJgI3.mjs.map} +1 -1
  50. package/dist/{radix-tree-D0XYaJKb.mjs → radix-tree-Qxr-QpCx.mjs} +1 -1
  51. package/dist/{radix-tree-D0XYaJKb.mjs.map → radix-tree-Qxr-QpCx.mjs.map} +1 -1
  52. package/dist/{request-CKC3Ox6M.mjs → request-B886yCvG.mjs} +1 -1
  53. package/dist/{request-CKC3Ox6M.mjs.map → request-B886yCvG.mjs.map} +1 -1
  54. package/dist/{request-validator-_J5HloRq.mjs → request-validator-DLFtm4uV.mjs} +3 -3
  55. package/dist/{request-validator-_J5HloRq.mjs.map → request-validator-DLFtm4uV.mjs.map} +1 -1
  56. package/dist/{response-Cf5FgtmE.mjs → response-30WnzABq.mjs} +1 -1
  57. package/dist/{response-Cf5FgtmE.mjs.map → response-30WnzABq.mjs.map} +1 -1
  58. package/dist/response-CxYf6Ep3.d.mts +48 -0
  59. package/dist/{route-9pAVP1GC.mjs → route-B3ONOzxQ.mjs} +1 -1
  60. package/dist/{route-9pAVP1GC.mjs.map → route-B3ONOzxQ.mjs.map} +1 -1
  61. package/dist/{route-BJ-40LNI.d.mts → route-CUbNpSwz.d.mts} +2 -2
  62. package/dist/{route-registry-mcTG0M-t.mjs → route-registry-BVvbghgH.mjs} +1 -1
  63. package/dist/{route-registry-mcTG0M-t.mjs.map → route-registry-BVvbghgH.mjs.map} +1 -1
  64. package/dist/{route-registry--tx1PNui.d.mts → route-registry-CYD7m6QP.d.mts} +2 -2
  65. package/dist/router/index.d.mts +2 -2
  66. package/dist/router/index.mjs +1 -1
  67. package/dist/router/radix-tree.d.mts +3 -3
  68. package/dist/router/radix-tree.mjs +1 -1
  69. package/dist/router.d.mts +3 -3
  70. package/dist/{schema-CPQudJpE.d.mts → schema-DOKg31ZX.d.mts} +1 -1
  71. package/dist/{serve-Be6NvuQk.mjs → serve-DgWBnexE.mjs} +3 -3
  72. package/dist/{serve-Be6NvuQk.mjs.map → serve-DgWBnexE.mjs.map} +1 -1
  73. package/dist/serve.mjs +2 -2
  74. package/dist/server/base-server.d.mts +3 -3
  75. package/dist/server/base-server.mjs +1 -1
  76. package/dist/server/component-server.d.mts +4 -4
  77. package/dist/server/component-server.mjs +2 -2
  78. package/dist/server/index.d.mts +6 -6
  79. package/dist/server/index.mjs +6 -5
  80. package/dist/server/server-factory.d.mts +6 -6
  81. package/dist/server/server-factory.mjs +5 -3
  82. package/dist/server/server.d.mts +4 -4
  83. package/dist/server/server.mjs +2 -1
  84. package/dist/{server-Cbd3Ia51.mjs → server-BttM6Ssc.mjs} +4 -4
  85. package/dist/{server-Cbd3Ia51.mjs.map → server-BttM6Ssc.mjs.map} +1 -1
  86. package/dist/{server-BmPKs8oM.mjs → server-C3yoZXNs.mjs} +5 -6
  87. package/dist/{server-BmPKs8oM.mjs.map → server-C3yoZXNs.mjs.map} +1 -1
  88. package/dist/{server-D9gjszHe.d.mts → server-CWIZP6nb.d.mts} +3 -3
  89. package/dist/{sse-BMM6KTfy.d.mts → sse-BDIptC85.d.mts} +2 -2
  90. package/dist/{sse-BT5yyLgX.mjs → sse-CCVfFW6s.mjs} +3 -3
  91. package/dist/{sse-BT5yyLgX.mjs.map → sse-CCVfFW6s.mjs.map} +1 -1
  92. package/dist/types/component-route.d.mts +1 -1
  93. package/dist/types/index.d.mts +5 -5
  94. package/dist/types/index.mjs +1 -1
  95. package/dist/types/route.d.mts +1 -1
  96. package/dist/types/route.mjs +1 -1
  97. package/dist/types/schema.d.mts +1 -1
  98. package/dist/types/types.d.mts +1 -1
  99. package/dist/{types-DuTa8AVN.d.mts → types-mpeSaHdI.d.mts} +1 -1
  100. package/dist/utils/base64url.mjs +1 -1
  101. package/dist/utils/create-handler.d.mts +2 -2
  102. package/dist/utils/create-handler.mjs +4 -3
  103. package/dist/utils/dependency-manager.d.mts +1 -1
  104. package/dist/utils/dependency-manager.mjs +1 -1
  105. package/dist/utils/go-await.mjs +1 -1
  106. package/dist/utils/handle.mjs +2 -2
  107. package/dist/utils/html-renderer.mjs +1 -1
  108. package/dist/utils/index.d.mts +9 -8
  109. package/dist/utils/index.mjs +13 -13
  110. package/dist/utils/index.mjs.map +1 -1
  111. package/dist/utils/parsers.mjs +1 -1
  112. package/dist/utils/path-matcher.mjs +1 -1
  113. package/dist/utils/request-validator.mjs +3 -3
  114. package/dist/utils/response.d.mts +5 -2
  115. package/dist/utils/response.mjs +2 -2
  116. package/dist/utils/route-registry.d.mts +3 -3
  117. package/dist/utils/route-registry.mjs +1 -1
  118. package/dist/utils/sse.d.mts +2 -2
  119. package/dist/utils/sse.mjs +3 -3
  120. package/dist/utils/validators/validators.mjs +1 -1
  121. package/dist/{validators-BBrGePBr.mjs → validators-WXQ49LcR.mjs} +1 -1
  122. package/dist/{validators-BBrGePBr.mjs.map → validators-WXQ49LcR.mjs.map} +1 -1
  123. package/package.json +1 -1
  124. package/dist/middleware-Byp3Hjae.mjs +0 -59
  125. package/dist/middleware-Byp3Hjae.mjs.map +0 -1
  126. package/dist/response-A-sZZiJ7.d.mts +0 -21
  127. package/dist/response-DXg4i_yh.mjs +0 -97
  128. package/dist/response-DXg4i_yh.mjs.map +0 -1
  129. /package/dist/{component-route-CYxLOnci.mjs → component-route-BKUFoJ5P.mjs} +0 -0
  130. /package/dist/{index-CzItj62a.d.mts → index-CTHojwxd.d.mts} +0 -0
  131. /package/dist/{schema-CtVBNfnQ.mjs → schema-CflsMJuG.mjs} +0 -0
@@ -0,0 +1,23 @@
1
+ import { o as Middleware, r as Handler } from "./types-mpeSaHdI.mjs";
2
+
3
+ //#region src/middleware.d.ts
4
+ /** 中间件类型:使用 next() 传递给下一个处理 */
5
+ /** Vafast 自定义错误类型 */
6
+ declare class VafastError extends Error {
7
+ status: number;
8
+ type: string;
9
+ expose: boolean;
10
+ constructor(message: string, options?: {
11
+ status?: number;
12
+ type?: string;
13
+ expose?: boolean;
14
+ cause?: unknown;
15
+ });
16
+ }
17
+ /**
18
+ * 组合类型: 自动注入错误处理器进行中间件组合
19
+ */
20
+ declare function composeMiddleware(middleware: Middleware[], finalHandler: Handler): (req: Request) => Promise<Response>;
21
+ //#endregion
22
+ export { composeMiddleware as n, VafastError as t };
23
+ //# sourceMappingURL=middleware-5PjaxPMA.d.mts.map
@@ -0,0 +1,189 @@
1
+ import { t as __esmMin } from "./chunk-DW4-Jl94.mjs";
2
+
3
+ //#region src/utils/response.ts
4
+ /** 生成 JSON 响应 */
5
+ function json(data, status = 200, headers = {}) {
6
+ const body = JSON.stringify(data);
7
+ if (Object.keys(headers).length === 0) return new Response(body, {
8
+ status,
9
+ headers: { "Content-Type": "application/json" }
10
+ });
11
+ const h = new Headers({
12
+ "Content-Type": "application/json",
13
+ ...headers
14
+ });
15
+ return new Response(body, {
16
+ status,
17
+ headers: h
18
+ });
19
+ }
20
+ /**
21
+ * 类型特化的响应映射
22
+ * 根据返回值类型直接生成 Response,避免不必要的检查
23
+ */
24
+ function mapResponse(response) {
25
+ if (response instanceof Response) return response;
26
+ switch (response?.constructor?.name) {
27
+ case "String": return new Response(response, { headers: TEXT_HEADERS });
28
+ case "Object":
29
+ case "Array": return new Response(JSON.stringify(response), { headers: JSON_HEADERS });
30
+ case "Number":
31
+ case "Boolean": return new Response(String(response), { headers: TEXT_HEADERS });
32
+ case void 0: return new Response(null, { status: 204 });
33
+ case "ReadableStream": return new Response(response);
34
+ case "Blob": return new Response(response);
35
+ case "ArrayBuffer": return new Response(response);
36
+ case "Uint8Array": return new Response(response);
37
+ default:
38
+ if (response instanceof Promise) return response.then(mapResponse);
39
+ return new Response(JSON.stringify(response), { headers: JSON_HEADERS });
40
+ }
41
+ }
42
+ /** 生成重定向响应 */
43
+ function redirect(location, status = 302) {
44
+ return new Response(null, {
45
+ status,
46
+ headers: { Location: location }
47
+ });
48
+ }
49
+ /** 生成纯文本响应 */
50
+ function text(content, status = 200, headers = {}) {
51
+ const h = new Headers({
52
+ "Content-Type": "text/plain; charset=utf-8",
53
+ ...headers
54
+ });
55
+ return new Response(content, {
56
+ status,
57
+ headers: h
58
+ });
59
+ }
60
+ /** 生成HTML响应 */
61
+ function html(content, status = 200, headers = {}) {
62
+ const h = new Headers({
63
+ "Content-Type": "text/html; charset=utf-8",
64
+ ...headers
65
+ });
66
+ return new Response(content, {
67
+ status,
68
+ headers: h
69
+ });
70
+ }
71
+ /** 生成空响应(204 No Content) */
72
+ function empty(status = 204, headers = {}) {
73
+ return new Response(null, {
74
+ status,
75
+ headers
76
+ });
77
+ }
78
+ /** 生成流式响应 */
79
+ function stream(stream$1, status = 200, headers = {}) {
80
+ const h = new Headers({
81
+ "Content-Type": "application/octet-stream",
82
+ ...headers
83
+ });
84
+ return new Response(stream$1, {
85
+ status,
86
+ headers: h
87
+ });
88
+ }
89
+ /**
90
+ * 创建错误响应
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * // 自定义错误
95
+ * throw err('用户不存在', 404, 'NOT_FOUND')
96
+ *
97
+ * // 预定义错误
98
+ * throw err.notFound('用户不存在')
99
+ * throw err.badRequest('参数错误')
100
+ * throw err.unauthorized('请先登录')
101
+ * ```
102
+ */
103
+ function err(message, status = 500, type = "ERROR") {
104
+ return new VafastError(message, {
105
+ status,
106
+ type,
107
+ expose: true
108
+ });
109
+ }
110
+ var JSON_HEADERS, TEXT_HEADERS;
111
+ var init_response = __esmMin((() => {
112
+ init_middleware();
113
+ JSON_HEADERS = { "Content-Type": "application/json" };
114
+ TEXT_HEADERS = { "Content-Type": "text/plain" };
115
+ /** 400 Bad Request */
116
+ err.badRequest = (message = "请求参数错误") => err(message, 400, "BAD_REQUEST");
117
+ /** 401 Unauthorized */
118
+ err.unauthorized = (message = "未授权") => err(message, 401, "UNAUTHORIZED");
119
+ /** 403 Forbidden */
120
+ err.forbidden = (message = "禁止访问") => err(message, 403, "FORBIDDEN");
121
+ /** 404 Not Found */
122
+ err.notFound = (message = "资源不存在") => err(message, 404, "NOT_FOUND");
123
+ /** 409 Conflict */
124
+ err.conflict = (message = "资源冲突") => err(message, 409, "CONFLICT");
125
+ /** 422 Unprocessable Entity */
126
+ err.unprocessable = (message = "无法处理的实体") => err(message, 422, "UNPROCESSABLE_ENTITY");
127
+ /** 429 Too Many Requests */
128
+ err.tooMany = (message = "请求过于频繁") => err(message, 429, "TOO_MANY_REQUESTS");
129
+ /** 500 Internal Server Error */
130
+ err.internal = (message = "服务器内部错误") => err(message, 500, "INTERNAL_ERROR");
131
+ }));
132
+
133
+ //#endregion
134
+ //#region src/middleware.ts
135
+ /**
136
+ * 组合类型: 自动注入错误处理器进行中间件组合
137
+ */
138
+ function composeMiddleware(middleware, finalHandler) {
139
+ const all = [errorHandler, ...middleware];
140
+ return function composedHandler(req) {
141
+ let i = -1;
142
+ const dispatch = (index) => {
143
+ if (index <= i) return Promise.reject(/* @__PURE__ */ new Error("next() called multiple times"));
144
+ i = index;
145
+ if (index < all.length) {
146
+ const mw = all[index];
147
+ return Promise.resolve(mw(req, () => dispatch(index + 1)));
148
+ }
149
+ return Promise.resolve(finalHandler(req)).then(mapResponse);
150
+ };
151
+ return dispatch(0);
152
+ };
153
+ }
154
+ var VafastError, errorHandler;
155
+ var init_middleware = __esmMin((() => {
156
+ init_response();
157
+ VafastError = class extends Error {
158
+ status;
159
+ type;
160
+ expose;
161
+ constructor(message, options = {}) {
162
+ super(message);
163
+ this.name = "VafastError";
164
+ this.status = options.status ?? 500;
165
+ this.type = options.type ?? "internal_error";
166
+ this.expose = options.expose ?? false;
167
+ if (options.cause) this.cause = options.cause;
168
+ }
169
+ };
170
+ errorHandler = async (req, next) => {
171
+ try {
172
+ return await next();
173
+ } catch (err$1) {
174
+ console.error("未处理的错误:", err$1);
175
+ if (err$1 instanceof VafastError) return json({
176
+ error: err$1.type,
177
+ message: err$1.expose ? err$1.message : "发生了一个错误"
178
+ }, err$1.status);
179
+ return json({
180
+ error: "internal_error",
181
+ message: "出现了一些问题"
182
+ }, 500);
183
+ }
184
+ };
185
+ }));
186
+
187
+ //#endregion
188
+ export { err as a, json as c, stream as d, text as f, empty as i, mapResponse as l, composeMiddleware as n, html as o, init_middleware as r, init_response as s, VafastError as t, redirect as u };
189
+ //# sourceMappingURL=middleware-CV5o-4wk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-CV5o-4wk.mjs","names":["stream","err"],"sources":["../src/utils/response.ts","../src/middleware.ts"],"sourcesContent":["// src/response.ts\n\nimport { VafastError } from \"../middleware\";\n\n/** 生成 JSON 响应 */\nexport function json(\n data: unknown,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const body = JSON.stringify(data);\n\n // 优化:只在有自定义 headers 时才创建 Headers 对象\n if (Object.keys(headers).length === 0) {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // 有自定义 headers 时才创建 Headers 对象\n const h = new Headers({\n \"Content-Type\": \"application/json\",\n ...headers,\n });\n\n return new Response(body, {\n status,\n headers: h,\n });\n}\n\n// JSON 响应的预创建 headers(避免每次创建)\nconst JSON_HEADERS = { \"Content-Type\": \"application/json\" };\nconst TEXT_HEADERS = { \"Content-Type\": \"text/plain\" };\n\n/**\n * 类型特化的响应映射\n * 根据返回值类型直接生成 Response,避免不必要的检查\n */\nexport function mapResponse(response: unknown): Response {\n // 快速路径:已经是 Response\n if (response instanceof Response) return response;\n\n // 使用 constructor.name 进行类型判断(比 instanceof 更快)\n switch (response?.constructor?.name) {\n case \"String\":\n return new Response(response as string, { headers: TEXT_HEADERS });\n\n case \"Object\":\n case \"Array\":\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n\n case \"Number\":\n case \"Boolean\":\n return new Response(String(response), { headers: TEXT_HEADERS });\n\n case undefined:\n // null 或 undefined\n return new Response(null, { status: 204 });\n\n case \"ReadableStream\":\n return new Response(response as ReadableStream);\n\n case \"Blob\":\n return new Response(response as Blob);\n\n case \"ArrayBuffer\":\n return new Response(response as ArrayBuffer);\n\n case \"Uint8Array\":\n return new Response(response as unknown as BodyInit);\n\n default:\n // Promise 处理\n if (response instanceof Promise) {\n return response.then(mapResponse) as unknown as Response;\n }\n // 其他情况使用 JSON 序列化\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n }\n}\n\n/** 生成重定向响应 */\nexport function redirect(location: string, status: 301 | 302 = 302): Response {\n return new Response(null, {\n status,\n headers: {\n Location: location,\n },\n });\n}\n\n/** 生成纯文本响应 */\nexport function text(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成HTML响应 */\nexport function html(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成空响应(204 No Content) */\nexport function empty(status = 204, headers: HeadersInit = {}): Response {\n return new Response(null, {\n status,\n headers,\n });\n}\n\n/** 生成流式响应 */\nexport function stream(\n stream: ReadableStream,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"application/octet-stream\",\n ...headers,\n });\n\n return new Response(stream, {\n status,\n headers: h,\n });\n}\n\n// ==================== 错误响应工具 ====================\n\n/**\n * 创建错误响应\n *\n * @example\n * ```typescript\n * // 自定义错误\n * throw err('用户不存在', 404, 'NOT_FOUND')\n *\n * // 预定义错误\n * throw err.notFound('用户不存在')\n * throw err.badRequest('参数错误')\n * throw err.unauthorized('请先登录')\n * ```\n */\nexport function err(message: string, status = 500, type = \"ERROR\") {\n return new VafastError(message, { status, type, expose: true });\n}\n\n/** 400 Bad Request */\nerr.badRequest = (message = \"请求参数错误\") =>\n err(message, 400, \"BAD_REQUEST\");\n\n/** 401 Unauthorized */\nerr.unauthorized = (message = \"未授权\") =>\n err(message, 401, \"UNAUTHORIZED\");\n\n/** 403 Forbidden */\nerr.forbidden = (message = \"禁止访问\") =>\n err(message, 403, \"FORBIDDEN\");\n\n/** 404 Not Found */\nerr.notFound = (message = \"资源不存在\") =>\n err(message, 404, \"NOT_FOUND\");\n\n/** 409 Conflict */\nerr.conflict = (message = \"资源冲突\") =>\n err(message, 409, \"CONFLICT\");\n\n/** 422 Unprocessable Entity */\nerr.unprocessable = (message = \"无法处理的实体\") =>\n err(message, 422, \"UNPROCESSABLE_ENTITY\");\n\n/** 429 Too Many Requests */\nerr.tooMany = (message = \"请求过于频繁\") =>\n err(message, 429, \"TOO_MANY_REQUESTS\");\n\n/** 500 Internal Server Error */\nerr.internal = (message = \"服务器内部错误\") =>\n err(message, 500, \"INTERNAL_ERROR\");\n","// src/middleware.ts\n\nimport { json, mapResponse } from \"./utils/response\";\n\nimport type { Handler, Middleware } from \"./types\";\n/** 中间件类型:使用 next() 传递给下一个处理 */\n\n/** Vafast 自定义错误类型 */\nexport class VafastError extends Error {\n status: number;\n type: string;\n expose: boolean;\n\n constructor(\n message: string,\n options: {\n status?: number;\n type?: string;\n expose?: boolean;\n cause?: unknown;\n } = {},\n ) {\n super(message);\n this.name = \"VafastError\";\n this.status = options.status ?? 500;\n this.type = options.type ?? \"internal_error\";\n this.expose = options.expose ?? false;\n if (options.cause) (this as any).cause = options.cause;\n }\n}\n\n/**\n * 组合类型: 自动注入错误处理器进行中间件组合\n */\nexport function composeMiddleware(\n middleware: Middleware[],\n finalHandler: Handler,\n): (req: Request) => Promise<Response> {\n const all = [errorHandler, ...middleware];\n\n return function composedHandler(req: Request): Promise<Response> {\n let i = -1;\n\n const dispatch = (index: number): Promise<Response> => {\n if (index <= i)\n return Promise.reject(new Error(\"next() called multiple times\"));\n i = index;\n\n // 中间件阶段\n if (index < all.length) {\n const mw = all[index];\n return Promise.resolve(mw(req, () => dispatch(index + 1)));\n }\n\n // 最终 handler - 使用 mapResponse 转换返回值\n return Promise.resolve(finalHandler(req)).then(mapResponse);\n };\n\n return dispatch(0);\n };\n}\n\n/** 默认包含的全局错误处理器 */\nconst errorHandler: Middleware = async (req, next) => {\n try {\n return await next();\n } catch (err) {\n console.error(\"未处理的错误:\", err);\n\n if (err instanceof VafastError) {\n return json(\n {\n error: err.type,\n message: err.expose ? err.message : \"发生了一个错误\",\n },\n err.status,\n );\n }\n\n return json({ error: \"internal_error\", message: \"出现了一些问题\" }, 500);\n }\n};\n"],"mappings":"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"}
@@ -1,25 +1,4 @@
1
- import { o as Middleware, r as Handler } from "./types-DuTa8AVN.mjs";
2
- import "./schema-CPQudJpE.mjs";
3
- import "./index-CzItj62a.mjs";
4
-
5
- //#region src/middleware.d.ts
6
- /** 中间件类型:使用 next() 传递给下一个处理 */
7
- /** Vafast 自定义错误类型 */
8
- declare class VafastError extends Error {
9
- status: number;
10
- type: string;
11
- expose: boolean;
12
- constructor(message: string, options?: {
13
- status?: number;
14
- type?: string;
15
- expose?: boolean;
16
- cause?: unknown;
17
- });
18
- }
19
- /**
20
- * 组合类型: 自动注入错误处理器进行中间件组合
21
- */
22
- declare function composeMiddleware(middleware: Middleware[], finalHandler: Handler): (req: Request) => Promise<Response>;
23
- //#endregion
24
- export { VafastError, composeMiddleware };
25
- //# sourceMappingURL=middleware.d.mts.map
1
+ import "./schema-DOKg31ZX.mjs";
2
+ import "./index-CTHojwxd.mjs";
3
+ import { n as composeMiddleware, t as VafastError } from "./middleware-5PjaxPMA.mjs";
4
+ export { VafastError, composeMiddleware };
@@ -1,4 +1,4 @@
1
- import { n as composeMiddleware, r as init_middleware, t as VafastError } from "./middleware-Byp3Hjae.mjs";
1
+ import { n as composeMiddleware, r as init_middleware, t as VafastError } from "./middleware-CV5o-4wk.mjs";
2
2
 
3
3
  init_middleware();
4
4
  export { VafastError, composeMiddleware };
@@ -1,9 +1,9 @@
1
- import "../schema-CPQudJpE.mjs";
2
- import "../index-CzItj62a.mjs";
3
- import "../base-server-DvGS6ATg.mjs";
4
- import "../server-D9gjszHe.mjs";
5
- import "../component-server-CGzU4bss.mjs";
6
- import "../index-Ci52vt55.mjs";
1
+ import "../schema-DOKg31ZX.mjs";
2
+ import "../index-CTHojwxd.mjs";
3
+ import "../base-server-CtA1bZSg.mjs";
4
+ import "../server-CWIZP6nb.mjs";
5
+ import "../component-server-DvcPVnL4.mjs";
6
+ import "../index-CdOYxwDQ.mjs";
7
7
  import { AggregatedMetrics, BaseMetrics, MonitoringConfig, MonitoringEvent, PerformanceMetrics, PerformanceReport } from "./types.mjs";
8
8
  import { MonitoredServer, NativeMonitoringConfig, NativeMonitoringMetrics, createMonitoredServer, withMonitoring } from "./native-monitor.mjs";
9
9
 
@@ -1,6 +1,8 @@
1
- import "../dependency-manager-Czg7Po2j.mjs";
2
- import "../component-server-DAbIyIPI.mjs";
3
- import "../server-Cbd3Ia51.mjs";
1
+ import "../middleware-CV5o-4wk.mjs";
2
+ import "../server-C3yoZXNs.mjs";
3
+ import "../dependency-manager-BpN2YufZ.mjs";
4
+ import "../component-server-DIgykV0F.mjs";
5
+ import "../server-BttM6Ssc.mjs";
4
6
  import "./types.mjs";
5
7
  import { createMonitoredServer, withMonitoring } from "./native-monitor.mjs";
6
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/monitoring/index.ts"],"sourcesContent":["/**\n * 原生监控系统入口\n *\n * @author Framework Team\n * @version 2.0.0\n * @license MIT\n */\n\nexport * from \"./types\";\nexport * from \"./native-monitor\";\n\n// 默认监控配置\nexport const defaultMonitoringConfig = {\n enabled: true,\n console: true,\n slowThreshold: 1000, // 1秒\n errorThreshold: 0.05, // 5%\n tags: {\n framework: \"vafast\",\n version: \"2.0.0\",\n },\n};\n\n// 创建监控配置\nexport function createMonitoringConfig(\n config: Partial<typeof defaultMonitoringConfig> = {},\n) {\n return { ...defaultMonitoringConfig, ...config };\n}\n"],"mappings":";;;;;;;AAYA,MAAa,0BAA0B;CACrC,SAAS;CACT,SAAS;CACT,eAAe;CACf,gBAAgB;CAChB,MAAM;EACJ,WAAW;EACX,SAAS;EACV;CACF;AAGD,SAAgB,uBACd,SAAkD,EAAE,EACpD;AACA,QAAO;EAAE,GAAG;EAAyB,GAAG;EAAQ"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/monitoring/index.ts"],"sourcesContent":["/**\n * 原生监控系统入口\n *\n * @author Framework Team\n * @version 2.0.0\n * @license MIT\n */\n\nexport * from \"./types\";\nexport * from \"./native-monitor\";\n\n// 默认监控配置\nexport const defaultMonitoringConfig = {\n enabled: true,\n console: true,\n slowThreshold: 1000, // 1秒\n errorThreshold: 0.05, // 5%\n tags: {\n framework: \"vafast\",\n version: \"2.0.0\",\n },\n};\n\n// 创建监控配置\nexport function createMonitoringConfig(\n config: Partial<typeof defaultMonitoringConfig> = {},\n) {\n return { ...defaultMonitoringConfig, ...config };\n}\n"],"mappings":";;;;;;;;;AAYA,MAAa,0BAA0B;CACrC,SAAS;CACT,SAAS;CACT,eAAe;CACf,gBAAgB;CAChB,MAAM;EACJ,WAAW;EACX,SAAS;EACV;CACF;AAGD,SAAgB,uBACd,SAAkD,EAAE,EACpD;AACA,QAAO;EAAE,GAAG;EAAyB,GAAG;EAAQ"}
@@ -1,9 +1,9 @@
1
- import "../schema-CPQudJpE.mjs";
2
- import "../index-CzItj62a.mjs";
3
- import "../base-server-DvGS6ATg.mjs";
4
- import { t as Server } from "../server-D9gjszHe.mjs";
5
- import "../component-server-CGzU4bss.mjs";
6
- import "../index-Ci52vt55.mjs";
1
+ import "../schema-DOKg31ZX.mjs";
2
+ import "../index-CTHojwxd.mjs";
3
+ import "../base-server-CtA1bZSg.mjs";
4
+ import { t as Server } from "../server-CWIZP6nb.mjs";
5
+ import "../component-server-DvcPVnL4.mjs";
6
+ import "../index-CdOYxwDQ.mjs";
7
7
 
8
8
  //#region src/monitoring/native-monitor.d.ts
9
9
  /**
@@ -1,7 +1,9 @@
1
1
  import { r as __toCommonJS } from "../chunk-DW4-Jl94.mjs";
2
- import "../dependency-manager-Czg7Po2j.mjs";
3
- import "../component-server-DAbIyIPI.mjs";
4
- import { n as server_exports, t as init_server } from "../server-Cbd3Ia51.mjs";
2
+ import "../middleware-CV5o-4wk.mjs";
3
+ import "../server-C3yoZXNs.mjs";
4
+ import "../dependency-manager-BpN2YufZ.mjs";
5
+ import "../component-server-DIgykV0F.mjs";
6
+ import { n as server_exports, t as init_server } from "../server-BttM6Ssc.mjs";
5
7
 
6
8
  //#region src/monitoring/native-monitor.ts
7
9
  var NativeMonitor = class {
@@ -1 +1 @@
1
- {"version":3,"file":"native-monitor.mjs","names":[],"sources":["../../src/monitoring/native-monitor.ts"],"sourcesContent":["/**\n * 原生监控装饰器\n *\n * 通过装饰器模式为 Server 添加监控能力,完全不入侵原类\n *\n * @author Framework Team\n * @version 2.0.0\n * @license MIT\n */\n\nimport type { Server } from \"../server\";\n\n// 监控配置接口\nexport interface NativeMonitoringConfig {\n enabled?: boolean;\n console?: boolean;\n slowThreshold?: number; // 毫秒\n errorThreshold?: number;\n tags?: Record<string, string>;\n}\n\n// 监控指标接口\nexport interface NativeMonitoringMetrics {\n requestId: string;\n method: string;\n path: string;\n statusCode: number;\n totalTime: number;\n timestamp: number;\n memoryUsage: {\n heapUsed: number;\n heapTotal: number;\n };\n}\n\n// 带监控的 Server 接口\nexport interface MonitoredServer extends Server {\n // 监控相关方法\n getMonitoringStatus(): any;\n getMonitoringMetrics(): NativeMonitoringMetrics[];\n resetMonitoring(): void;\n\n // 原始方法保持不变\n fetch: (req: Request) => Promise<Response>;\n use: (mw: any) => void;\n}\n\n// 原生监控器\nclass NativeMonitor {\n private config: NativeMonitoringConfig;\n private metrics: NativeMonitoringMetrics[] = [];\n private isEnabled = false;\n\n constructor(config: NativeMonitoringConfig = {}) {\n this.config = {\n enabled: true,\n console: true,\n slowThreshold: 1000,\n errorThreshold: 0.05,\n tags: { framework: \"vafast\" },\n ...config,\n };\n\n this.isEnabled = this.config.enabled ?? true;\n\n if (this.isEnabled && this.config.console) {\n console.log(\"✅ 原生监控已启用\");\n console.log(`📊 监控配置:`, {\n 慢请求阈值: `${this.config.slowThreshold}ms`,\n 错误率阈值: `${(this.config.errorThreshold! * 100).toFixed(1)}%`,\n 标签: this.config.tags,\n });\n }\n }\n\n // 记录监控指标\n recordMetrics(metrics: NativeMonitoringMetrics): void {\n if (!this.isEnabled) return;\n\n this.metrics.push(metrics);\n\n // 保持最近1000条记录\n if (this.metrics.length > 1000) {\n this.metrics = this.metrics.slice(-1000);\n }\n\n // 控制台输出\n if (this.config.console) {\n const status = metrics.statusCode < 400 ? \"✅\" : \"❌\";\n const timeColor =\n metrics.totalTime > this.config.slowThreshold! ? \"🐌\" : \"⚡\";\n\n console.log(\n `${status} ${metrics.method} ${metrics.path} - ${\n metrics.statusCode\n } (${timeColor} ${metrics.totalTime.toFixed(2)}ms)`,\n );\n\n // 慢请求警告\n if (metrics.totalTime > this.config.slowThreshold!) {\n console.warn(\n `🐌 慢请求警告: ${metrics.path} 耗时 ${metrics.totalTime.toFixed(\n 2,\n )}ms`,\n );\n }\n }\n }\n\n // 获取监控状态\n getStatus() {\n if (!this.isEnabled) {\n return { enabled: false, message: \"监控未启用\" };\n }\n\n const totalRequests = this.metrics.length;\n const successfulRequests = this.metrics.filter(\n (m) => m.statusCode < 400,\n ).length;\n const failedRequests = totalRequests - successfulRequests;\n const avgResponseTime =\n totalRequests > 0\n ? this.metrics.reduce((sum, m) => sum + m.totalTime, 0) / totalRequests\n : 0;\n\n return {\n enabled: true,\n totalRequests,\n successfulRequests,\n failedRequests,\n errorRate: totalRequests > 0 ? failedRequests / totalRequests : 0,\n avgResponseTime: avgResponseTime.toFixed(2) + \"ms\",\n memoryUsage: this.getMemoryUsage(),\n recentRequests: this.metrics.slice(-5),\n };\n }\n\n // 获取监控指标\n getMetrics() {\n return this.metrics;\n }\n\n // 重置监控数据\n reset() {\n this.metrics = [];\n console.log(\"🔄 监控数据已重置\");\n }\n\n // 获取内存使用情况\n private getMemoryUsage() {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: (mem.heapUsed / 1024 / 1024).toFixed(2) + \"MB\",\n heapTotal: (mem.heapTotal / 1024 / 1024).toFixed(2) + \"MB\",\n external: (mem.external / 1024 / 1024).toFixed(2) + \"MB\",\n };\n }\n return { message: \"内存信息不可用\" };\n }\n}\n\n// 纯函数:为 Server 添加监控能力\nexport function withMonitoring(\n server: Server,\n config: NativeMonitoringConfig = {},\n): MonitoredServer {\n const monitor = new NativeMonitor(config);\n\n // 保存原始的 fetch 方法\n const originalFetch = server.fetch.bind(server);\n\n // 创建带监控的 fetch 方法\n const monitoredFetch = async (req: Request): Promise<Response> => {\n const startTime = performance.now();\n const requestId = `req_${Date.now()}_${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const { pathname } = new URL(req.url);\n const method = req.method;\n\n try {\n // 调用原始 fetch\n const response = await originalFetch(req);\n\n // 记录监控指标\n const totalTime = performance.now() - startTime;\n monitor.recordMetrics({\n requestId,\n method,\n path: pathname,\n statusCode: response.status,\n totalTime,\n timestamp: Date.now(),\n memoryUsage: (() => {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n };\n }\n return { heapUsed: 0, heapTotal: 0 };\n })(),\n });\n\n return response;\n } catch (error) {\n // 记录错误监控指标\n const totalTime = performance.now() - startTime;\n monitor.recordMetrics({\n requestId,\n method,\n path: pathname,\n statusCode: 500,\n totalTime,\n timestamp: Date.now(),\n memoryUsage: (() => {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n };\n }\n return { heapUsed: 0, heapTotal: 0 };\n })(),\n });\n\n throw error;\n }\n };\n\n // 创建带监控的 Server 对象\n const monitoredServer = {\n ...server,\n fetch: monitoredFetch,\n\n // 监控方法\n getMonitoringStatus: () => monitor.getStatus(),\n getMonitoringMetrics: () => monitor.getMetrics(),\n resetMonitoring: () => monitor.reset(),\n } as MonitoredServer;\n\n return monitoredServer;\n}\n\n// 便捷函数:创建带监控的 Server\nexport function createMonitoredServer(\n routes: any[],\n config?: NativeMonitoringConfig,\n): MonitoredServer {\n const { Server } = require(\"../server\");\n const server = new Server(routes);\n return withMonitoring(server, config);\n}\n"],"mappings":";;;;;;AAgDA,IAAM,gBAAN,MAAoB;CAClB,AAAQ;CACR,AAAQ,UAAqC,EAAE;CAC/C,AAAQ,YAAY;CAEpB,YAAY,SAAiC,EAAE,EAAE;AAC/C,OAAK,SAAS;GACZ,SAAS;GACT,SAAS;GACT,eAAe;GACf,gBAAgB;GAChB,MAAM,EAAE,WAAW,UAAU;GAC7B,GAAG;GACJ;AAED,OAAK,YAAY,KAAK,OAAO,WAAW;AAExC,MAAI,KAAK,aAAa,KAAK,OAAO,SAAS;AACzC,WAAQ,IAAI,YAAY;AACxB,WAAQ,IAAI,YAAY;IACtB,OAAO,GAAG,KAAK,OAAO,cAAc;IACpC,OAAO,IAAI,KAAK,OAAO,iBAAkB,KAAK,QAAQ,EAAE,CAAC;IACzD,IAAI,KAAK,OAAO;IACjB,CAAC;;;CAKN,cAAc,SAAwC;AACpD,MAAI,CAAC,KAAK,UAAW;AAErB,OAAK,QAAQ,KAAK,QAAQ;AAG1B,MAAI,KAAK,QAAQ,SAAS,IACxB,MAAK,UAAU,KAAK,QAAQ,MAAM,KAAM;AAI1C,MAAI,KAAK,OAAO,SAAS;GACvB,MAAM,SAAS,QAAQ,aAAa,MAAM,MAAM;GAChD,MAAM,YACJ,QAAQ,YAAY,KAAK,OAAO,gBAAiB,OAAO;AAE1D,WAAQ,IACN,GAAG,OAAO,GAAG,QAAQ,OAAO,GAAG,QAAQ,KAAK,KAC1C,QAAQ,WACT,IAAI,UAAU,GAAG,QAAQ,UAAU,QAAQ,EAAE,CAAC,KAChD;AAGD,OAAI,QAAQ,YAAY,KAAK,OAAO,cAClC,SAAQ,KACN,aAAa,QAAQ,KAAK,MAAM,QAAQ,UAAU,QAChD,EACD,CAAC,IACH;;;CAMP,YAAY;AACV,MAAI,CAAC,KAAK,UACR,QAAO;GAAE,SAAS;GAAO,SAAS;GAAS;EAG7C,MAAM,gBAAgB,KAAK,QAAQ;EACnC,MAAM,qBAAqB,KAAK,QAAQ,QACrC,MAAM,EAAE,aAAa,IACvB,CAAC;EACF,MAAM,iBAAiB,gBAAgB;EACvC,MAAM,kBACJ,gBAAgB,IACZ,KAAK,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,WAAW,EAAE,GAAG,gBACxD;AAEN,SAAO;GACL,SAAS;GACT;GACA;GACA;GACA,WAAW,gBAAgB,IAAI,iBAAiB,gBAAgB;GAChE,iBAAiB,gBAAgB,QAAQ,EAAE,GAAG;GAC9C,aAAa,KAAK,gBAAgB;GAClC,gBAAgB,KAAK,QAAQ,MAAM,GAAG;GACvC;;CAIH,aAAa;AACX,SAAO,KAAK;;CAId,QAAQ;AACN,OAAK,UAAU,EAAE;AACjB,UAAQ,IAAI,aAAa;;CAI3B,AAAQ,iBAAiB;AACvB,MAAI,OAAO,YAAY,eAAe,QAAQ,aAAa;GACzD,MAAM,MAAM,QAAQ,aAAa;AACjC,UAAO;IACL,WAAW,IAAI,WAAW,OAAO,MAAM,QAAQ,EAAE,GAAG;IACpD,YAAY,IAAI,YAAY,OAAO,MAAM,QAAQ,EAAE,GAAG;IACtD,WAAW,IAAI,WAAW,OAAO,MAAM,QAAQ,EAAE,GAAG;IACrD;;AAEH,SAAO,EAAE,SAAS,WAAW;;;AAKjC,SAAgB,eACd,QACA,SAAiC,EAAE,EAClB;CACjB,MAAM,UAAU,IAAI,cAAc,OAAO;CAGzC,MAAM,gBAAgB,OAAO,MAAM,KAAK,OAAO;CAG/C,MAAM,iBAAiB,OAAO,QAAoC;EAChE,MAAM,YAAY,YAAY,KAAK;EACnC,MAAM,YAAY,OAAO,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CACjD,SAAS,GAAG,CACZ,OAAO,GAAG,EAAE;EACf,MAAM,EAAE,aAAa,IAAI,IAAI,IAAI,IAAI;EACrC,MAAM,SAAS,IAAI;AAEnB,MAAI;GAEF,MAAM,WAAW,MAAM,cAAc,IAAI;GAGzC,MAAM,YAAY,YAAY,KAAK,GAAG;AACtC,WAAQ,cAAc;IACpB;IACA;IACA,MAAM;IACN,YAAY,SAAS;IACrB;IACA,WAAW,KAAK,KAAK;IACrB,oBAAoB;AAClB,SAAI,OAAO,YAAY,eAAe,QAAQ,aAAa;MACzD,MAAM,MAAM,QAAQ,aAAa;AACjC,aAAO;OACL,UAAU,IAAI;OACd,WAAW,IAAI;OAChB;;AAEH,YAAO;MAAE,UAAU;MAAG,WAAW;MAAG;QAClC;IACL,CAAC;AAEF,UAAO;WACA,OAAO;GAEd,MAAM,YAAY,YAAY,KAAK,GAAG;AACtC,WAAQ,cAAc;IACpB;IACA;IACA,MAAM;IACN,YAAY;IACZ;IACA,WAAW,KAAK,KAAK;IACrB,oBAAoB;AAClB,SAAI,OAAO,YAAY,eAAe,QAAQ,aAAa;MACzD,MAAM,MAAM,QAAQ,aAAa;AACjC,aAAO;OACL,UAAU,IAAI;OACd,WAAW,IAAI;OAChB;;AAEH,YAAO;MAAE,UAAU;MAAG,WAAW;MAAG;QAClC;IACL,CAAC;AAEF,SAAM;;;AAeV,QAVwB;EACtB,GAAG;EACH,OAAO;EAGP,2BAA2B,QAAQ,WAAW;EAC9C,4BAA4B,QAAQ,YAAY;EAChD,uBAAuB,QAAQ,OAAO;EACvC;;AAMH,SAAgB,sBACd,QACA,QACiB;CACjB,MAAM,EAAE;AAER,QAAO,eADQ,IAAI,OAAO,OAAO,EACH,OAAO"}
1
+ {"version":3,"file":"native-monitor.mjs","names":[],"sources":["../../src/monitoring/native-monitor.ts"],"sourcesContent":["/**\n * 原生监控装饰器\n *\n * 通过装饰器模式为 Server 添加监控能力,完全不入侵原类\n *\n * @author Framework Team\n * @version 2.0.0\n * @license MIT\n */\n\nimport type { Server } from \"../server\";\n\n// 监控配置接口\nexport interface NativeMonitoringConfig {\n enabled?: boolean;\n console?: boolean;\n slowThreshold?: number; // 毫秒\n errorThreshold?: number;\n tags?: Record<string, string>;\n}\n\n// 监控指标接口\nexport interface NativeMonitoringMetrics {\n requestId: string;\n method: string;\n path: string;\n statusCode: number;\n totalTime: number;\n timestamp: number;\n memoryUsage: {\n heapUsed: number;\n heapTotal: number;\n };\n}\n\n// 带监控的 Server 接口\nexport interface MonitoredServer extends Server {\n // 监控相关方法\n getMonitoringStatus(): any;\n getMonitoringMetrics(): NativeMonitoringMetrics[];\n resetMonitoring(): void;\n\n // 原始方法保持不变\n fetch: (req: Request) => Promise<Response>;\n use: (mw: any) => void;\n}\n\n// 原生监控器\nclass NativeMonitor {\n private config: NativeMonitoringConfig;\n private metrics: NativeMonitoringMetrics[] = [];\n private isEnabled = false;\n\n constructor(config: NativeMonitoringConfig = {}) {\n this.config = {\n enabled: true,\n console: true,\n slowThreshold: 1000,\n errorThreshold: 0.05,\n tags: { framework: \"vafast\" },\n ...config,\n };\n\n this.isEnabled = this.config.enabled ?? true;\n\n if (this.isEnabled && this.config.console) {\n console.log(\"✅ 原生监控已启用\");\n console.log(`📊 监控配置:`, {\n 慢请求阈值: `${this.config.slowThreshold}ms`,\n 错误率阈值: `${(this.config.errorThreshold! * 100).toFixed(1)}%`,\n 标签: this.config.tags,\n });\n }\n }\n\n // 记录监控指标\n recordMetrics(metrics: NativeMonitoringMetrics): void {\n if (!this.isEnabled) return;\n\n this.metrics.push(metrics);\n\n // 保持最近1000条记录\n if (this.metrics.length > 1000) {\n this.metrics = this.metrics.slice(-1000);\n }\n\n // 控制台输出\n if (this.config.console) {\n const status = metrics.statusCode < 400 ? \"✅\" : \"❌\";\n const timeColor =\n metrics.totalTime > this.config.slowThreshold! ? \"🐌\" : \"⚡\";\n\n console.log(\n `${status} ${metrics.method} ${metrics.path} - ${\n metrics.statusCode\n } (${timeColor} ${metrics.totalTime.toFixed(2)}ms)`,\n );\n\n // 慢请求警告\n if (metrics.totalTime > this.config.slowThreshold!) {\n console.warn(\n `🐌 慢请求警告: ${metrics.path} 耗时 ${metrics.totalTime.toFixed(\n 2,\n )}ms`,\n );\n }\n }\n }\n\n // 获取监控状态\n getStatus() {\n if (!this.isEnabled) {\n return { enabled: false, message: \"监控未启用\" };\n }\n\n const totalRequests = this.metrics.length;\n const successfulRequests = this.metrics.filter(\n (m) => m.statusCode < 400,\n ).length;\n const failedRequests = totalRequests - successfulRequests;\n const avgResponseTime =\n totalRequests > 0\n ? this.metrics.reduce((sum, m) => sum + m.totalTime, 0) / totalRequests\n : 0;\n\n return {\n enabled: true,\n totalRequests,\n successfulRequests,\n failedRequests,\n errorRate: totalRequests > 0 ? failedRequests / totalRequests : 0,\n avgResponseTime: avgResponseTime.toFixed(2) + \"ms\",\n memoryUsage: this.getMemoryUsage(),\n recentRequests: this.metrics.slice(-5),\n };\n }\n\n // 获取监控指标\n getMetrics() {\n return this.metrics;\n }\n\n // 重置监控数据\n reset() {\n this.metrics = [];\n console.log(\"🔄 监控数据已重置\");\n }\n\n // 获取内存使用情况\n private getMemoryUsage() {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: (mem.heapUsed / 1024 / 1024).toFixed(2) + \"MB\",\n heapTotal: (mem.heapTotal / 1024 / 1024).toFixed(2) + \"MB\",\n external: (mem.external / 1024 / 1024).toFixed(2) + \"MB\",\n };\n }\n return { message: \"内存信息不可用\" };\n }\n}\n\n// 纯函数:为 Server 添加监控能力\nexport function withMonitoring(\n server: Server,\n config: NativeMonitoringConfig = {},\n): MonitoredServer {\n const monitor = new NativeMonitor(config);\n\n // 保存原始的 fetch 方法\n const originalFetch = server.fetch.bind(server);\n\n // 创建带监控的 fetch 方法\n const monitoredFetch = async (req: Request): Promise<Response> => {\n const startTime = performance.now();\n const requestId = `req_${Date.now()}_${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const { pathname } = new URL(req.url);\n const method = req.method;\n\n try {\n // 调用原始 fetch\n const response = await originalFetch(req);\n\n // 记录监控指标\n const totalTime = performance.now() - startTime;\n monitor.recordMetrics({\n requestId,\n method,\n path: pathname,\n statusCode: response.status,\n totalTime,\n timestamp: Date.now(),\n memoryUsage: (() => {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n };\n }\n return { heapUsed: 0, heapTotal: 0 };\n })(),\n });\n\n return response;\n } catch (error) {\n // 记录错误监控指标\n const totalTime = performance.now() - startTime;\n monitor.recordMetrics({\n requestId,\n method,\n path: pathname,\n statusCode: 500,\n totalTime,\n timestamp: Date.now(),\n memoryUsage: (() => {\n if (typeof process !== \"undefined\" && process.memoryUsage) {\n const mem = process.memoryUsage();\n return {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n };\n }\n return { heapUsed: 0, heapTotal: 0 };\n })(),\n });\n\n throw error;\n }\n };\n\n // 创建带监控的 Server 对象\n const monitoredServer = {\n ...server,\n fetch: monitoredFetch,\n\n // 监控方法\n getMonitoringStatus: () => monitor.getStatus(),\n getMonitoringMetrics: () => monitor.getMetrics(),\n resetMonitoring: () => monitor.reset(),\n } as MonitoredServer;\n\n return monitoredServer;\n}\n\n// 便捷函数:创建带监控的 Server\nexport function createMonitoredServer(\n routes: any[],\n config?: NativeMonitoringConfig,\n): MonitoredServer {\n const { Server } = require(\"../server\");\n const server = new Server(routes);\n return withMonitoring(server, config);\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { t as createProxyRequest } from "../request-CKC3Ox6M.mjs";
2
- import { n as writeResponseSimple, t as writeResponse } from "../response-Cf5FgtmE.mjs";
3
- import { n as serve, t as createAdaptorServer } from "../serve-Be6NvuQk.mjs";
1
+ import { t as createProxyRequest } from "../request-B886yCvG.mjs";
2
+ import { n as writeResponseSimple, t as writeResponse } from "../response-30WnzABq.mjs";
3
+ import { n as serve, t as createAdaptorServer } from "../serve-DgWBnexE.mjs";
4
4
 
5
5
  export { createAdaptorServer, createProxyRequest, serve, writeResponse, writeResponseSimple };
@@ -1,3 +1,3 @@
1
- import { t as createProxyRequest } from "../request-CKC3Ox6M.mjs";
1
+ import { t as createProxyRequest } from "../request-B886yCvG.mjs";
2
2
 
3
3
  export { createProxyRequest };
@@ -1,3 +1,3 @@
1
- import { n as writeResponseSimple, t as writeResponse } from "../response-Cf5FgtmE.mjs";
1
+ import { n as writeResponseSimple, t as writeResponse } from "../response-30WnzABq.mjs";
2
2
 
3
3
  export { writeResponse, writeResponseSimple };
@@ -1,4 +1,4 @@
1
- import "../request-CKC3Ox6M.mjs";
2
- import { n as serve, t as createAdaptorServer } from "../serve-Be6NvuQk.mjs";
1
+ import "../request-B886yCvG.mjs";
2
+ import { n as serve, t as createAdaptorServer } from "../serve-DgWBnexE.mjs";
3
3
 
4
4
  export { createAdaptorServer, serve };
@@ -165,4 +165,4 @@ function getCookie(req, name) {
165
165
 
166
166
  //#endregion
167
167
  export { parseCookies as a, parseFormData as c, parseQueryFast as d, parseBodyAs as i, parseHeaders as l, getHeader as n, parseCookiesFast as o, parseBody as r, parseFile as s, getCookie as t, parseQuery as u };
168
- //# sourceMappingURL=parsers-CI_TZ7pO.mjs.map
168
+ //# sourceMappingURL=parsers-BQ63b0YE.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parsers-CI_TZ7pO.mjs","names":[],"sources":["../src/utils/parsers.ts"],"sourcesContent":["// src/parsers.ts\nimport qs from \"qs\";\nimport cookie from \"cookie\";\n\n// 文件信息接口\nexport interface FileInfo {\n name: string;\n type: string;\n size: number;\n data: ArrayBuffer;\n}\n\n// 表单数据接口\nexport interface FormData {\n fields: Record<string, string>;\n files: Record<string, FileInfo>;\n}\n\n/**\n * 简化的请求体解析函数\n * 优先简洁性,处理最常见的场景\n */\nexport async function parseBody(req: Request): Promise<unknown> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n return await req.json();\n }\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const text = await req.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n return await req.text(); // fallback\n}\n\n/**\n * 解析 multipart/form-data 格式\n * 支持文件上传和普通表单字段\n */\nasync function parseMultipartFormData(req: Request): Promise<FormData> {\n const formData = await req.formData();\n const result: FormData = {\n fields: {},\n files: {},\n };\n\n for (const [key, value] of formData.entries()) {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n \"type\" in value &&\n \"size\" in value\n ) {\n // 处理文件\n const file = value as any;\n const arrayBuffer = await file.arrayBuffer();\n result.files[key] = {\n name: file.name,\n type: file.type,\n size: file.size,\n data: arrayBuffer,\n };\n } else {\n // 处理普通字段\n result.fields[key] = value as string;\n }\n }\n\n return result;\n}\n\n/**\n * 解析请求体为特定类型\n * 提供类型安全的解析方法\n */\nexport async function parseBodyAs<T>(req: Request): Promise<T> {\n const body = await parseBody(req);\n return body as T;\n}\n\n/**\n * 解析请求体为表单数据\n * 专门用于处理 multipart/form-data\n */\nexport async function parseFormData(req: Request): Promise<FormData> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n return await parseMultipartFormData(req);\n}\n\n/**\n * 解析请求体为文件\n * 专门用于处理文件上传\n */\nexport async function parseFile(req: Request): Promise<FileInfo> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n const formData = await parseMultipartFormData(req);\n const fileKeys = Object.keys(formData.files);\n\n if (fileKeys.length === 0) {\n throw new Error(\"请求中没有文件\");\n }\n\n if (fileKeys.length > 1) {\n throw new Error(\"请求中包含多个文件,请使用 parseFormData\");\n }\n\n return formData.files[fileKeys[0]];\n}\n\n/**\n * 快速提取 query string(避免创建 URL 对象)\n */\nfunction extractQueryString(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return \"\";\n\n const hashIndex = url.indexOf(\"#\", qIndex);\n return hashIndex === -1\n ? url.substring(qIndex + 1)\n : url.substring(qIndex + 1, hashIndex);\n}\n\n/** 获取查询字符串,直接返回对象 */\nexport function parseQuery(req: Request): Record<string, unknown> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n return qs.parse(queryString);\n}\n\n/**\n * 快速解析简单查询字符串(不支持嵌套,但更快)\n * 适用于简单的 key=value&key2=value2 场景\n */\nexport function parseQueryFast(req: Request): Record<string, string> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) {\n result[decodeURIComponent(pair)] = \"\";\n } else {\n const key = decodeURIComponent(pair.substring(0, eqIndex));\n const value = decodeURIComponent(pair.substring(eqIndex + 1));\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/** 解析请求头,返回对象 */\nexport function parseHeaders(req: Request): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n req.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return headers;\n}\n\n/**\n * 获取单个请求头(避免解析全部)\n */\nexport function getHeader(req: Request, name: string): string | null {\n return req.headers.get(name);\n}\n\n/** 使用cookie库解析Cookie,保证可靠性 */\nexport function parseCookies(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n try {\n const parsed = cookie.parse(cookieHeader);\n // 过滤掉undefined和null值\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n return result;\n } catch {\n return {};\n }\n}\n\n/**\n * 快速解析 Cookie(简化版,不使用外部库)\n * 适用于简单的 cookie 场景\n */\nexport function parseCookiesFast(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex > 0) {\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n // 移除引号\n result[key] =\n value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return result;\n}\n\n/**\n * 获取单个 Cookie 值(避免解析全部)\n */\nexport function getCookie(req: Request, name: string): string | null {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return null;\n\n const prefix = `${name}=`;\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n if (trimmed.startsWith(prefix)) {\n const value = trimmed.substring(prefix.length).trim();\n return value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;AAsBA,eAAsB,UAAU,KAAgC;CAC9D,MAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,IAAI;AACvD,KAAI,YAAY,SAAS,mBAAmB,CAC1C,QAAO,MAAM,IAAI,MAAM;AAEzB,KAAI,YAAY,SAAS,oCAAoC,EAAE;EAC7D,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,SAAO,OAAO,YAAY,IAAI,gBAAgB,KAAK,CAAC;;AAEtD,QAAO,MAAM,IAAI,MAAM;;;;;;AAOzB,eAAe,uBAAuB,KAAiC;CACrE,MAAM,WAAW,MAAM,IAAI,UAAU;CACrC,MAAM,SAAmB;EACvB,QAAQ,EAAE;EACV,OAAO,EAAE;EACV;AAED,MAAK,MAAM,CAAC,KAAK,UAAU,SAAS,SAAS,CAC3C,KACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,UAAU,SACV,UAAU,OACV;EAEA,MAAM,OAAO;EACb,MAAM,cAAc,MAAM,KAAK,aAAa;AAC5C,SAAO,MAAM,OAAO;GAClB,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM;GACP;OAGD,QAAO,OAAO,OAAO;AAIzB,QAAO;;;;;;AAOT,eAAsB,YAAe,KAA0B;AAE7D,QADa,MAAM,UAAU,IAAI;;;;;;AAQnC,eAAsB,cAAc,KAAiC;AAGnE,KAAI,EAFgB,IAAI,QAAQ,IAAI,eAAe,IAAI,IAEtC,SAAS,sBAAsB,CAC9C,OAAM,IAAI,MAAM,8BAA8B;AAGhD,QAAO,MAAM,uBAAuB,IAAI;;;;;;AAO1C,eAAsB,UAAU,KAAiC;AAG/D,KAAI,EAFgB,IAAI,QAAQ,IAAI,eAAe,IAAI,IAEtC,SAAS,sBAAsB,CAC9C,OAAM,IAAI,MAAM,8BAA8B;CAGhD,MAAM,WAAW,MAAM,uBAAuB,IAAI;CAClD,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM;AAE5C,KAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,UAAU;AAG5B,KAAI,SAAS,SAAS,EACpB,OAAM,IAAI,MAAM,8BAA8B;AAGhD,QAAO,SAAS,MAAM,SAAS;;;;;AAMjC,SAAS,mBAAmB,KAAqB;CAC/C,MAAM,SAAS,IAAI,QAAQ,IAAI;AAC/B,KAAI,WAAW,GAAI,QAAO;CAE1B,MAAM,YAAY,IAAI,QAAQ,KAAK,OAAO;AAC1C,QAAO,cAAc,KACjB,IAAI,UAAU,SAAS,EAAE,GACzB,IAAI,UAAU,SAAS,GAAG,UAAU;;;AAI1C,SAAgB,WAAW,KAAuC;CAChE,MAAM,cAAc,mBAAmB,IAAI,IAAI;AAC/C,KAAI,CAAC,YAAa,QAAO,EAAE;AAC3B,QAAO,GAAG,MAAM,YAAY;;;;;;AAO9B,SAAgB,eAAe,KAAsC;CACnE,MAAM,cAAc,mBAAmB,IAAI,IAAI;AAC/C,KAAI,CAAC,YAAa,QAAO,EAAE;CAE3B,MAAM,SAAiC,OAAO,OAAO,KAAK;CAC1D,MAAM,QAAQ,YAAY,MAAM,IAAI;AAEpC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,MAAI,YAAY,GACd,QAAO,mBAAmB,KAAK,IAAI;OAC9B;GACL,MAAM,MAAM,mBAAmB,KAAK,UAAU,GAAG,QAAQ,CAAC;AAE1D,UAAO,OADO,mBAAmB,KAAK,UAAU,UAAU,EAAE,CAAC;;;AAKjE,QAAO;;;AAIT,SAAgB,aAAa,KAAsC;CACjE,MAAM,UAAkC,OAAO,OAAO,KAAK;AAC3D,KAAI,QAAQ,SAAS,OAAO,QAAQ;AAClC,UAAQ,OAAO;GACf;AACF,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAA6B;AACnE,QAAO,IAAI,QAAQ,IAAI,KAAK;;;AAI9B,SAAgB,aAAa,KAAsC;CACjE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO,EAAE;AAE5B,KAAI;EACF,MAAM,SAAS,OAAO,MAAM,aAAa;EAEzC,MAAM,SAAiC,EAAE;AACzC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,UAAU,UAAa,UAAU,KACnC,QAAO,OAAO;AAGlB,SAAO;SACD;AACN,SAAO,EAAE;;;;;;;AAQb,SAAgB,iBAAiB,KAAsC;CACrE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO,EAAE;CAE5B,MAAM,SAAiC,OAAO,OAAO,KAAK;CAC1D,MAAM,QAAQ,aAAa,MAAM,IAAI;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,MAAM;EAC3B,MAAM,UAAU,QAAQ,QAAQ,IAAI;AACpC,MAAI,UAAU,GAAG;GACf,MAAM,MAAM,QAAQ,UAAU,GAAG,QAAQ,CAAC,MAAM;GAChD,MAAM,QAAQ,QAAQ,UAAU,UAAU,EAAE,CAAC,MAAM;AAEnD,UAAO,OACL,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,GACxC,MAAM,MAAM,GAAG,GAAG,GAClB;;;AAIV,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAA6B;CACnE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO;CAE1B,MAAM,SAAS,GAAG,KAAK;CACvB,MAAM,QAAQ,aAAa,MAAM,IAAI;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,QAAQ,WAAW,OAAO,EAAE;GAC9B,MAAM,QAAQ,QAAQ,UAAU,OAAO,OAAO,CAAC,MAAM;AACrD,UAAO,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,GAC/C,MAAM,MAAM,GAAG,GAAG,GAClB;;;AAIR,QAAO"}
1
+ {"version":3,"file":"parsers-BQ63b0YE.mjs","names":[],"sources":["../src/utils/parsers.ts"],"sourcesContent":["// src/parsers.ts\nimport qs from \"qs\";\nimport cookie from \"cookie\";\n\n// 文件信息接口\nexport interface FileInfo {\n name: string;\n type: string;\n size: number;\n data: ArrayBuffer;\n}\n\n// 表单数据接口\nexport interface FormData {\n fields: Record<string, string>;\n files: Record<string, FileInfo>;\n}\n\n/**\n * 简化的请求体解析函数\n * 优先简洁性,处理最常见的场景\n */\nexport async function parseBody(req: Request): Promise<unknown> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n return await req.json();\n }\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const text = await req.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n return await req.text(); // fallback\n}\n\n/**\n * 解析 multipart/form-data 格式\n * 支持文件上传和普通表单字段\n */\nasync function parseMultipartFormData(req: Request): Promise<FormData> {\n const formData = await req.formData();\n const result: FormData = {\n fields: {},\n files: {},\n };\n\n for (const [key, value] of formData.entries()) {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n \"type\" in value &&\n \"size\" in value\n ) {\n // 处理文件\n const file = value as any;\n const arrayBuffer = await file.arrayBuffer();\n result.files[key] = {\n name: file.name,\n type: file.type,\n size: file.size,\n data: arrayBuffer,\n };\n } else {\n // 处理普通字段\n result.fields[key] = value as string;\n }\n }\n\n return result;\n}\n\n/**\n * 解析请求体为特定类型\n * 提供类型安全的解析方法\n */\nexport async function parseBodyAs<T>(req: Request): Promise<T> {\n const body = await parseBody(req);\n return body as T;\n}\n\n/**\n * 解析请求体为表单数据\n * 专门用于处理 multipart/form-data\n */\nexport async function parseFormData(req: Request): Promise<FormData> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n return await parseMultipartFormData(req);\n}\n\n/**\n * 解析请求体为文件\n * 专门用于处理文件上传\n */\nexport async function parseFile(req: Request): Promise<FileInfo> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n const formData = await parseMultipartFormData(req);\n const fileKeys = Object.keys(formData.files);\n\n if (fileKeys.length === 0) {\n throw new Error(\"请求中没有文件\");\n }\n\n if (fileKeys.length > 1) {\n throw new Error(\"请求中包含多个文件,请使用 parseFormData\");\n }\n\n return formData.files[fileKeys[0]];\n}\n\n/**\n * 快速提取 query string(避免创建 URL 对象)\n */\nfunction extractQueryString(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return \"\";\n\n const hashIndex = url.indexOf(\"#\", qIndex);\n return hashIndex === -1\n ? url.substring(qIndex + 1)\n : url.substring(qIndex + 1, hashIndex);\n}\n\n/** 获取查询字符串,直接返回对象 */\nexport function parseQuery(req: Request): Record<string, unknown> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n return qs.parse(queryString);\n}\n\n/**\n * 快速解析简单查询字符串(不支持嵌套,但更快)\n * 适用于简单的 key=value&key2=value2 场景\n */\nexport function parseQueryFast(req: Request): Record<string, string> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) {\n result[decodeURIComponent(pair)] = \"\";\n } else {\n const key = decodeURIComponent(pair.substring(0, eqIndex));\n const value = decodeURIComponent(pair.substring(eqIndex + 1));\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/** 解析请求头,返回对象 */\nexport function parseHeaders(req: Request): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n req.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return headers;\n}\n\n/**\n * 获取单个请求头(避免解析全部)\n */\nexport function getHeader(req: Request, name: string): string | null {\n return req.headers.get(name);\n}\n\n/** 使用cookie库解析Cookie,保证可靠性 */\nexport function parseCookies(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n try {\n const parsed = cookie.parse(cookieHeader);\n // 过滤掉undefined和null值\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n return result;\n } catch {\n return {};\n }\n}\n\n/**\n * 快速解析 Cookie(简化版,不使用外部库)\n * 适用于简单的 cookie 场景\n */\nexport function parseCookiesFast(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex > 0) {\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n // 移除引号\n result[key] =\n value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return result;\n}\n\n/**\n * 获取单个 Cookie 值(避免解析全部)\n */\nexport function getCookie(req: Request, name: string): string | null {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return null;\n\n const prefix = `${name}=`;\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n if (trimmed.startsWith(prefix)) {\n const value = trimmed.substring(prefix.length).trim();\n return value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;AAsBA,eAAsB,UAAU,KAAgC;CAC9D,MAAM,cAAc,IAAI,QAAQ,IAAI,eAAe,IAAI;AACvD,KAAI,YAAY,SAAS,mBAAmB,CAC1C,QAAO,MAAM,IAAI,MAAM;AAEzB,KAAI,YAAY,SAAS,oCAAoC,EAAE;EAC7D,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,SAAO,OAAO,YAAY,IAAI,gBAAgB,KAAK,CAAC;;AAEtD,QAAO,MAAM,IAAI,MAAM;;;;;;AAOzB,eAAe,uBAAuB,KAAiC;CACrE,MAAM,WAAW,MAAM,IAAI,UAAU;CACrC,MAAM,SAAmB;EACvB,QAAQ,EAAE;EACV,OAAO,EAAE;EACV;AAED,MAAK,MAAM,CAAC,KAAK,UAAU,SAAS,SAAS,CAC3C,KACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,UAAU,SACV,UAAU,OACV;EAEA,MAAM,OAAO;EACb,MAAM,cAAc,MAAM,KAAK,aAAa;AAC5C,SAAO,MAAM,OAAO;GAClB,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM;GACP;OAGD,QAAO,OAAO,OAAO;AAIzB,QAAO;;;;;;AAOT,eAAsB,YAAe,KAA0B;AAE7D,QADa,MAAM,UAAU,IAAI;;;;;;AAQnC,eAAsB,cAAc,KAAiC;AAGnE,KAAI,EAFgB,IAAI,QAAQ,IAAI,eAAe,IAAI,IAEtC,SAAS,sBAAsB,CAC9C,OAAM,IAAI,MAAM,8BAA8B;AAGhD,QAAO,MAAM,uBAAuB,IAAI;;;;;;AAO1C,eAAsB,UAAU,KAAiC;AAG/D,KAAI,EAFgB,IAAI,QAAQ,IAAI,eAAe,IAAI,IAEtC,SAAS,sBAAsB,CAC9C,OAAM,IAAI,MAAM,8BAA8B;CAGhD,MAAM,WAAW,MAAM,uBAAuB,IAAI;CAClD,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM;AAE5C,KAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,UAAU;AAG5B,KAAI,SAAS,SAAS,EACpB,OAAM,IAAI,MAAM,8BAA8B;AAGhD,QAAO,SAAS,MAAM,SAAS;;;;;AAMjC,SAAS,mBAAmB,KAAqB;CAC/C,MAAM,SAAS,IAAI,QAAQ,IAAI;AAC/B,KAAI,WAAW,GAAI,QAAO;CAE1B,MAAM,YAAY,IAAI,QAAQ,KAAK,OAAO;AAC1C,QAAO,cAAc,KACjB,IAAI,UAAU,SAAS,EAAE,GACzB,IAAI,UAAU,SAAS,GAAG,UAAU;;;AAI1C,SAAgB,WAAW,KAAuC;CAChE,MAAM,cAAc,mBAAmB,IAAI,IAAI;AAC/C,KAAI,CAAC,YAAa,QAAO,EAAE;AAC3B,QAAO,GAAG,MAAM,YAAY;;;;;;AAO9B,SAAgB,eAAe,KAAsC;CACnE,MAAM,cAAc,mBAAmB,IAAI,IAAI;AAC/C,KAAI,CAAC,YAAa,QAAO,EAAE;CAE3B,MAAM,SAAiC,OAAO,OAAO,KAAK;CAC1D,MAAM,QAAQ,YAAY,MAAM,IAAI;AAEpC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,MAAI,YAAY,GACd,QAAO,mBAAmB,KAAK,IAAI;OAC9B;GACL,MAAM,MAAM,mBAAmB,KAAK,UAAU,GAAG,QAAQ,CAAC;AAE1D,UAAO,OADO,mBAAmB,KAAK,UAAU,UAAU,EAAE,CAAC;;;AAKjE,QAAO;;;AAIT,SAAgB,aAAa,KAAsC;CACjE,MAAM,UAAkC,OAAO,OAAO,KAAK;AAC3D,KAAI,QAAQ,SAAS,OAAO,QAAQ;AAClC,UAAQ,OAAO;GACf;AACF,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAA6B;AACnE,QAAO,IAAI,QAAQ,IAAI,KAAK;;;AAI9B,SAAgB,aAAa,KAAsC;CACjE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO,EAAE;AAE5B,KAAI;EACF,MAAM,SAAS,OAAO,MAAM,aAAa;EAEzC,MAAM,SAAiC,EAAE;AACzC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,UAAU,UAAa,UAAU,KACnC,QAAO,OAAO;AAGlB,SAAO;SACD;AACN,SAAO,EAAE;;;;;;;AAQb,SAAgB,iBAAiB,KAAsC;CACrE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO,EAAE;CAE5B,MAAM,SAAiC,OAAO,OAAO,KAAK;CAC1D,MAAM,QAAQ,aAAa,MAAM,IAAI;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,MAAM;EAC3B,MAAM,UAAU,QAAQ,QAAQ,IAAI;AACpC,MAAI,UAAU,GAAG;GACf,MAAM,MAAM,QAAQ,UAAU,GAAG,QAAQ,CAAC,MAAM;GAChD,MAAM,QAAQ,QAAQ,UAAU,UAAU,EAAE,CAAC,MAAM;AAEnD,UAAO,OACL,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,GACxC,MAAM,MAAM,GAAG,GAAG,GAClB;;;AAIV,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAA6B;CACnE,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,KAAI,CAAC,aAAc,QAAO;CAE1B,MAAM,SAAS,GAAG,KAAK;CACvB,MAAM,QAAQ,aAAa,MAAM,IAAI;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,QAAQ,WAAW,OAAO,EAAE;GAC9B,MAAM,QAAQ,QAAQ,UAAU,OAAO,OAAO,CAAC,MAAM;AACrD,UAAO,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,GAC/C,MAAM,MAAM,GAAG,GAAG,GAClB;;;AAIR,QAAO"}
@@ -59,4 +59,4 @@ var init_path_matcher = __esmMin((() => {
59
59
 
60
60
  //#endregion
61
61
  export { init_path_matcher as n, PathMatcher as t };
62
- //# sourceMappingURL=path-matcher-73cJd5Y7.mjs.map
62
+ //# sourceMappingURL=path-matcher-BNaaJgI3.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-matcher-73cJd5Y7.mjs","names":[],"sources":["../src/utils/path-matcher.ts"],"sourcesContent":["/**\n * 路径匹配工具类\n * 提供统一的路径匹配和参数提取功能\n */\nexport class PathMatcher {\n /**\n * 路径匹配\n */\n static matchPath(pattern: string, path: string): boolean {\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n if (patternParts.length !== pathParts.length) {\n return false;\n }\n\n for (let i = 0; i < patternParts.length; i++) {\n if (\n patternParts[i] !== pathParts[i] &&\n !patternParts[i].startsWith(\":\")\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * 提取路径参数\n */\n static extractParams(pattern: string, path: string): Record<string, string> {\n const params: Record<string, string> = {};\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n for (let i = 0; i < patternParts.length; i++) {\n if (patternParts[i].startsWith(\":\")) {\n const paramName = patternParts[i].slice(1);\n params[paramName] = pathParts[i];\n }\n }\n\n return params;\n }\n\n /**\n * 计算路径特异性分数\n * 用于路由排序:静态 > 动态(:param) > 通配符(*)\n */\n static calculatePathScore(path: string): number {\n const parts = path.split(\"/\").filter(Boolean);\n let score = 0;\n for (const p of parts) {\n if (p === \"*\")\n score += 1; // 最弱\n else if (p.startsWith(\":\"))\n score += 2; // 中等\n else score += 3; // 静态最强\n }\n // 更长的路径更具体,略微提升\n return score * 10 + parts.length;\n }\n\n /**\n * 判断两个路径是否可能冲突\n */\n static pathsMayConflict(path1: string, path2: string): boolean {\n const parts1 = path1.split(\"/\").filter(Boolean);\n const parts2 = path2.split(\"/\").filter(Boolean);\n\n if (parts1.length !== parts2.length) return false;\n\n for (let i = 0; i < parts1.length; i++) {\n const p1 = parts1[i];\n const p2 = parts2[i];\n\n // 如果两个部分都是静态的且不同,则不会冲突\n if (\n !p1.startsWith(\":\") &&\n !p1.startsWith(\"*\") &&\n !p2.startsWith(\":\") &&\n !p2.startsWith(\"*\") &&\n p1 !== p2\n ) {\n return false;\n }\n\n // 如果一个是通配符,另一个是动态参数,可能冲突\n if (\n (p1 === \"*\" && p2.startsWith(\":\")) ||\n (p2 === \"*\" && p1.startsWith(\":\"))\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n"],"mappings":";;;;;CAIa,cAAb,MAAyB;;;;EAIvB,OAAO,UAAU,SAAiB,MAAuB;GACvD,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;GACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,OAAI,aAAa,WAAW,UAAU,OACpC,QAAO;AAGT,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KACE,aAAa,OAAO,UAAU,MAC9B,CAAC,aAAa,GAAG,WAAW,IAAI,CAEhC,QAAO;AAIX,UAAO;;;;;EAMT,OAAO,cAAc,SAAiB,MAAsC;GAC1E,MAAM,SAAiC,EAAE;GACzC,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;GACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KAAI,aAAa,GAAG,WAAW,IAAI,EAAE;IACnC,MAAM,YAAY,aAAa,GAAG,MAAM,EAAE;AAC1C,WAAO,aAAa,UAAU;;AAIlC,UAAO;;;;;;EAOT,OAAO,mBAAmB,MAAsB;GAC9C,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;GAC7C,IAAI,QAAQ;AACZ,QAAK,MAAM,KAAK,MACd,KAAI,MAAM,IACR,UAAS;YACF,EAAE,WAAW,IAAI,CACxB,UAAS;OACN,UAAS;AAGhB,UAAO,QAAQ,KAAK,MAAM;;;;;EAM5B,OAAO,iBAAiB,OAAe,OAAwB;GAC7D,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;GAC/C,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;AAE/C,OAAI,OAAO,WAAW,OAAO,OAAQ,QAAO;AAE5C,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,KAAK,OAAO;IAClB,MAAM,KAAK,OAAO;AAGlB,QACE,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,OAAO,GAEP,QAAO;AAIT,QACG,OAAO,OAAO,GAAG,WAAW,IAAI,IAChC,OAAO,OAAO,GAAG,WAAW,IAAI,CAEjC,QAAO;;AAIX,UAAO"}
1
+ {"version":3,"file":"path-matcher-BNaaJgI3.mjs","names":[],"sources":["../src/utils/path-matcher.ts"],"sourcesContent":["/**\n * 路径匹配工具类\n * 提供统一的路径匹配和参数提取功能\n */\nexport class PathMatcher {\n /**\n * 路径匹配\n */\n static matchPath(pattern: string, path: string): boolean {\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n if (patternParts.length !== pathParts.length) {\n return false;\n }\n\n for (let i = 0; i < patternParts.length; i++) {\n if (\n patternParts[i] !== pathParts[i] &&\n !patternParts[i].startsWith(\":\")\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * 提取路径参数\n */\n static extractParams(pattern: string, path: string): Record<string, string> {\n const params: Record<string, string> = {};\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n for (let i = 0; i < patternParts.length; i++) {\n if (patternParts[i].startsWith(\":\")) {\n const paramName = patternParts[i].slice(1);\n params[paramName] = pathParts[i];\n }\n }\n\n return params;\n }\n\n /**\n * 计算路径特异性分数\n * 用于路由排序:静态 > 动态(:param) > 通配符(*)\n */\n static calculatePathScore(path: string): number {\n const parts = path.split(\"/\").filter(Boolean);\n let score = 0;\n for (const p of parts) {\n if (p === \"*\")\n score += 1; // 最弱\n else if (p.startsWith(\":\"))\n score += 2; // 中等\n else score += 3; // 静态最强\n }\n // 更长的路径更具体,略微提升\n return score * 10 + parts.length;\n }\n\n /**\n * 判断两个路径是否可能冲突\n */\n static pathsMayConflict(path1: string, path2: string): boolean {\n const parts1 = path1.split(\"/\").filter(Boolean);\n const parts2 = path2.split(\"/\").filter(Boolean);\n\n if (parts1.length !== parts2.length) return false;\n\n for (let i = 0; i < parts1.length; i++) {\n const p1 = parts1[i];\n const p2 = parts2[i];\n\n // 如果两个部分都是静态的且不同,则不会冲突\n if (\n !p1.startsWith(\":\") &&\n !p1.startsWith(\"*\") &&\n !p2.startsWith(\":\") &&\n !p2.startsWith(\"*\") &&\n p1 !== p2\n ) {\n return false;\n }\n\n // 如果一个是通配符,另一个是动态参数,可能冲突\n if (\n (p1 === \"*\" && p2.startsWith(\":\")) ||\n (p2 === \"*\" && p1.startsWith(\":\"))\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n"],"mappings":";;;;;CAIa,cAAb,MAAyB;;;;EAIvB,OAAO,UAAU,SAAiB,MAAuB;GACvD,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;GACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,OAAI,aAAa,WAAW,UAAU,OACpC,QAAO;AAGT,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KACE,aAAa,OAAO,UAAU,MAC9B,CAAC,aAAa,GAAG,WAAW,IAAI,CAEhC,QAAO;AAIX,UAAO;;;;;EAMT,OAAO,cAAc,SAAiB,MAAsC;GAC1E,MAAM,SAAiC,EAAE;GACzC,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;GACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KAAI,aAAa,GAAG,WAAW,IAAI,EAAE;IACnC,MAAM,YAAY,aAAa,GAAG,MAAM,EAAE;AAC1C,WAAO,aAAa,UAAU;;AAIlC,UAAO;;;;;;EAOT,OAAO,mBAAmB,MAAsB;GAC9C,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;GAC7C,IAAI,QAAQ;AACZ,QAAK,MAAM,KAAK,MACd,KAAI,MAAM,IACR,UAAS;YACF,EAAE,WAAW,IAAI,CACxB,UAAS;OACN,UAAS;AAGhB,UAAO,QAAQ,KAAK,MAAM;;;;;EAM5B,OAAO,iBAAiB,OAAe,OAAwB;GAC7D,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;GAC/C,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;AAE/C,OAAI,OAAO,WAAW,OAAO,OAAQ,QAAO;AAE5C,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,KAAK,OAAO;IAClB,MAAM,KAAK,OAAO;AAGlB,QACE,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,OAAO,GAEP,QAAO;AAIT,QACG,OAAO,OAAO,GAAG,WAAW,IAAI,IAChC,OAAO,OAAO,GAAG,WAAW,IAAI,CAEjC,QAAO;;AAIX,UAAO"}
@@ -154,4 +154,4 @@ var init_radix_tree = __esmMin((() => {
154
154
 
155
155
  //#endregion
156
156
  export { init_radix_tree as n, RadixRouter as t };
157
- //# sourceMappingURL=radix-tree-D0XYaJKb.mjs.map
157
+ //# sourceMappingURL=radix-tree-Qxr-QpCx.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"radix-tree-D0XYaJKb.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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"}
1
+ {"version":3,"file":"radix-tree-Qxr-QpCx.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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"}
@@ -130,4 +130,4 @@ function createProxyRequest(incoming, defaultHost) {
130
130
 
131
131
  //#endregion
132
132
  export { createProxyRequest as t };
133
- //# sourceMappingURL=request-CKC3Ox6M.mjs.map
133
+ //# sourceMappingURL=request-B886yCvG.mjs.map