vafast 0.4.24 → 0.5.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.
Files changed (165) hide show
  1. package/README.md +132 -1
  2. package/dist/{base-server-B7MYJNsl.mjs → base-server-CE0mfqPY.mjs} +11 -23
  3. package/dist/base-server-CE0mfqPY.mjs.map +1 -0
  4. package/dist/{base-server-DLxtulAO.d.mts → base-server-Contwrlf.d.mts} +5 -6
  5. package/dist/{base64url-C2zopQdH.mjs → base64url-Cc77f1ms.mjs} +1 -1
  6. package/dist/{base64url-C2zopQdH.mjs.map → base64url-Cc77f1ms.mjs.map} +1 -1
  7. package/dist/{base64url-Dwi2Afhc.d.mts → base64url-DNUGwekK.d.mts} +1 -1
  8. package/dist/{component-route-nrrO0iSI.d.mts → component-route-Di7R40-2.d.mts} +2 -2
  9. package/dist/{component-router-RwPL20vN.mjs → component-router-B6M5XDnp.mjs} +1 -1
  10. package/dist/{component-router-RwPL20vN.mjs.map → component-router-B6M5XDnp.mjs.map} +1 -1
  11. package/dist/{component-server-DomPJ_7S.mjs → component-server-Cya46YN3.mjs} +7 -7
  12. package/dist/component-server-Cya46YN3.mjs.map +1 -0
  13. package/dist/{component-server-JqpDC7wy.d.mts → component-server-fR4UV6Jq.d.mts} +4 -4
  14. package/dist/contract-BKqc9fFH.mjs +114 -0
  15. package/dist/contract-BKqc9fFH.mjs.map +1 -0
  16. package/dist/contract-BL3JflJ7.d.mts +71 -0
  17. package/dist/defineRoute-BjLBWeSj.d.mts +152 -0
  18. package/dist/defineRoute.d.mts +2 -60
  19. package/dist/defineRoute.mjs +135 -26
  20. package/dist/defineRoute.mjs.map +1 -1
  21. package/dist/{dependency-manager-DCmh7xFc.mjs → dependency-manager-CGMZJTer.mjs} +1 -1
  22. package/dist/{dependency-manager-DCmh7xFc.mjs.map → dependency-manager-CGMZJTer.mjs.map} +1 -1
  23. package/dist/{dependency-manager-C3_7ic4h.d.mts → dependency-manager-DIN9X0Gj.d.mts} +1 -1
  24. package/dist/{formats-Dk-DSBY4.d.mts → formats-DDDSFWP0.d.mts} +1 -1
  25. package/dist/{go-await-C4ZdEUwY.mjs → go-await-B1U27PgB.mjs} +1 -1
  26. package/dist/{go-await-C4ZdEUwY.mjs.map → go-await-B1U27PgB.mjs.map} +1 -1
  27. package/dist/{go-await-DL1A_-4X.d.mts → go-await-DPtVBug4.d.mts} +1 -1
  28. package/dist/{html-renderer-DTtJ_Yic.mjs → html-renderer-D1zzDVQM.mjs} +1 -1
  29. package/dist/{html-renderer-DTtJ_Yic.mjs.map → html-renderer-D1zzDVQM.mjs.map} +1 -1
  30. package/dist/{html-renderer-CfKK2BrP.d.mts → html-renderer-DhQxRuyi.d.mts} +1 -1
  31. package/dist/{index-Bj3SWrMU.d.mts → index-DCloGU_g.d.mts} +6 -6
  32. package/dist/index.d.mts +22 -27
  33. package/dist/index.mjs +19 -22
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/middleware/component-router.d.mts +1 -1
  36. package/dist/middleware/component-router.mjs +1 -1
  37. package/dist/{middleware-KXEoefLX.d.mts → middleware-BR-R4p0M.d.mts} +2 -2
  38. package/dist/middleware.d.mts +1 -3
  39. package/dist/middleware.mjs +1 -1
  40. package/dist/monitoring/index.d.mts +3 -6
  41. package/dist/monitoring/native-monitor.d.mts +3 -6
  42. package/dist/node-server/index.d.mts +1 -1
  43. package/dist/node-server/index.mjs +3 -3
  44. package/dist/node-server/request.mjs +1 -1
  45. package/dist/node-server/response.mjs +1 -1
  46. package/dist/node-server/serve.d.mts +1 -1
  47. package/dist/node-server/serve.mjs +2 -2
  48. package/dist/{parsers-BerGr2_q.d.mts → parsers-8hIAx0OV.d.mts} +1 -1
  49. package/dist/{parsers-DpH_mD0H.mjs → parsers-BrG_mRLq.mjs} +1 -1
  50. package/dist/{parsers-DpH_mD0H.mjs.map → parsers-BrG_mRLq.mjs.map} +1 -1
  51. package/dist/{path-matcher-CGczAIl_.mjs → path-matcher-Dp-DRUV9.mjs} +1 -1
  52. package/dist/{path-matcher-CGczAIl_.mjs.map → path-matcher-Dp-DRUV9.mjs.map} +1 -1
  53. package/dist/{radix-tree-qqSjnVXF.mjs → radix-tree-CccjvyTP.mjs} +1 -1
  54. package/dist/{radix-tree-qqSjnVXF.mjs.map → radix-tree-CccjvyTP.mjs.map} +1 -1
  55. package/dist/{request-B-Nct5f7.mjs → request-CppAFyqX.mjs} +1 -1
  56. package/dist/{request-B-Nct5f7.mjs.map → request-CppAFyqX.mjs.map} +1 -1
  57. package/dist/{response-BMfdEcTm.d.mts → response-BNLzz4Tq.d.mts} +2 -2
  58. package/dist/{middleware-CewKbtb4.mjs → response-CQ1IgWei.mjs} +55 -55
  59. package/dist/response-CQ1IgWei.mjs.map +1 -0
  60. package/dist/{response-BnkYA4pj.mjs → response-DNdvtn-K.mjs} +1 -1
  61. package/dist/{response-BnkYA4pj.mjs.map → response-DNdvtn-K.mjs.map} +1 -1
  62. package/dist/{route-registry-emTmRrWQ.mjs → route-registry-BzExlM2t.mjs} +23 -9
  63. package/dist/route-registry-BzExlM2t.mjs.map +1 -0
  64. package/dist/{route-registry-CmABJA2V.d.mts → route-registry-CDBB0GI1.d.mts} +21 -7
  65. package/dist/router/index.d.mts +2 -4
  66. package/dist/router/index.mjs +3 -3
  67. package/dist/router/radix-tree.d.mts +1 -3
  68. package/dist/router/radix-tree.mjs +1 -1
  69. package/dist/router.d.mts +4 -7
  70. package/dist/router.mjs +27 -2
  71. package/dist/router.mjs.map +1 -0
  72. package/dist/{serve-48LEIkPa.mjs → serve-Df3HzwZM.mjs} +3 -3
  73. package/dist/{serve-48LEIkPa.mjs.map → serve-Df3HzwZM.mjs.map} +1 -1
  74. package/dist/{serve-AG80VaIr.d.mts → serve-DlzxgOhz.d.mts} +1 -1
  75. package/dist/serve.d.mts +1 -1
  76. package/dist/serve.mjs +2 -2
  77. package/dist/server/base-server.d.mts +1 -3
  78. package/dist/server/base-server.mjs +1 -1
  79. package/dist/server/component-server.d.mts +1 -4
  80. package/dist/server/component-server.mjs +2 -2
  81. package/dist/server/index.d.mts +5 -6
  82. package/dist/server/index.mjs +6 -6
  83. package/dist/server/server-factory.d.mts +3 -6
  84. package/dist/server/server-factory.mjs +5 -5
  85. package/dist/server/server.d.mts +2 -4
  86. package/dist/server/server.mjs +2 -2
  87. package/dist/{server-OUUug5DR.mjs → server-Bm0BGm01.mjs} +19 -30
  88. package/dist/server-Bm0BGm01.mjs.map +1 -0
  89. package/dist/server-CW1cdqGD.d.mts +48 -0
  90. package/dist/{server-BUom6ISO.mjs → server-CZLmrJSk.mjs} +3 -3
  91. package/dist/server-CZLmrJSk.mjs.map +1 -0
  92. package/dist/{sse-BgLhEo43.d.mts → sse-5HykEmSm.d.mts} +2 -4
  93. package/dist/{sse-CBl-szg1.mjs → sse-CWNz0ky7.mjs} +3 -4
  94. package/dist/sse-CWNz0ky7.mjs.map +1 -0
  95. package/dist/types/component-route.d.mts +1 -1
  96. package/dist/types/index.d.mts +3 -6
  97. package/dist/types/index.mjs +1 -3
  98. package/dist/types/types.d.mts +2 -2
  99. package/dist/types-B8Z3cMtZ.d.mts +12 -0
  100. package/dist/utils/base64url.d.mts +1 -1
  101. package/dist/utils/base64url.mjs +1 -1
  102. package/dist/utils/contract.d.mts +2 -0
  103. package/dist/utils/contract.mjs +3 -0
  104. package/dist/utils/dependency-manager.d.mts +1 -1
  105. package/dist/utils/dependency-manager.mjs +1 -1
  106. package/dist/utils/formats.d.mts +1 -1
  107. package/dist/utils/go-await.d.mts +1 -1
  108. package/dist/utils/go-await.mjs +1 -1
  109. package/dist/utils/handle.d.mts +13 -2
  110. package/dist/utils/handle.mjs +19 -3
  111. package/dist/utils/handle.mjs.map +1 -0
  112. package/dist/utils/html-renderer.d.mts +1 -1
  113. package/dist/utils/html-renderer.mjs +1 -1
  114. package/dist/utils/index.d.mts +13 -17
  115. package/dist/utils/index.mjs +11 -13
  116. package/dist/utils/parsers.d.mts +1 -1
  117. package/dist/utils/parsers.mjs +1 -1
  118. package/dist/utils/path-matcher.mjs +1 -1
  119. package/dist/utils/response.d.mts +1 -4
  120. package/dist/utils/response.mjs +1 -1
  121. package/dist/utils/route-registry.d.mts +3 -4
  122. package/dist/utils/route-registry.mjs +2 -2
  123. package/dist/utils/sse.d.mts +2 -2
  124. package/dist/utils/sse.mjs +3 -3
  125. package/dist/utils/validators/validators.d.mts +1 -1
  126. package/dist/utils/validators/validators.mjs +1 -1
  127. package/dist/{validators-Ch71zkT8.d.mts → validators-BFC6S_fr.d.mts} +1 -1
  128. package/dist/{validators-DBkyw6BG.mjs → validators-CkfvNBbK.mjs} +1 -1
  129. package/dist/{validators-DBkyw6BG.mjs.map → validators-CkfvNBbK.mjs.map} +1 -1
  130. package/package.json +1 -1
  131. package/dist/base-server-B7MYJNsl.mjs.map +0 -1
  132. package/dist/component-server-DomPJ_7S.mjs.map +0 -1
  133. package/dist/create-handler-DKw-sQOV.d.mts +0 -87
  134. package/dist/create-handler-RconAcAB.mjs +0 -165
  135. package/dist/create-handler-RconAcAB.mjs.map +0 -1
  136. package/dist/handle-BhR3oyky.d.mts +0 -15
  137. package/dist/handle-BxJwSvV0.mjs +0 -30
  138. package/dist/handle-BxJwSvV0.mjs.map +0 -1
  139. package/dist/middleware-CewKbtb4.mjs.map +0 -1
  140. package/dist/request-validator-Bz9X48FX.mjs +0 -77
  141. package/dist/request-validator-Bz9X48FX.mjs.map +0 -1
  142. package/dist/request-validator-Coo8dI-p.d.mts +0 -67
  143. package/dist/route-6A7umH7b.d.mts +0 -44
  144. package/dist/route-Ds53PR4M.mjs +0 -11
  145. package/dist/route-Ds53PR4M.mjs.map +0 -1
  146. package/dist/route-registry-emTmRrWQ.mjs.map +0 -1
  147. package/dist/router-CgYfGB4J.mjs +0 -98
  148. package/dist/router-CgYfGB4J.mjs.map +0 -1
  149. package/dist/schema-1fwiv7cm.mjs +0 -1
  150. package/dist/schema-B6DFN5c2.d.mts +0 -81
  151. package/dist/server-BUom6ISO.mjs.map +0 -1
  152. package/dist/server-C2RPKSvC.d.mts +0 -51
  153. package/dist/server-OUUug5DR.mjs.map +0 -1
  154. package/dist/sse-CBl-szg1.mjs.map +0 -1
  155. package/dist/types/route.d.mts +0 -2
  156. package/dist/types/route.mjs +0 -3
  157. package/dist/types/schema.d.mts +0 -2
  158. package/dist/types/schema.mjs +0 -1
  159. package/dist/types-D1PUFkda.d.mts +0 -45
  160. package/dist/utils/create-handler.d.mts +0 -3
  161. package/dist/utils/create-handler.mjs +0 -6
  162. package/dist/utils/request-validator.d.mts +0 -3
  163. package/dist/utils/request-validator.mjs +0 -5
  164. /package/dist/{component-route-DNgAj6VC.mjs → component-route-BiUHBq7a.mjs} +0 -0
  165. /package/dist/{index-CREkvfw9.d.mts → index-Dflz2i1X.d.mts} +0 -0
@@ -1,165 +0,0 @@
1
- import { o as json } from "./middleware-CewKbtb4.mjs";
2
- import { a as parseCookies, l as parseHeaders, r as parseBody, u as parseQuery } from "./parsers-DpH_mD0H.mjs";
3
- import { t as goAwait } from "./go-await-C4ZdEUwY.mjs";
4
- import { a as validateAllSchemas, i as precompileSchemas } from "./validators-DBkyw6BG.mjs";
5
-
6
- //#region src/utils/create-handler.ts
7
- /**
8
- * 自动响应转换
9
- * 将各种返回值类型转换为 Response 对象
10
- */
11
- function autoResponse(result) {
12
- if (result instanceof Response) return result;
13
- if (result === null || result === void 0) return new Response(null, { status: 204 });
14
- if (typeof result === "string") return new Response(result, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
15
- if (typeof result === "number" || typeof result === "boolean") return new Response(String(result), { headers: { "Content-Type": "text/plain; charset=utf-8" } });
16
- if (typeof result === "object") {
17
- const obj = result;
18
- if ("data" in obj && ("status" in obj || "headers" in obj)) {
19
- const { data, status = 200, headers = {} } = obj;
20
- if (data === null || data === void 0) return new Response(null, {
21
- status: status === 200 ? 204 : status,
22
- headers
23
- });
24
- if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") return new Response(String(data), {
25
- status,
26
- headers: {
27
- "Content-Type": "text/plain; charset=utf-8",
28
- ...headers
29
- }
30
- });
31
- return json(data, status, headers);
32
- }
33
- return json(result);
34
- }
35
- return new Response(null, { status: 204 });
36
- }
37
- /**
38
- * 处理验证错误
39
- */
40
- function handleValidationError(error) {
41
- return json({
42
- success: false,
43
- error: "Validation Error",
44
- message: error.message,
45
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
46
- }, 400);
47
- }
48
- /**
49
- * 处理内部错误
50
- */
51
- function handleInternalError(error) {
52
- return json({
53
- success: false,
54
- error: "Internal Error",
55
- message: error instanceof Error ? error.message : "未知错误"
56
- }, 500);
57
- }
58
- /**
59
- * 判断是否为 handler 函数
60
- */
61
- function isHandler(value) {
62
- return typeof value === "function";
63
- }
64
- function createHandler(schemaOrHandler, maybeHandler) {
65
- const hasSchema = !isHandler(schemaOrHandler);
66
- const schema = hasSchema ? schemaOrHandler : {};
67
- const handler = hasSchema ? maybeHandler : schemaOrHandler;
68
- if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) precompileSchemas(schema);
69
- const handlerFn = async (req) => {
70
- try {
71
- const query = parseQuery(req);
72
- const headers = parseHeaders(req);
73
- const cookies = parseCookies(req);
74
- const params = req.params || {};
75
- let body = void 0;
76
- if (req.method !== "GET" && req.method !== "HEAD") {
77
- const [, parsedBody] = await goAwait(parseBody(req));
78
- body = parsedBody;
79
- }
80
- const data = {
81
- body,
82
- query,
83
- params,
84
- headers,
85
- cookies
86
- };
87
- if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) validateAllSchemas(schema, data);
88
- return autoResponse(await handler({
89
- req,
90
- body,
91
- query,
92
- params,
93
- headers,
94
- cookies
95
- }));
96
- } catch (error) {
97
- if (error instanceof Error && error.message.includes("验证失败")) return handleValidationError(error);
98
- return handleInternalError(error);
99
- }
100
- };
101
- return handlerFn;
102
- }
103
- function createHandlerWithExtra(schemaOrHandler, maybeHandler) {
104
- const hasSchema = !isHandler(schemaOrHandler);
105
- const schema = hasSchema ? schemaOrHandler : {};
106
- const handler = hasSchema ? maybeHandler : schemaOrHandler;
107
- if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) precompileSchemas(schema);
108
- return async (req) => {
109
- try {
110
- const query = parseQuery(req);
111
- const headers = parseHeaders(req);
112
- const cookies = parseCookies(req);
113
- const params = req.params || {};
114
- let body = void 0;
115
- if (req.method !== "GET" && req.method !== "HEAD") {
116
- const [, parsedBody] = await goAwait(parseBody(req));
117
- body = parsedBody;
118
- }
119
- const data = {
120
- body,
121
- query,
122
- params,
123
- headers,
124
- cookies
125
- };
126
- if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) validateAllSchemas(schema, data);
127
- const extras = req.__locals ?? {};
128
- return autoResponse(await handler({
129
- req,
130
- body,
131
- query,
132
- params,
133
- headers,
134
- cookies,
135
- ...extras
136
- }));
137
- } catch (error) {
138
- if (error instanceof Error && error.message.includes("验证失败")) return handleValidationError(error);
139
- return handleInternalError(error);
140
- }
141
- };
142
- }
143
- /**
144
- * 简单的路由处理器 (无 schema 验证,只有 req)
145
- *
146
- * @example
147
- * ```typescript
148
- * simpleHandler(({ req }) => {
149
- * return { message: "Hello World" };
150
- * })
151
- * ```
152
- */
153
- function simpleHandler(handler) {
154
- return async (req) => {
155
- try {
156
- return autoResponse(await handler({ req }));
157
- } catch (error) {
158
- return handleInternalError(error);
159
- }
160
- };
161
- }
162
-
163
- //#endregion
164
- export { createHandlerWithExtra as n, simpleHandler as r, createHandler as t };
165
- //# sourceMappingURL=create-handler-RconAcAB.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-handler-RconAcAB.mjs","names":[],"sources":["../src/utils/create-handler.ts"],"sourcesContent":["/**\n * 类型安全的路由处理器工厂\n *\n * 非柯里化设计,API 更简洁\n *\n * @author Framework Team\n * @version 3.0.0\n * @license MIT\n */\n\nimport type {\n RouteSchema,\n HandlerContext,\n HandlerContextWithExtra,\n} from \"../types/schema\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { goAwait } from \"./go-await\";\nimport { json } from \"./response\";\nimport {\n validateAllSchemas,\n precompileSchemas,\n} from \"./validators/validators\";\n\n/**\n * 自动响应转换\n * 将各种返回值类型转换为 Response 对象\n */\nfunction autoResponse(result: unknown): Response {\n // 已经是 Response\n if (result instanceof Response) {\n return result;\n }\n\n // null/undefined -> 204\n if (result === null || result === undefined) {\n return new Response(null, { status: 204 });\n }\n\n // 字符串 -> text/plain\n if (typeof result === \"string\") {\n return new Response(result, {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 数字/布尔 -> text/plain\n if (typeof result === \"number\" || typeof result === \"boolean\") {\n return new Response(String(result), {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 对象 -> 检查是否是 { data, status, headers } 格式\n if (typeof result === \"object\") {\n const obj = result as Record<string, unknown>;\n if (\"data\" in obj && (\"status\" in obj || \"headers\" in obj)) {\n const { data, status = 200, headers = {} } = obj;\n\n if (data === null || data === undefined) {\n return new Response(null, {\n status: status === 200 ? 204 : (status as number),\n headers: headers as HeadersInit,\n });\n }\n\n if (\n typeof data === \"string\" ||\n typeof data === \"number\" ||\n typeof data === \"boolean\"\n ) {\n return new Response(String(data), {\n status: status as number,\n headers: {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...(headers as Record<string, string>),\n },\n });\n }\n\n return json(data, status as number, headers as Record<string, string>);\n }\n\n // 普通对象 -> JSON\n return json(result);\n }\n\n // 其他类型 -> 204\n return new Response(null, { status: 204 });\n}\n\n/**\n * 处理验证错误\n */\nfunction handleValidationError(error: Error): Response {\n return json(\n {\n success: false,\n error: \"Validation Error\",\n message: error.message,\n timestamp: new Date().toISOString(),\n },\n 400,\n );\n}\n\n/**\n * 处理内部错误\n */\nfunction handleInternalError(error: unknown): Response {\n return json(\n {\n success: false,\n error: \"Internal Error\",\n message: error instanceof Error ? error.message : \"未知错误\",\n },\n 500,\n );\n}\n\n/** 空 schema 的上下文类型 */\ntype EmptySchemaContext = {\n req: Request;\n body: unknown;\n query: Record<string, string>;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n};\n\n/**\n * 判断是否为 handler 函数\n */\nfunction isHandler(value: unknown): value is (...args: unknown[]) => unknown {\n return typeof value === \"function\";\n}\n\n/**\n * 创建类型安全的路由处理器\n *\n * @example\n * ```typescript\n * // 无 schema - 直接传入 handler\n * createHandler(({ params }) => `User: ${params.id}`)\n *\n * // 有 schema - 传入 schema 和 handler\n * createHandler(\n * { body: Type.Object({ name: Type.String() }) },\n * ({ body }) => ({ hello: body.name })\n * )\n * ```\n */\n/**\n * 带类型推断的 Handler - 保留返回类型信息用于客户端类型推断\n */\nexport type InferableHandler<TReturn, TSchema extends RouteSchema = RouteSchema> = ((req: Request) => Promise<Response>) & {\n /** 返回类型标记(仅用于类型推断,运行时不存在) */\n __returnType: TReturn;\n /** Schema 类型标记 */\n __schema: TSchema;\n};\n\n\n// 重载 1: 无 schema\nexport function createHandler<R>(\n handler: (ctx: EmptySchemaContext) => R | Promise<R>,\n): InferableHandler<R>;\n\n// 重载 2: 有 schema\nexport function createHandler<const T extends RouteSchema, R>(\n schema: T,\n handler: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T>;\n\n// 实现\nexport function createHandler<const T extends RouteSchema, R>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (ctx: HandlerContext<T>) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n const handlerFn = async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n });\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n\n // 类型断言:这些属性只在编译时用于类型推断,运行时不存在\n return handlerFn as InferableHandler<R, T>;\n}\n\n/**\n * 创建带额外上下文的路由处理器\n *\n * 用于中间件注入额外数据的场景\n *\n * @example\n * ```typescript\n * // 定义中间件注入的类型\n * type AuthContext = { user: { id: string; role: string } };\n *\n * // 无 schema\n * createHandlerWithExtra<AuthContext>(({ user }) => {\n * return { userId: user.id };\n * })\n *\n * // 有 schema\n * createHandlerWithExtra<AuthContext>(\n * { body: Type.Object({ action: Type.String() }) },\n * ({ body, user }) => ({ success: true, userId: user.id })\n * )\n * ```\n */\n// 重载 1: 无 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n R = unknown,\n>(\n handler: (ctx: EmptySchemaContext & TExtra) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 重载 2: 有 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schema: T,\n handler: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 实现\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext & TExtra) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (\n ctx: HandlerContextWithExtra<T, TExtra>,\n ) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 获取中间件注入的额外数据\n const extras = ((req as unknown as Record<string, unknown>).__locals ??\n {}) as TExtra;\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n ...extras,\n } as HandlerContextWithExtra<T, TExtra>);\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n}\n\n/**\n * 简单的路由处理器 (无 schema 验证,只有 req)\n *\n * @example\n * ```typescript\n * simpleHandler(({ req }) => {\n * return { message: \"Hello World\" };\n * })\n * ```\n */\nexport function simpleHandler<R>(\n handler: (ctx: { req: Request }) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n return async (req: Request): Promise<Response> => {\n try {\n const result = await handler({ req });\n return autoResponse(result);\n } catch (error) {\n return handleInternalError(error);\n }\n };\n}\n"],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- //#region src/utils/handle.d.ts
2
- /** 获取单个 Cookie 值 */
3
- declare function getCookie(req: Request, key: string): string | null;
4
- /** 生成 Set-Cookie 头 */
5
- declare function setCookie(key: string, value: string, options?: {
6
- path?: string;
7
- httpOnly?: boolean;
8
- maxAge?: number;
9
- secure?: boolean;
10
- }): string;
11
- declare function setLocals<T extends object>(req: Request, extras: T): void;
12
- declare function getLocals<T extends object>(req: Request): T;
13
- //#endregion
14
- export { setLocals as i, getLocals as n, setCookie as r, getCookie as t };
15
- //# sourceMappingURL=handle-BhR3oyky.d.mts.map
@@ -1,30 +0,0 @@
1
- import { a as parseCookies } from "./parsers-DpH_mD0H.mjs";
2
-
3
- //#region src/utils/handle.ts
4
- /** 获取单个 Cookie 值 */
5
- function getCookie(req, key) {
6
- return parseCookies(req)[key] || null;
7
- }
8
- /** 生成 Set-Cookie 头 */
9
- function setCookie(key, value, options = {}) {
10
- let cookie = `${key}=${encodeURIComponent(value)}`;
11
- if (options.path) cookie += `; Path=${options.path}`;
12
- if (options.httpOnly) cookie += `; HttpOnly`;
13
- if (options.secure) cookie += `; Secure`;
14
- if (options.maxAge) cookie += `; Max-Age=${options.maxAge}`;
15
- return cookie;
16
- }
17
- function setLocals(req, extras) {
18
- const target = req;
19
- target.__locals = {
20
- ...target.__locals ?? {},
21
- ...extras
22
- };
23
- }
24
- function getLocals(req) {
25
- return req.__locals ?? {};
26
- }
27
-
28
- //#endregion
29
- export { setLocals as i, getLocals as n, setCookie as r, getCookie as t };
30
- //# sourceMappingURL=handle-BxJwSvV0.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle-BxJwSvV0.mjs","names":[],"sources":["../src/utils/handle.ts"],"sourcesContent":["import { parseCookies } from \"./parsers\";\n\n/** 获取单个 Cookie 值 */\nexport function getCookie(req: Request, key: string): string | null {\n const cookies = parseCookies(req);\n return cookies[key] || null;\n}\n\n/** 生成 Set-Cookie 头 */\nexport function setCookie(\n key: string,\n value: string,\n options: {\n path?: string;\n httpOnly?: boolean;\n maxAge?: number;\n secure?: boolean;\n } = {},\n): string {\n let cookie = `${key}=${encodeURIComponent(value)}`;\n\n if (options.path) cookie += `; Path=${options.path}`;\n if (options.httpOnly) cookie += `; HttpOnly`;\n if (options.secure) cookie += `; Secure`;\n if (options.maxAge) cookie += `; Max-Age=${options.maxAge}`;\n\n return cookie;\n}\n\n// 提供给中间件写入\"局部上下文\"的工具函数\nexport function setLocals<T extends object>(req: Request, extras: T) {\n const target = req as unknown as Record<string, unknown>;\n target.__locals = { ...((target.__locals as object) ?? {}), ...extras };\n}\n\n// 获取中间件注入的局部上下文\nexport function getLocals<T extends object>(req: Request): T {\n const target = req as unknown as Record<string, unknown>;\n return (target.__locals ?? {}) as T;\n}\n"],"mappings":";;;;AAGA,SAAgB,UAAU,KAAc,KAA4B;AAElE,QADgB,aAAa,IAAI,CAClB,QAAQ;;;AAIzB,SAAgB,UACd,KACA,OACA,UAKI,EAAE,EACE;CACR,IAAI,SAAS,GAAG,IAAI,GAAG,mBAAmB,MAAM;AAEhD,KAAI,QAAQ,KAAM,WAAU,UAAU,QAAQ;AAC9C,KAAI,QAAQ,SAAU,WAAU;AAChC,KAAI,QAAQ,OAAQ,WAAU;AAC9B,KAAI,QAAQ,OAAQ,WAAU,aAAa,QAAQ;AAEnD,QAAO;;AAIT,SAAgB,UAA4B,KAAc,QAAW;CACnE,MAAM,SAAS;AACf,QAAO,WAAW;EAAE,GAAK,OAAO,YAAuB,EAAE;EAAG,GAAG;EAAQ;;AAIzE,SAAgB,UAA4B,KAAiB;AAE3D,QADe,IACA,YAAY,EAAE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware-CewKbtb4.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,77 +0,0 @@
1
- import { a as parseCookies, l as parseHeaders, r as parseBody, u as parseQuery } from "./parsers-DpH_mD0H.mjs";
2
- import { a as validateAllSchemas } from "./validators-DBkyw6BG.mjs";
3
-
4
- //#region src/utils/request-validator.ts
5
- /**
6
- * 解析Request对象,提取所有相关数据
7
- * @param request Request对象
8
- * @param params 路径参数(可选)
9
- * @returns 解析后的请求数据
10
- */
11
- async function parseRequest(request, params) {
12
- const requestData = {
13
- body: void 0,
14
- query: parseQuery(request),
15
- params: params || {},
16
- headers: parseHeaders(request),
17
- cookies: parseCookies(request)
18
- };
19
- if (request.method !== "GET" && request.method !== "HEAD") requestData.body = await parseBody(request);
20
- return requestData;
21
- }
22
- /**
23
- * 验证请求数据
24
- * @param config Schema配置
25
- * @param requestData 请求数据
26
- * @returns 验证结果
27
- */
28
- function validateRequest(config, requestData) {
29
- try {
30
- return {
31
- success: true,
32
- data: validateAllSchemas(config, requestData)
33
- };
34
- } catch (error) {
35
- return {
36
- success: false,
37
- errors: [{
38
- field: "unknown",
39
- message: error instanceof Error ? error.message : "验证失败"
40
- }]
41
- };
42
- }
43
- }
44
- /**
45
- * 完整的请求解析和验证流程
46
- * @param request Request对象
47
- * @param config Schema配置
48
- * @param params 路径参数(可选)
49
- * @returns 验证结果
50
- */
51
- async function parseAndValidateRequest(request, config, params) {
52
- try {
53
- return validateRequest(config, await parseRequest(request, params));
54
- } catch (error) {
55
- return {
56
- success: false,
57
- errors: [{
58
- field: "unknown",
59
- message: error instanceof Error ? error.message : "请求解析失败"
60
- }]
61
- };
62
- }
63
- }
64
- /**
65
- * 创建类型安全的请求验证器工厂
66
- * @param config Schema配置
67
- * @returns 验证器函数
68
- */
69
- function createRequestValidator(config) {
70
- return async (request, params) => {
71
- return parseAndValidateRequest(request, config, params);
72
- };
73
- }
74
-
75
- //#endregion
76
- export { validateRequest as i, parseAndValidateRequest as n, parseRequest as r, createRequestValidator as t };
77
- //# sourceMappingURL=request-validator-Bz9X48FX.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"request-validator-Bz9X48FX.mjs","names":[],"sources":["../src/utils/request-validator.ts"],"sourcesContent":["/**\n * 请求解析和验证器\n *\n * 解析handler的req参数,使用Ultra验证器进行验证,\n * 并类型安全地返回解析出来的值\n *\n * @author Framework Team\n * @version 1.0.0\n * @license MIT\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { Static } from \"@sinclair/typebox\";\nimport {\n validateAllSchemas,\n type SchemaConfig,\n} from \"./validators/validators\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\n\n// 请求数据结构\nexport interface RequestData {\n body: unknown;\n query: unknown;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}\n\n// 验证后的请求数据类型\nexport interface ValidatedRequestData<T extends SchemaConfig> {\n body: T[\"body\"] extends TSchema ? Static<T[\"body\"]> : unknown;\n query: T[\"query\"] extends TSchema ? Static<T[\"query\"]> : unknown;\n params: T[\"params\"] extends TSchema\n ? Static<T[\"params\"]>\n : Record<string, string>;\n headers: T[\"headers\"] extends TSchema\n ? Static<T[\"headers\"]>\n : Record<string, string>;\n cookies: T[\"cookies\"] extends TSchema\n ? Static<T[\"cookies\"]>\n : Record<string, string>;\n}\n\n// 验证结果\nexport interface ValidationResult<T extends SchemaConfig> {\n success: boolean;\n data?: ValidatedRequestData<T>;\n errors?: Array<{ field: keyof SchemaConfig; message: string }>;\n}\n\n/**\n * 解析Request对象,提取所有相关数据\n * @param request Request对象\n * @param params 路径参数(可选)\n * @returns 解析后的请求数据\n */\nexport async function parseRequest(\n request: Request,\n params?: Record<string, string>,\n): Promise<RequestData> {\n const requestData: RequestData = {\n body: undefined,\n query: parseQuery(request),\n params: params || {},\n headers: parseHeaders(request),\n cookies: parseCookies(request),\n };\n\n // 对于非GET请求,尝试解析请求体\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n requestData.body = await parseBody(request);\n }\n\n return requestData;\n}\n\n/**\n * 验证请求数据\n * @param config Schema配置\n * @param requestData 请求数据\n * @returns 验证结果\n */\nexport function validateRequest<T extends SchemaConfig>(\n config: T,\n requestData: RequestData,\n): ValidationResult<T> {\n try {\n const validatedData = validateAllSchemas(config, requestData);\n\n return {\n success: true,\n data: validatedData as ValidatedRequestData<T>,\n };\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"验证失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 完整的请求解析和验证流程\n * @param request Request对象\n * @param config Schema配置\n * @param params 路径参数(可选)\n * @returns 验证结果\n */\nexport async function parseAndValidateRequest<T extends SchemaConfig>(\n request: Request,\n config: T,\n params?: Record<string, string>,\n): Promise<ValidationResult<T>> {\n try {\n // 1. 解析请求\n const requestData = await parseRequest(request, params);\n\n // 2. 验证数据\n return validateRequest(config, requestData);\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"请求解析失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 创建类型安全的请求验证器工厂\n * @param config Schema配置\n * @returns 验证器函数\n */\nexport function createRequestValidator<T extends SchemaConfig>(config: T) {\n return async (request: Request, params?: Record<string, string>) => {\n return parseAndValidateRequest(request, config, params);\n };\n}\n"],"mappings":";;;;;;;;;;AAwDA,eAAsB,aACpB,SACA,QACsB;CACtB,MAAM,cAA2B;EAC/B,MAAM;EACN,OAAO,WAAW,QAAQ;EAC1B,QAAQ,UAAU,EAAE;EACpB,SAAS,aAAa,QAAQ;EAC9B,SAAS,aAAa,QAAQ;EAC/B;AAGD,KAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,OACjD,aAAY,OAAO,MAAM,UAAU,QAAQ;AAG7C,QAAO;;;;;;;;AAST,SAAgB,gBACd,QACA,aACqB;AACrB,KAAI;AAGF,SAAO;GACL,SAAS;GACT,MAJoB,mBAAmB,QAAQ,YAAY;GAK5D;UACM,OAAO;AACd,SAAO;GACL,SAAS;GACT,QAAQ,CACN;IACE,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IACnD,CACF;GACF;;;;;;;;;;AAWL,eAAsB,wBACpB,SACA,QACA,QAC8B;AAC9B,KAAI;AAKF,SAAO,gBAAgB,QAHH,MAAM,aAAa,SAAS,OAAO,CAGZ;UACpC,OAAO;AACd,SAAO;GACL,SAAS;GACT,QAAQ,CACN;IACE,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IACnD,CACF;GACF;;;;;;;;AASL,SAAgB,uBAA+C,QAAW;AACxE,QAAO,OAAO,SAAkB,WAAoC;AAClE,SAAO,wBAAwB,SAAS,QAAQ,OAAO"}
@@ -1,67 +0,0 @@
1
- import { t as SchemaConfig } from "./validators-Ch71zkT8.mjs";
2
- import { Static, TSchema } from "@sinclair/typebox";
3
-
4
- //#region src/utils/request-validator.d.ts
5
- /**
6
- * 请求解析和验证器
7
- *
8
- * 解析handler的req参数,使用Ultra验证器进行验证,
9
- * 并类型安全地返回解析出来的值
10
- *
11
- * @author Framework Team
12
- * @version 1.0.0
13
- * @license MIT
14
- */
15
- interface RequestData {
16
- body: unknown;
17
- query: unknown;
18
- params: Record<string, string>;
19
- headers: Record<string, string>;
20
- cookies: Record<string, string>;
21
- }
22
- interface ValidatedRequestData<T extends SchemaConfig> {
23
- body: T["body"] extends TSchema ? Static<T["body"]> : unknown;
24
- query: T["query"] extends TSchema ? Static<T["query"]> : unknown;
25
- params: T["params"] extends TSchema ? Static<T["params"]> : Record<string, string>;
26
- headers: T["headers"] extends TSchema ? Static<T["headers"]> : Record<string, string>;
27
- cookies: T["cookies"] extends TSchema ? Static<T["cookies"]> : Record<string, string>;
28
- }
29
- interface ValidationResult<T extends SchemaConfig> {
30
- success: boolean;
31
- data?: ValidatedRequestData<T>;
32
- errors?: Array<{
33
- field: keyof SchemaConfig;
34
- message: string;
35
- }>;
36
- }
37
- /**
38
- * 解析Request对象,提取所有相关数据
39
- * @param request Request对象
40
- * @param params 路径参数(可选)
41
- * @returns 解析后的请求数据
42
- */
43
- declare function parseRequest(request: Request, params?: Record<string, string>): Promise<RequestData>;
44
- /**
45
- * 验证请求数据
46
- * @param config Schema配置
47
- * @param requestData 请求数据
48
- * @returns 验证结果
49
- */
50
- declare function validateRequest<T extends SchemaConfig>(config: T, requestData: RequestData): ValidationResult<T>;
51
- /**
52
- * 完整的请求解析和验证流程
53
- * @param request Request对象
54
- * @param config Schema配置
55
- * @param params 路径参数(可选)
56
- * @returns 验证结果
57
- */
58
- declare function parseAndValidateRequest<T extends SchemaConfig>(request: Request, config: T, params?: Record<string, string>): Promise<ValidationResult<T>>;
59
- /**
60
- * 创建类型安全的请求验证器工厂
61
- * @param config Schema配置
62
- * @returns 验证器函数
63
- */
64
- declare function createRequestValidator<T extends SchemaConfig>(config: T): (request: Request, params?: Record<string, string>) => Promise<ValidationResult<T>>;
65
- //#endregion
66
- export { parseAndValidateRequest as a, createRequestValidator as i, ValidatedRequestData as n, parseRequest as o, ValidationResult as r, validateRequest as s, RequestData as t };
67
- //# sourceMappingURL=request-validator-Coo8dI-p.d.mts.map
@@ -1,44 +0,0 @@
1
- import { c as ResponseBody, l as Route } from "./types-D1PUFkda.mjs";
2
-
3
- //#region src/types/route.d.ts
4
- interface Middleware {
5
- (req: Request, next: () => Promise<Response>): Promise<Response>;
6
- }
7
- interface BaseRouteConfig {
8
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
9
- path: string;
10
- handler: (req: Request) => ResponseBody | Promise<ResponseBody>;
11
- }
12
- interface ExtendedRouteConfig extends BaseRouteConfig {
13
- middleware?: Middleware[];
14
- body?: any;
15
- query?: any;
16
- params?: any;
17
- headers?: any;
18
- cookies?: any;
19
- docs?: {
20
- description?: string;
21
- tags?: string[];
22
- security?: any[];
23
- responses?: Record<string, any>;
24
- };
25
- timeout?: number;
26
- maxBodySize?: string;
27
- [key: string]: any;
28
- }
29
- interface NestedRouteConfig {
30
- path: string;
31
- middleware?: Middleware[];
32
- children?: (NestedRouteConfig | ExtendedRouteConfig)[];
33
- }
34
- type TypedRoute = ExtendedRouteConfig;
35
- type CompatibleRoute = Route | TypedRoute;
36
- interface FlattenedRoute extends ExtendedRouteConfig {
37
- fullPath: string;
38
- middlewareChain: Middleware[];
39
- }
40
- declare function createTypedRoute(config: ExtendedRouteConfig): ExtendedRouteConfig;
41
- declare function isTypedRoute(route: any): route is TypedRoute;
42
- //#endregion
43
- export { Middleware as a, createTypedRoute as c, FlattenedRoute as i, isTypedRoute as l, CompatibleRoute as n, NestedRouteConfig as o, ExtendedRouteConfig as r, TypedRoute as s, BaseRouteConfig as t };
44
- //# sourceMappingURL=route-6A7umH7b.d.mts.map
@@ -1,11 +0,0 @@
1
- //#region src/types/route.ts
2
- function createTypedRoute(config) {
3
- return config;
4
- }
5
- function isTypedRoute(route) {
6
- return route && typeof route === "object" && "method" in route && "path" in route && "handler" in route;
7
- }
8
-
9
- //#endregion
10
- export { isTypedRoute as n, createTypedRoute as t };
11
- //# sourceMappingURL=route-Ds53PR4M.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-Ds53PR4M.mjs","names":[],"sources":["../src/types/route.ts"],"sourcesContent":["import { Route, ResponseBody } from \"./types\";\n\n// 定义中间件类型\nexport interface Middleware {\n (req: Request, next: () => Promise<Response>): Promise<Response>;\n}\n\n// 基础路由配置\nexport interface BaseRouteConfig {\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"OPTIONS\" | \"HEAD\";\n path: string;\n handler: (req: Request) => ResponseBody | Promise<ResponseBody>;\n}\n\n// 扩展的路由配置 - 只保留Schema验证和中间件\nexport interface ExtendedRouteConfig extends BaseRouteConfig {\n // Tirne 中间件系统\n middleware?: Middleware[];\n\n // Schema验证配置\n body?: any;\n query?: any;\n params?: any;\n headers?: any;\n cookies?: any;\n\n // 其他配置\n docs?: {\n description?: string;\n tags?: string[];\n security?: any[];\n responses?: Record<string, any>;\n };\n timeout?: number;\n maxBodySize?: string;\n\n // 允许任意扩展\n [key: string]: any;\n}\n\n// 嵌套路由配置\nexport interface NestedRouteConfig {\n path: string;\n middleware?: Middleware[];\n children?: (NestedRouteConfig | ExtendedRouteConfig)[];\n}\n\n// 类型安全的路由\nexport type TypedRoute = ExtendedRouteConfig;\n\n// 兼容类型:可以接受Route或TypedRoute\nexport type CompatibleRoute = Route | TypedRoute;\n\n// 扁平化后的路由,包含完整的中间件链\nexport interface FlattenedRoute extends ExtendedRouteConfig {\n fullPath: string;\n middlewareChain: Middleware[];\n}\n\n// 导出一些实际的函数,确保 JavaScript 代码生成\nexport function createTypedRoute(\n config: ExtendedRouteConfig,\n): ExtendedRouteConfig {\n return config;\n}\n\nexport function isTypedRoute(route: any): route is TypedRoute {\n return (\n route &&\n typeof route === \"object\" &&\n \"method\" in route &&\n \"path\" in route &&\n \"handler\" in route\n );\n}\n"],"mappings":";AA4DA,SAAgB,iBACd,QACqB;AACrB,QAAO;;AAGT,SAAgB,aAAa,OAAiC;AAC5D,QACE,SACA,OAAO,UAAU,YACjB,YAAY,SACZ,UAAU,SACV,aAAa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-registry-emTmRrWQ.mjs","names":[],"sources":["../src/utils/route-registry.ts"],"sourcesContent":["/**\n * 路由注册表\n *\n * 提供路由元信息的收集和查询能力\n * 可用于:API 文档生成、Webhook 事件注册、权限检查、审计日志等\n *\n * @example\n * ```typescript\n * // 创建注册表\n * const registry = createRouteRegistry(server.getRoutes())\n *\n * // 查询路由\n * const route = registry.get('POST', '/auth/signIn')\n *\n * // 筛选有 webhook 配置的路由\n * const webhookRoutes = registry.filter('webhook')\n *\n * // 按分类获取\n * const authRoutes = registry.getByCategory('auth')\n * ```\n */\n\nimport type { FlattenedRoute, Method } from '../types'\n\n/**\n * 路由元信息(不含 handler 和 middleware)\n */\nexport interface RouteMeta {\n method: Method\n path: string\n fullPath: string\n name?: string\n description?: string\n /** 扩展字段 */\n [key: string]: unknown\n}\n\n/**\n * 路由注册表\n *\n * 泛型 T 用于定义扩展字段的类型\n */\nexport class RouteRegistry<T extends Record<string, unknown> = Record<string, unknown>> {\n /** 所有路由元信息 */\n private routes: RouteMeta[] = []\n\n /** 路由映射表:METHOD:fullPath -> RouteMeta */\n private routeMap = new Map<string, RouteMeta>()\n\n /** 分类映射表:category -> RouteMeta[] */\n private categoryMap = new Map<string, RouteMeta[]>()\n\n constructor(routes: FlattenedRoute[]) {\n this.buildRegistry(routes)\n }\n\n /**\n * 构建注册表\n */\n private buildRegistry(routes: FlattenedRoute[]): void {\n for (const route of routes) {\n // 提取元信息(排除 handler 和 middleware)\n const meta: RouteMeta = {\n method: route.method,\n path: route.path,\n fullPath: route.fullPath,\n name: route.name,\n description: route.description,\n }\n\n // 复制扩展字段\n for (const key of Object.keys(route)) {\n if (!['method', 'path', 'fullPath', 'name', 'description', 'handler', 'middleware', 'middlewareChain'].includes(key)) {\n meta[key] = route[key as keyof FlattenedRoute]\n }\n }\n\n this.routes.push(meta)\n this.routeMap.set(`${route.method}:${route.fullPath}`, meta)\n\n // 按分类索引\n const category = this.extractCategory(route.fullPath)\n if (!this.categoryMap.has(category)) {\n this.categoryMap.set(category, [])\n }\n this.categoryMap.get(category)!.push(meta)\n }\n }\n\n /**\n * 提取分类(第一段路径)\n */\n private extractCategory(path: string): string {\n const segments = path.split('/').filter(Boolean)\n return segments[0] || 'root'\n }\n\n // ============================================\n // 查询接口\n // ============================================\n\n /**\n * 获取所有路由元信息\n */\n getAll(): RouteMeta[] {\n return [...this.routes]\n }\n\n /**\n * 按 method + path 查询路由\n */\n get(method: string, path: string): (RouteMeta & T) | undefined {\n return this.routeMap.get(`${method}:${path}`) as (RouteMeta & T) | undefined\n }\n\n /**\n * 检查路由是否存在\n */\n has(method: string, path: string): boolean {\n return this.routeMap.has(`${method}:${path}`)\n }\n\n /**\n * 按分类获取路由\n */\n getByCategory(category: string): RouteMeta[] {\n return this.categoryMap.get(category) || []\n }\n\n /**\n * 获取所有分类\n */\n getCategories(): string[] {\n return Array.from(this.categoryMap.keys()).sort()\n }\n\n /**\n * 筛选有特定字段的路由\n *\n * @example\n * ```typescript\n * // 获取所有配置了 webhook 的路由\n * const webhookRoutes = registry.filter('webhook')\n * ```\n */\n filter<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[] {\n return this.routes.filter((r) => field in r && r[field] !== undefined) as (RouteMeta & Record<K, unknown>)[]\n }\n\n /**\n * 按条件筛选路由\n *\n * @example\n * ```typescript\n * // 获取所有 POST 请求\n * const postRoutes = registry.filterBy(r => r.method === 'POST')\n * ```\n */\n filterBy(predicate: (route: RouteMeta) => boolean): RouteMeta[] {\n return this.routes.filter(predicate)\n }\n\n /**\n * 获取路由数量\n */\n get size(): number {\n return this.routes.length\n }\n\n /**\n * 遍历所有路由\n */\n forEach(callback: (route: RouteMeta, index: number) => void): void {\n this.routes.forEach(callback)\n }\n\n /**\n * 映射所有路由\n */\n map<R>(callback: (route: RouteMeta, index: number) => R): R[] {\n return this.routes.map(callback)\n }\n}\n\n/**\n * 创建路由注册表\n *\n * @example\n * ```typescript\n * // 定义扩展字段类型\n * interface MyRouteMeta {\n * webhook?: { eventKey: string }\n * permission?: string\n * }\n *\n * // 创建带类型的注册表\n * const registry = createRouteRegistry<MyRouteMeta>(server.getRoutes())\n *\n * // 类型安全的查询\n * const route = registry.get('POST', '/auth/signIn')\n * if (route?.webhook) {\n * console.log(route.webhook.eventKey)\n * }\n * ```\n */\nexport function createRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(\n routes: FlattenedRoute[]\n): RouteRegistry<T> {\n return new RouteRegistry<T>(routes)\n}\n\n// ============================================\n// 全局 Registry(单例模式)\n// ============================================\n\n/** 全局 registry 实例 */\nlet globalRegistry: RouteRegistry | null = null\n\n/**\n * 设置全局 registry(框架内部使用)\n * @internal\n */\nexport function setGlobalRegistry(registry: RouteRegistry): void {\n globalRegistry = registry\n}\n\n/**\n * 获取全局路由注册表\n *\n * @example\n * ```typescript\n * // 在任意文件中\n * import { getRouteRegistry } from 'vafast'\n *\n * const registry = getRouteRegistry()\n * const webhookRoutes = registry.filter('webhook')\n * ```\n *\n * @throws 如果 Server 尚未创建\n */\nexport function getRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(): RouteRegistry<T> {\n if (!globalRegistry) {\n throw new Error('RouteRegistry not initialized. Make sure Server is created first.')\n }\n return globalRegistry as RouteRegistry<T>\n}\n\n/**\n * 按 method + path 获取单个路由\n *\n * 便捷函数,无需先获取 registry\n *\n * @example\n * ```typescript\n * // 在中间件或接口中\n * import { getRoute } from 'vafast'\n *\n * const route = getRoute('POST', '/auth/signIn')\n * if (route?.webhook) {\n * console.log('This route has webhook:', route.webhook)\n * }\n * ```\n */\nexport function getRoute<T extends Record<string, unknown> = Record<string, unknown>>(\n method: string,\n path: string\n): (RouteMeta & T) | undefined {\n return getRouteRegistry<T>().get(method, path)\n}\n\n/**\n * 获取所有路由\n *\n * @example\n * ```typescript\n * import { getAllRoutes } from 'vafast'\n *\n * const routes = getAllRoutes()\n * console.log(`Total ${routes.length} routes`)\n * ```\n */\nexport function getAllRoutes(): RouteMeta[] {\n return getRouteRegistry().getAll()\n}\n\n/**\n * 筛选有特定字段的路由\n *\n * @example\n * ```typescript\n * import { filterRoutes } from 'vafast'\n *\n * // 获取所有配置了 webhook 的路由\n * const webhookRoutes = filterRoutes('webhook')\n * ```\n */\nexport function filterRoutes<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[] {\n return getRouteRegistry().filter(field)\n}\n\n"],"mappings":";;;;;;AA0CA,IAAa,gBAAb,MAAwF;;CAEtF,AAAQ,SAAsB,EAAE;;CAGhC,AAAQ,2BAAW,IAAI,KAAwB;;CAG/C,AAAQ,8BAAc,IAAI,KAA0B;CAEpD,YAAY,QAA0B;AACpC,OAAK,cAAc,OAAO;;;;;CAM5B,AAAQ,cAAc,QAAgC;AACpD,OAAK,MAAM,SAAS,QAAQ;GAE1B,MAAM,OAAkB;IACtB,QAAQ,MAAM;IACd,MAAM,MAAM;IACZ,UAAU,MAAM;IAChB,MAAM,MAAM;IACZ,aAAa,MAAM;IACpB;AAGD,QAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,KAAI,CAAC;IAAC;IAAU;IAAQ;IAAY;IAAQ;IAAe;IAAW;IAAc;IAAkB,CAAC,SAAS,IAAI,CAClH,MAAK,OAAO,MAAM;AAItB,QAAK,OAAO,KAAK,KAAK;AACtB,QAAK,SAAS,IAAI,GAAG,MAAM,OAAO,GAAG,MAAM,YAAY,KAAK;GAG5D,MAAM,WAAW,KAAK,gBAAgB,MAAM,SAAS;AACrD,OAAI,CAAC,KAAK,YAAY,IAAI,SAAS,CACjC,MAAK,YAAY,IAAI,UAAU,EAAE,CAAC;AAEpC,QAAK,YAAY,IAAI,SAAS,CAAE,KAAK,KAAK;;;;;;CAO9C,AAAQ,gBAAgB,MAAsB;AAE5C,SADiB,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAChC,MAAM;;;;;CAUxB,SAAsB;AACpB,SAAO,CAAC,GAAG,KAAK,OAAO;;;;;CAMzB,IAAI,QAAgB,MAA2C;AAC7D,SAAO,KAAK,SAAS,IAAI,GAAG,OAAO,GAAG,OAAO;;;;;CAM/C,IAAI,QAAgB,MAAuB;AACzC,SAAO,KAAK,SAAS,IAAI,GAAG,OAAO,GAAG,OAAO;;;;;CAM/C,cAAc,UAA+B;AAC3C,SAAO,KAAK,YAAY,IAAI,SAAS,IAAI,EAAE;;;;;CAM7C,gBAA0B;AACxB,SAAO,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC,CAAC,MAAM;;;;;;;;;;;CAYnD,OAAyB,OAA8C;AACrE,SAAO,KAAK,OAAO,QAAQ,MAAM,SAAS,KAAK,EAAE,WAAW,OAAU;;;;;;;;;;;CAYxE,SAAS,WAAuD;AAC9D,SAAO,KAAK,OAAO,OAAO,UAAU;;;;;CAMtC,IAAI,OAAe;AACjB,SAAO,KAAK,OAAO;;;;;CAMrB,QAAQ,UAA2D;AACjE,OAAK,OAAO,QAAQ,SAAS;;;;;CAM/B,IAAO,UAAuD;AAC5D,SAAO,KAAK,OAAO,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;AAyBpC,SAAgB,oBACd,QACkB;AAClB,QAAO,IAAI,cAAiB,OAAO;;;AAQrC,IAAI,iBAAuC;;;;;AAM3C,SAAgB,kBAAkB,UAA+B;AAC/D,kBAAiB;;;;;;;;;;;;;;;;AAiBnB,SAAgB,mBAAkG;AAChH,KAAI,CAAC,eACH,OAAM,IAAI,MAAM,oEAAoE;AAEtF,QAAO;;;;;;;;;;;;;;;;;;AAmBT,SAAgB,SACd,QACA,MAC6B;AAC7B,QAAO,kBAAqB,CAAC,IAAI,QAAQ,KAAK;;;;;;;;;;;;;AAchD,SAAgB,eAA4B;AAC1C,QAAO,kBAAkB,CAAC,QAAQ;;;;;;;;;;;;;AAcpC,SAAgB,aAA+B,OAA8C;AAC3F,QAAO,kBAAkB,CAAC,OAAO,MAAM"}
@@ -1,98 +0,0 @@
1
- //#region src/router.ts
2
- /**
3
- * 扁平化嵌套路由
4
- *
5
- * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链
6
- *
7
- * @example
8
- * ```typescript
9
- * const routes = flattenNestedRoutes([
10
- * {
11
- * path: "/api",
12
- * middleware: [authMiddleware],
13
- * children: [
14
- * { path: "/users", method: "GET", handler: getUsers },
15
- * { path: "/users/:id", method: "GET", handler: getUser },
16
- * ],
17
- * },
18
- * ]);
19
- * // 结果:
20
- * // [
21
- * // { fullPath: "/api/users", method: "GET", ... },
22
- * // { fullPath: "/api/users/:id", method: "GET", ... },
23
- * // ]
24
- * ```
25
- */
26
- /** 标准路由属性(不继承) */
27
- const STANDARD_ROUTE_PROPS = new Set([
28
- "path",
29
- "method",
30
- "handler",
31
- "middleware",
32
- "children",
33
- "name",
34
- "description"
35
- ]);
36
- /**
37
- * 提取路由的自定义属性(用于继承)
38
- * 排除标准属性,保留 log, webhook, auth 等自定义配置
39
- */
40
- function extractCustomProps(route) {
41
- const custom = {};
42
- for (const key of Object.keys(route)) if (!STANDARD_ROUTE_PROPS.has(key)) custom[key] = route[key];
43
- return custom;
44
- }
45
- /**
46
- * 合并自定义属性(子路由覆盖父路由)
47
- */
48
- function mergeCustomProps(parentProps, childProps) {
49
- return {
50
- ...parentProps,
51
- ...childProps
52
- };
53
- }
54
- function flattenNestedRoutes(routes) {
55
- const flattened = [];
56
- function processRoute(route, parentPath = "", parentMiddleware = [], parentName, parentCustomProps = {}) {
57
- const currentPath = normalizePath(parentPath + route.path);
58
- const currentMiddleware = [...parentMiddleware, ...route.middleware || []];
59
- const currentName = route.name || parentName;
60
- const currentCustomProps = mergeCustomProps(parentCustomProps, extractCustomProps(route));
61
- if ("method" in route && "handler" in route) {
62
- const leafRoute = route;
63
- flattened.push({
64
- ...currentCustomProps,
65
- ...leafRoute,
66
- fullPath: currentPath,
67
- middlewareChain: currentMiddleware,
68
- parentName
69
- });
70
- } else if ("children" in route && route.children) for (const child of route.children) processRoute(child, currentPath, currentMiddleware, currentName, currentCustomProps);
71
- }
72
- for (const route of routes) processRoute(route);
73
- return flattened;
74
- }
75
- /**
76
- * 标准化路径
77
- *
78
- * - 解码 URL 编码字符
79
- * - 去除重复斜杠
80
- * - 处理结尾斜杠
81
- *
82
- * @example
83
- * ```typescript
84
- * normalizePath("//api//users/") // "/api/users"
85
- * normalizePath("/api/%20test") // "/api/ test"
86
- * ```
87
- */
88
- function normalizePath(path) {
89
- let normalized = decodeURIComponent(path);
90
- normalized = normalized.replace(/\/+/g, "/");
91
- if (normalized === "") return "/";
92
- if (normalized !== "/" && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
93
- return normalized;
94
- }
95
-
96
- //#endregion
97
- export { normalizePath as n, flattenNestedRoutes as t };
98
- //# sourceMappingURL=router-CgYfGB4J.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-CgYfGB4J.mjs","names":[],"sources":["../src/router.ts"],"sourcesContent":["/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\n/** 标准路由属性(不继承) */\nconst STANDARD_ROUTE_PROPS = new Set([\n 'path', 'method', 'handler', 'middleware', 'children', 'name', 'description',\n]);\n\n/**\n * 提取路由的自定义属性(用于继承)\n * 排除标准属性,保留 log, webhook, auth 等自定义配置\n */\nfunction extractCustomProps(route: Route | NestedRoute): Record<string, unknown> {\n const custom: Record<string, unknown> = {};\n for (const key of Object.keys(route)) {\n if (!STANDARD_ROUTE_PROPS.has(key)) {\n custom[key] = (route as Record<string, unknown>)[key];\n }\n }\n return custom;\n}\n\n/**\n * 合并自定义属性(子路由覆盖父路由)\n */\nfunction mergeCustomProps(\n parentProps: Record<string, unknown>,\n childProps: Record<string, unknown>,\n): Record<string, unknown> {\n return { ...parentProps, ...childProps };\n}\n\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n parentName?: string,\n parentCustomProps: Record<string, unknown> = {},\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n // 当前路由的 name(用于传递给子路由)\n const currentName = route.name || parentName;\n // 合并自定义属性(子路由可覆盖父路由设置)\n const currentCustomProps = mergeCustomProps(parentCustomProps, extractCustomProps(route));\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n const leafRoute = route as Route;\n flattened.push({\n ...currentCustomProps, // 继承的自定义属性放在前面\n ...leafRoute, // 叶子路由自身属性覆盖\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n parentName: parentName,\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware, currentName, currentCustomProps);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,uBAAuB,IAAI,IAAI;CACnC;CAAQ;CAAU;CAAW;CAAc;CAAY;CAAQ;CAChE,CAAC;;;;;AAMF,SAAS,mBAAmB,OAAqD;CAC/E,MAAM,SAAkC,EAAE;AAC1C,MAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,KAAI,CAAC,qBAAqB,IAAI,IAAI,CAChC,QAAO,OAAQ,MAAkC;AAGrD,QAAO;;;;;AAMT,SAAS,iBACP,aACA,YACyB;AACzB,QAAO;EAAE,GAAG;EAAa,GAAG;EAAY;;AAG1C,SAAgB,oBACd,QACkB;CAClB,MAAM,YAA8B,EAAE;CAEtC,SAAS,aACP,OACA,aAAa,IACb,mBAAiC,EAAE,EACnC,YACA,oBAA6C,EAAE,EACzC;EAEN,MAAM,cAAc,cAAc,aAAa,MAAM,KAAK;EAE1D,MAAM,oBAAoB,CACxB,GAAG,kBACH,GAAI,MAAM,cAAc,EAAE,CAC3B;EAED,MAAM,cAAc,MAAM,QAAQ;EAElC,MAAM,qBAAqB,iBAAiB,mBAAmB,mBAAmB,MAAM,CAAC;AAEzF,MAAI,YAAY,SAAS,aAAa,OAAO;GAE3C,MAAM,YAAY;AAClB,aAAU,KAAK;IACb,GAAG;IACH,GAAG;IACH,UAAU;IACV,iBAAiB;IACL;IACb,CAAC;aACO,cAAc,SAAS,MAAM,SAEtC,MAAK,MAAM,SAAS,MAAM,SACxB,cAAa,OAAO,aAAa,mBAAmB,aAAa,mBAAmB;;AAK1F,MAAK,MAAM,SAAS,OAClB,cAAa,MAAM;AAGrB,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,cAAc,MAAsB;CAElD,IAAI,aAAa,mBAAmB,KAAK;AAGzC,cAAa,WAAW,QAAQ,QAAQ,IAAI;AAG5C,KAAI,eAAe,GAAI,QAAO;AAG9B,KAAI,eAAe,OAAO,WAAW,SAAS,IAAI,CAChD,cAAa,WAAW,MAAM,GAAG,GAAG;AAGtC,QAAO"}
@@ -1 +0,0 @@
1
- export { };