vafast 0.4.4 → 0.4.8

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 (168) hide show
  1. package/README.md +43 -8
  2. package/dist/base-server-B7MYJNsl.mjs +112 -0
  3. package/dist/{base-server-CSkyjEaY.mjs.map → base-server-B7MYJNsl.mjs.map} +1 -1
  4. package/dist/{base-server-DvGS6ATg.d.mts → base-server-DLxtulAO.d.mts} +2 -2
  5. package/dist/{base64url-CwQnvZyp.mjs → base64url-C2zopQdH.mjs} +1 -1
  6. package/dist/{base64url-CwQnvZyp.mjs.map → base64url-C2zopQdH.mjs.map} +1 -1
  7. package/dist/{base64url-0N9uQPjZ.d.mts → base64url-Dwi2Afhc.d.mts} +1 -1
  8. package/dist/{component-route-CZawYn61.d.mts → component-route-nrrO0iSI.d.mts} +2 -2
  9. package/dist/{component-router-CErbGh2A.mjs → component-router-RwPL20vN.mjs} +10 -11
  10. package/dist/{component-router-CErbGh2A.mjs.map → component-router-RwPL20vN.mjs.map} +1 -1
  11. package/dist/component-server-DomPJ_7S.mjs +119 -0
  12. package/dist/{component-server-DAbIyIPI.mjs.map → component-server-DomPJ_7S.mjs.map} +1 -1
  13. package/dist/{component-server-CGzU4bss.d.mts → component-server-JqpDC7wy.d.mts} +4 -4
  14. package/dist/{create-handler-Bo-hvWp-.d.mts → create-handler-DKw-sQOV.d.mts} +2 -2
  15. package/dist/{create-handler-B_pfxh3m.mjs → create-handler-RconAcAB.mjs} +5 -6
  16. package/dist/{create-handler-B_pfxh3m.mjs.map → create-handler-RconAcAB.mjs.map} +1 -1
  17. package/dist/defineRoute.d.mts +3 -3
  18. package/dist/{dependency-manager-C6vFWP2L.d.mts → dependency-manager-C3_7ic4h.d.mts} +1 -1
  19. package/dist/dependency-manager-DCmh7xFc.mjs +60 -0
  20. package/dist/{dependency-manager-Czg7Po2j.mjs.map → dependency-manager-DCmh7xFc.mjs.map} +1 -1
  21. package/dist/{formats-CYLwo9GJ.d.mts → formats-Dk-DSBY4.d.mts} +1 -1
  22. package/dist/{go-await-BGAGJfrB.mjs → go-await-C4ZdEUwY.mjs} +1 -1
  23. package/dist/{go-await-BGAGJfrB.mjs.map → go-await-C4ZdEUwY.mjs.map} +1 -1
  24. package/dist/{go-await-DRItVwwh.d.mts → go-await-DL1A_-4X.d.mts} +1 -1
  25. package/dist/{handle-D0TFoOiX.d.mts → handle-BhR3oyky.d.mts} +1 -1
  26. package/dist/{handle-Csjtywdc.mjs → handle-BxJwSvV0.mjs} +2 -2
  27. package/dist/{handle-Csjtywdc.mjs.map → handle-BxJwSvV0.mjs.map} +1 -1
  28. package/dist/{html-renderer-CMGKJoIy.d.mts → html-renderer-CfKK2BrP.d.mts} +1 -1
  29. package/dist/{html-renderer-CczE8mwC.mjs → html-renderer-DTtJ_Yic.mjs} +26 -27
  30. package/dist/{html-renderer-CczE8mwC.mjs.map → html-renderer-DTtJ_Yic.mjs.map} +1 -1
  31. package/dist/{index-Ci52vt55.d.mts → index-CEfOqqvd.d.mts} +5 -5
  32. package/dist/index.d.mts +25 -25
  33. package/dist/index.mjs +21 -25
  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 -2
  37. package/dist/middleware-CewKbtb4.mjs +182 -0
  38. package/dist/middleware-CewKbtb4.mjs.map +1 -0
  39. package/dist/middleware-KXEoefLX.d.mts +23 -0
  40. package/dist/middleware.d.mts +4 -25
  41. package/dist/middleware.mjs +1 -2
  42. package/dist/monitoring/index.d.mts +8 -33
  43. package/dist/monitoring/index.mjs +1 -25
  44. package/dist/monitoring/native-monitor.d.mts +148 -27
  45. package/dist/monitoring/native-monitor.mjs +320 -114
  46. package/dist/monitoring/native-monitor.mjs.map +1 -1
  47. package/dist/node-server/index.d.mts +1 -1
  48. package/dist/node-server/index.mjs +3 -3
  49. package/dist/node-server/request.mjs +1 -1
  50. package/dist/node-server/response.mjs +1 -1
  51. package/dist/node-server/serve.d.mts +1 -1
  52. package/dist/node-server/serve.mjs +2 -2
  53. package/dist/{parsers-7lvt3Oss.d.mts → parsers-BerGr2_q.d.mts} +1 -1
  54. package/dist/{parsers-CI_TZ7pO.mjs → parsers-DpH_mD0H.mjs} +1 -1
  55. package/dist/{parsers-CI_TZ7pO.mjs.map → parsers-DpH_mD0H.mjs.map} +1 -1
  56. package/dist/path-matcher-CGczAIl_.mjs +61 -0
  57. package/dist/{path-matcher-73cJd5Y7.mjs.map → path-matcher-CGczAIl_.mjs.map} +1 -1
  58. package/dist/radix-tree-qqSjnVXF.mjs +163 -0
  59. package/dist/{radix-tree-D0XYaJKb.mjs.map → radix-tree-qqSjnVXF.mjs.map} +1 -1
  60. package/dist/{request-CKC3Ox6M.mjs → request-B-Nct5f7.mjs} +1 -1
  61. package/dist/{request-CKC3Ox6M.mjs.map → request-B-Nct5f7.mjs.map} +1 -1
  62. package/dist/{request-validator-_J5HloRq.mjs → request-validator-Bz9X48FX.mjs} +3 -3
  63. package/dist/{request-validator-_J5HloRq.mjs.map → request-validator-Bz9X48FX.mjs.map} +1 -1
  64. package/dist/{request-validator-42lY21gn.d.mts → request-validator-Coo8dI-p.d.mts} +2 -2
  65. package/dist/response-BMfdEcTm.d.mts +48 -0
  66. package/dist/{response-Cf5FgtmE.mjs → response-BnkYA4pj.mjs} +1 -1
  67. package/dist/{response-Cf5FgtmE.mjs.map → response-BnkYA4pj.mjs.map} +1 -1
  68. package/dist/{route-BJ-40LNI.d.mts → route-6A7umH7b.d.mts} +2 -2
  69. package/dist/{route-9pAVP1GC.mjs → route-Ds53PR4M.mjs} +1 -1
  70. package/dist/{route-9pAVP1GC.mjs.map → route-Ds53PR4M.mjs.map} +1 -1
  71. package/dist/{route-registry--tx1PNui.d.mts → route-registry-CmABJA2V.d.mts} +2 -2
  72. package/dist/route-registry-emTmRrWQ.mjs +226 -0
  73. package/dist/{route-registry-mcTG0M-t.mjs.map → route-registry-emTmRrWQ.mjs.map} +1 -1
  74. package/dist/router/index.d.mts +2 -2
  75. package/dist/router/index.mjs +3 -9
  76. package/dist/router/radix-tree.d.mts +3 -3
  77. package/dist/router/radix-tree.mjs +1 -2
  78. package/dist/{router-B9HUUCkR.mjs → router-xWzwz_1a.mjs} +2 -5
  79. package/dist/{router-B9HUUCkR.mjs.map → router-xWzwz_1a.mjs.map} +1 -1
  80. package/dist/router.d.mts +3 -3
  81. package/dist/router.mjs +1 -2
  82. package/dist/{schema-CPQudJpE.d.mts → schema-B6DFN5c2.d.mts} +1 -1
  83. package/dist/{serve-Be6NvuQk.mjs → serve-48LEIkPa.mjs} +3 -3
  84. package/dist/{serve-Be6NvuQk.mjs.map → serve-48LEIkPa.mjs.map} +1 -1
  85. package/dist/{serve-B5WmhK6m.d.mts → serve-AG80VaIr.d.mts} +1 -1
  86. package/dist/serve.d.mts +1 -1
  87. package/dist/serve.mjs +2 -2
  88. package/dist/server/base-server.d.mts +3 -3
  89. package/dist/server/base-server.mjs +1 -2
  90. package/dist/server/component-server.d.mts +4 -4
  91. package/dist/server/component-server.mjs +2 -3
  92. package/dist/server/index.d.mts +6 -6
  93. package/dist/server/index.mjs +6 -6
  94. package/dist/server/server-factory.d.mts +6 -6
  95. package/dist/server/server-factory.mjs +5 -4
  96. package/dist/server/server.d.mts +4 -4
  97. package/dist/server/server.mjs +2 -2
  98. package/dist/server-C75o1b-a.mjs +70 -0
  99. package/dist/server-C75o1b-a.mjs.map +1 -0
  100. package/dist/{server-D9gjszHe.d.mts → server-DGA3dd5s.d.mts} +3 -3
  101. package/dist/server-L_FNwdap.mjs +137 -0
  102. package/dist/{server-BmPKs8oM.mjs.map → server-L_FNwdap.mjs.map} +1 -1
  103. package/dist/{sse-BMM6KTfy.d.mts → sse-BgLhEo43.d.mts} +2 -2
  104. package/dist/{sse-BT5yyLgX.mjs → sse-CBl-szg1.mjs} +3 -3
  105. package/dist/{sse-BT5yyLgX.mjs.map → sse-CBl-szg1.mjs.map} +1 -1
  106. package/dist/types/component-route.d.mts +1 -1
  107. package/dist/types/index.d.mts +5 -5
  108. package/dist/types/index.mjs +1 -1
  109. package/dist/types/route.d.mts +1 -1
  110. package/dist/types/route.mjs +1 -1
  111. package/dist/types/schema.d.mts +1 -1
  112. package/dist/types/types.d.mts +1 -1
  113. package/dist/{types-DuTa8AVN.d.mts → types-D1PUFkda.d.mts} +1 -1
  114. package/dist/utils/base64url.d.mts +1 -1
  115. package/dist/utils/base64url.mjs +1 -1
  116. package/dist/utils/create-handler.d.mts +2 -2
  117. package/dist/utils/create-handler.mjs +4 -3
  118. package/dist/utils/dependency-manager.d.mts +1 -1
  119. package/dist/utils/dependency-manager.mjs +1 -2
  120. package/dist/utils/formats.d.mts +1 -1
  121. package/dist/utils/go-await.d.mts +1 -1
  122. package/dist/utils/go-await.mjs +1 -1
  123. package/dist/utils/handle.d.mts +1 -1
  124. package/dist/utils/handle.mjs +2 -2
  125. package/dist/utils/html-renderer.d.mts +1 -1
  126. package/dist/utils/html-renderer.mjs +1 -2
  127. package/dist/utils/index.d.mts +17 -16
  128. package/dist/utils/index.mjs +13 -21
  129. package/dist/utils/parsers.d.mts +1 -1
  130. package/dist/utils/parsers.mjs +1 -1
  131. package/dist/utils/path-matcher.mjs +1 -2
  132. package/dist/utils/request-validator.d.mts +2 -2
  133. package/dist/utils/request-validator.mjs +3 -3
  134. package/dist/utils/response.d.mts +5 -2
  135. package/dist/utils/response.mjs +2 -3
  136. package/dist/utils/route-registry.d.mts +3 -3
  137. package/dist/utils/route-registry.mjs +1 -2
  138. package/dist/utils/sse.d.mts +2 -2
  139. package/dist/utils/sse.mjs +3 -3
  140. package/dist/utils/validators/validators.d.mts +1 -1
  141. package/dist/utils/validators/validators.mjs +1 -1
  142. package/dist/{validators-CPmnj_y9.d.mts → validators-Ch71zkT8.d.mts} +1 -1
  143. package/dist/{validators-BBrGePBr.mjs → validators-DBkyw6BG.mjs} +1 -1
  144. package/dist/{validators-BBrGePBr.mjs.map → validators-DBkyw6BG.mjs.map} +1 -1
  145. package/package.json +6 -1
  146. package/dist/base-server-CSkyjEaY.mjs +0 -113
  147. package/dist/chunk-DW4-Jl94.mjs +0 -37
  148. package/dist/component-server-DAbIyIPI.mjs +0 -124
  149. package/dist/dependency-manager-Czg7Po2j.mjs +0 -61
  150. package/dist/middleware-Byp3Hjae.mjs +0 -59
  151. package/dist/middleware-Byp3Hjae.mjs.map +0 -1
  152. package/dist/monitoring/index.mjs.map +0 -1
  153. package/dist/monitoring/types.d.mts +0 -150
  154. package/dist/path-matcher-73cJd5Y7.mjs +0 -62
  155. package/dist/radix-tree-D0XYaJKb.mjs +0 -157
  156. package/dist/response-A-sZZiJ7.d.mts +0 -21
  157. package/dist/response-DXg4i_yh.mjs +0 -97
  158. package/dist/response-DXg4i_yh.mjs.map +0 -1
  159. package/dist/route-registry-mcTG0M-t.mjs +0 -225
  160. package/dist/router/index.mjs.map +0 -1
  161. package/dist/schema-CtVBNfnQ.mjs +0 -1
  162. package/dist/server-BmPKs8oM.mjs +0 -137
  163. package/dist/server-Cbd3Ia51.mjs +0 -88
  164. package/dist/server-Cbd3Ia51.mjs.map +0 -1
  165. package/dist/utils/index.mjs.map +0 -1
  166. /package/dist/{component-route-CYxLOnci.mjs → component-route-DNgAj6VC.mjs} +0 -0
  167. /package/dist/{index-CzItj62a.d.mts → index-CREkvfw9.d.mts} +0 -0
  168. /package/dist/{monitoring/types.mjs → schema-1fwiv7cm.mjs} +0 -0
@@ -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":"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"}
1
+ {"version":3,"file":"parsers-DpH_mD0H.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":"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"}
@@ -0,0 +1,61 @@
1
+ //#region src/utils/path-matcher.ts
2
+ /**
3
+ * 路径匹配工具类
4
+ * 提供统一的路径匹配和参数提取功能
5
+ */
6
+ var PathMatcher = class {
7
+ /**
8
+ * 路径匹配
9
+ */
10
+ static matchPath(pattern, path) {
11
+ const patternParts = pattern.split("/").filter(Boolean);
12
+ const pathParts = path.split("/").filter(Boolean);
13
+ if (patternParts.length !== pathParts.length) return false;
14
+ for (let i = 0; i < patternParts.length; i++) if (patternParts[i] !== pathParts[i] && !patternParts[i].startsWith(":")) return false;
15
+ return true;
16
+ }
17
+ /**
18
+ * 提取路径参数
19
+ */
20
+ static extractParams(pattern, path) {
21
+ const params = {};
22
+ const patternParts = pattern.split("/").filter(Boolean);
23
+ const pathParts = path.split("/").filter(Boolean);
24
+ for (let i = 0; i < patternParts.length; i++) if (patternParts[i].startsWith(":")) {
25
+ const paramName = patternParts[i].slice(1);
26
+ params[paramName] = pathParts[i];
27
+ }
28
+ return params;
29
+ }
30
+ /**
31
+ * 计算路径特异性分数
32
+ * 用于路由排序:静态 > 动态(:param) > 通配符(*)
33
+ */
34
+ static calculatePathScore(path) {
35
+ const parts = path.split("/").filter(Boolean);
36
+ let score = 0;
37
+ for (const p of parts) if (p === "*") score += 1;
38
+ else if (p.startsWith(":")) score += 2;
39
+ else score += 3;
40
+ return score * 10 + parts.length;
41
+ }
42
+ /**
43
+ * 判断两个路径是否可能冲突
44
+ */
45
+ static pathsMayConflict(path1, path2) {
46
+ const parts1 = path1.split("/").filter(Boolean);
47
+ const parts2 = path2.split("/").filter(Boolean);
48
+ if (parts1.length !== parts2.length) return false;
49
+ for (let i = 0; i < parts1.length; i++) {
50
+ const p1 = parts1[i];
51
+ const p2 = parts2[i];
52
+ if (!p1.startsWith(":") && !p1.startsWith("*") && !p2.startsWith(":") && !p2.startsWith("*") && p1 !== p2) return false;
53
+ if (p1 === "*" && p2.startsWith(":") || p2 === "*" && p1.startsWith(":")) return true;
54
+ }
55
+ return false;
56
+ }
57
+ };
58
+
59
+ //#endregion
60
+ export { PathMatcher as t };
61
+ //# sourceMappingURL=path-matcher-CGczAIl_.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-CGczAIl_.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":";;;;;AAIA,IAAa,cAAb,MAAyB;;;;CAIvB,OAAO,UAAU,SAAiB,MAAuB;EACvD,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;EACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,MAAI,aAAa,WAAW,UAAU,OACpC,QAAO;AAGT,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KACE,aAAa,OAAO,UAAU,MAC9B,CAAC,aAAa,GAAG,WAAW,IAAI,CAEhC,QAAO;AAIX,SAAO;;;;;CAMT,OAAO,cAAc,SAAiB,MAAsC;EAC1E,MAAM,SAAiC,EAAE;EACzC,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;EACvD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEjD,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,IACvC,KAAI,aAAa,GAAG,WAAW,IAAI,EAAE;GACnC,MAAM,YAAY,aAAa,GAAG,MAAM,EAAE;AAC1C,UAAO,aAAa,UAAU;;AAIlC,SAAO;;;;;;CAOT,OAAO,mBAAmB,MAAsB;EAC9C,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;EAC7C,IAAI,QAAQ;AACZ,OAAK,MAAM,KAAK,MACd,KAAI,MAAM,IACR,UAAS;WACF,EAAE,WAAW,IAAI,CACxB,UAAS;MACN,UAAS;AAGhB,SAAO,QAAQ,KAAK,MAAM;;;;;CAM5B,OAAO,iBAAiB,OAAe,OAAwB;EAC7D,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;EAC/C,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,OAAO,QAAQ;AAE/C,MAAI,OAAO,WAAW,OAAO,OAAQ,QAAO;AAE5C,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;GACtC,MAAM,KAAK,OAAO;GAClB,MAAM,KAAK,OAAO;AAGlB,OACE,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,CAAC,GAAG,WAAW,IAAI,IACnB,OAAO,GAEP,QAAO;AAIT,OACG,OAAO,OAAO,GAAG,WAAW,IAAI,IAChC,OAAO,OAAO,GAAG,WAAW,IAAI,CAEjC,QAAO;;AAIX,SAAO"}
@@ -0,0 +1,163 @@
1
+ //#region src/router/radix-tree.ts
2
+ /**
3
+ * Radix Tree 路由器
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const router = new RadixRouter();
8
+ * router.register("GET", "/users/:id", handler);
9
+ * const result = router.match("GET", "/users/123");
10
+ * // result.params = { id: "123" }
11
+ * ```
12
+ */
13
+ var RadixRouter = class {
14
+ root;
15
+ constructor() {
16
+ this.root = this.createNode("");
17
+ }
18
+ createNode(path) {
19
+ return {
20
+ path,
21
+ children: Object.create(null),
22
+ handlers: Object.create(null)
23
+ };
24
+ }
25
+ /** 分割路径 */
26
+ splitPath(path) {
27
+ return path.split("/").filter(Boolean);
28
+ }
29
+ /** 编译器函数 - 用于预编译中间件链 */
30
+ compiler;
31
+ /** 设置中间件编译器 */
32
+ setCompiler(compiler) {
33
+ this.compiler = compiler;
34
+ }
35
+ /** 注册路由 */
36
+ register(method, pattern, handler, middleware = []) {
37
+ const segments = this.splitPath(pattern);
38
+ let node = this.root;
39
+ for (const segment of segments) {
40
+ const firstChar = segment[0];
41
+ if (firstChar === ":") {
42
+ if (!node.paramChild) {
43
+ node.paramChild = this.createNode(segment);
44
+ node.paramChild.paramName = segment.substring(1);
45
+ }
46
+ node = node.paramChild;
47
+ } else if (firstChar === "*") {
48
+ if (!node.wildcardChild) {
49
+ node.wildcardChild = this.createNode(segment);
50
+ node.wildcardChild.paramName = segment.length > 1 ? segment.substring(1) : "*";
51
+ }
52
+ node = node.wildcardChild;
53
+ break;
54
+ } else {
55
+ if (!node.children[segment]) node.children[segment] = this.createNode(segment);
56
+ node = node.children[segment];
57
+ }
58
+ }
59
+ const routeHandler = {
60
+ handler,
61
+ middleware
62
+ };
63
+ if (this.compiler && middleware.length === 0) routeHandler.compiled = this.compiler([], handler);
64
+ node.handlers[method] = routeHandler;
65
+ }
66
+ /** 预编译所有路由(在添加全局中间件后调用) */
67
+ precompileAll(globalMiddleware) {
68
+ if (!this.compiler) return;
69
+ this.precompileNode(this.root, globalMiddleware);
70
+ }
71
+ precompileNode(node, globalMiddleware) {
72
+ for (const method in node.handlers) {
73
+ const routeHandler = node.handlers[method];
74
+ if (routeHandler) {
75
+ const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];
76
+ routeHandler.compiled = this.compiler(allMiddleware, routeHandler.handler);
77
+ }
78
+ }
79
+ for (const key in node.children) this.precompileNode(node.children[key], globalMiddleware);
80
+ if (node.paramChild) this.precompileNode(node.paramChild, globalMiddleware);
81
+ if (node.wildcardChild) this.precompileNode(node.wildcardChild, globalMiddleware);
82
+ }
83
+ /** 匹配路由 */
84
+ match(method, path) {
85
+ const segments = this.splitPath(path);
86
+ const params = Object.create(null);
87
+ const node = this.matchNode(this.root, segments, 0, params);
88
+ if (!node) return null;
89
+ const routeHandler = node.handlers[method];
90
+ if (!routeHandler) return null;
91
+ return {
92
+ handler: routeHandler.handler,
93
+ middleware: routeHandler.middleware,
94
+ params,
95
+ compiled: routeHandler.compiled
96
+ };
97
+ }
98
+ /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */
99
+ matchNode(node, segments, index, params) {
100
+ if (index === segments.length) {
101
+ for (const method in node.handlers) if (node.handlers[method]) return node;
102
+ return null;
103
+ }
104
+ const segment = segments[index];
105
+ const staticChild = node.children[segment];
106
+ if (staticChild) {
107
+ const result = this.matchNode(staticChild, segments, index + 1, params);
108
+ if (result) return result;
109
+ }
110
+ if (node.paramChild) {
111
+ const paramName = node.paramChild.paramName;
112
+ const oldValue = params[paramName];
113
+ params[paramName] = segment;
114
+ const result = this.matchNode(node.paramChild, segments, index + 1, params);
115
+ if (result) return result;
116
+ if (oldValue === void 0) delete params[paramName];
117
+ else params[paramName] = oldValue;
118
+ }
119
+ if (node.wildcardChild) {
120
+ params[node.wildcardChild.paramName || "*"] = segments.slice(index).join("/");
121
+ return node.wildcardChild;
122
+ }
123
+ return null;
124
+ }
125
+ /** 获取路径允许的 HTTP 方法 */
126
+ getAllowedMethods(path) {
127
+ const segments = this.splitPath(path);
128
+ const node = this.findNode(segments);
129
+ if (!node) return [];
130
+ const methods = [];
131
+ for (const method in node.handlers) if (node.handlers[method]) methods.push(method);
132
+ return methods;
133
+ }
134
+ /** 查找节点(不提取参数) */
135
+ findNode(segments) {
136
+ let node = this.root;
137
+ for (const segment of segments) if (node.children[segment]) node = node.children[segment];
138
+ else if (node.paramChild) node = node.paramChild;
139
+ else if (node.wildcardChild) return node.wildcardChild;
140
+ else return null;
141
+ return node;
142
+ }
143
+ /** 获取所有已注册的路由 */
144
+ getRoutes() {
145
+ const routes = [];
146
+ this.collectRoutes(this.root, "", routes);
147
+ return routes;
148
+ }
149
+ collectRoutes(node, prefix, routes) {
150
+ const currentPath = prefix + (node.path ? "/" + node.path : "");
151
+ for (const method in node.handlers) if (node.handlers[method]) routes.push({
152
+ method,
153
+ path: currentPath || "/"
154
+ });
155
+ for (const key in node.children) this.collectRoutes(node.children[key], currentPath, routes);
156
+ if (node.paramChild) this.collectRoutes(node.paramChild, currentPath, routes);
157
+ if (node.wildcardChild) this.collectRoutes(node.wildcardChild, currentPath, routes);
158
+ }
159
+ };
160
+
161
+ //#endregion
162
+ export { RadixRouter as t };
163
+ //# sourceMappingURL=radix-tree-qqSjnVXF.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-qqSjnVXF.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-B-Nct5f7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-CKC3Ox6M.mjs","names":[],"sources":["../src/node-server/request.ts"],"sourcesContent":["/**\n * 优化的 Request 代理\n * 延迟创建真实 Request,减少不必要的对象分配\n */\n\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport type { IncomingMessage } from \"node:http\";\n\n// 内部 Symbol\nconst requestCache = Symbol(\"requestCache\");\nconst incomingKey = Symbol(\"incoming\");\nconst urlKey = Symbol(\"url\");\nconst headersKey = Symbol(\"headers\");\n\n/**\n * 从 rawHeaders 高效解析 Headers\n */\nfunction parseHeaders(rawHeaders: string[]): Headers {\n const headers = new Headers();\n for (let i = 0; i < rawHeaders.length; i += 2) {\n const key = rawHeaders[i];\n const value = rawHeaders[i + 1];\n // 跳过 HTTP/2 伪头 (以 : 开头)\n if (key.charCodeAt(0) !== 58) {\n headers.append(key, value);\n }\n }\n return headers;\n}\n\n/**\n * 将 Node.js ReadableStream 转换为 Web 标准 ReadableStream\n * Node.js 和 Web 标准的 ReadableStream 在运行时兼容,但 TypeScript 类型不同\n */\nfunction toWebStream(\n nodeStream: NodeReadableStream<Uint8Array>,\n): ReadableStream<Uint8Array> {\n // Node.js ReadableStream 和 Web ReadableStream 在运行时是兼容的\n // 这里使用类型断言是安全的,因为 Node.js >= 18 的 stream/web 完全实现了 WHATWG Streams 标准\n return nodeStream as unknown as ReadableStream<Uint8Array>;\n}\n\n/** 代理 Request 内部接口 */\ninterface ProxyRequestInternal {\n [requestCache]?: Request;\n [incomingKey]: IncomingMessage;\n [urlKey]: string;\n [headersKey]?: Headers;\n _getRequest(): Request;\n}\n\n/**\n * 创建真实的 Request 对象\n */\nfunction createRealRequest(proxy: ProxyRequestInternal): Request {\n const incoming = proxy[incomingKey];\n const method = incoming.method || \"GET\";\n const init: RequestInit & { duplex?: string } = {\n method,\n headers: proxy[headersKey] || parseHeaders(incoming.rawHeaders),\n };\n\n // 只有非 GET/HEAD 请求才有 body\n if (method !== \"GET\" && method !== \"HEAD\") {\n // 使用 Node.js 原生流转换,避免收集 chunks\n const nodeWebStream = Readable.toWeb(\n incoming,\n ) as NodeReadableStream<Uint8Array>;\n init.body = toWebStream(nodeWebStream);\n init.duplex = \"half\";\n }\n\n return new Request(proxy[urlKey], init);\n}\n\n/**\n * Request 代理原型\n * 使用 Object.defineProperty 定义属性以支持 this 绑定\n */\nconst requestPrototype: object = {};\n\n// 定义 method 属性\nObject.defineProperty(requestPrototype, \"method\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[incomingKey].method || \"GET\";\n },\n enumerable: true,\n});\n\n// 定义 url 属性\nObject.defineProperty(requestPrototype, \"url\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[urlKey];\n },\n enumerable: true,\n});\n\n// 定义 headers 属性(延迟解析)\nObject.defineProperty(requestPrototype, \"headers\", {\n get() {\n const self = this as ProxyRequestInternal;\n if (!self[headersKey]) {\n self[headersKey] = parseHeaders(self[incomingKey].rawHeaders);\n }\n return self[headersKey];\n },\n enumerable: true,\n});\n\n// 定义 _getRequest 方法(获取或创建真实 Request)\nObject.defineProperty(requestPrototype, \"_getRequest\", {\n value: function () {\n const self = this as ProxyRequestInternal;\n if (!self[requestCache]) {\n self[requestCache] = createRealRequest(self);\n }\n return self[requestCache]!;\n },\n enumerable: false,\n});\n\n// 代理需要访问真实 Request 的属性\nconst proxyGetters = [\n \"body\",\n \"bodyUsed\",\n \"signal\",\n \"cache\",\n \"credentials\",\n \"destination\",\n \"integrity\",\n \"mode\",\n \"redirect\",\n \"referrer\",\n \"referrerPolicy\",\n \"keepalive\",\n];\n\nproxyGetters.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n get() {\n const self = this as ProxyRequestInternal;\n return self._getRequest()[key as keyof Request];\n },\n enumerable: true,\n });\n});\n\n// 代理需要调用真实 Request 的方法\nconst proxyMethods = [\n \"arrayBuffer\",\n \"blob\",\n \"clone\",\n \"formData\",\n \"json\",\n \"text\",\n];\n\nproxyMethods.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n value: function () {\n const self = this as ProxyRequestInternal;\n const req = self._getRequest();\n return (req[key as keyof Request] as () => Promise<unknown>).call(req);\n },\n enumerable: true,\n });\n});\n\n// 设置原型链\nObject.setPrototypeOf(requestPrototype, Request.prototype);\n\n/**\n * 创建代理 Request\n * @param incoming Node.js IncomingMessage\n * @param defaultHost 默认主机名\n */\nexport function createProxyRequest(\n incoming: IncomingMessage,\n defaultHost: string,\n): Request {\n const req = Object.create(requestPrototype) as ProxyRequestInternal;\n req[incomingKey] = incoming;\n\n // 构建 URL\n const host = incoming.headers.host || defaultHost;\n const protocol = (incoming.socket as { encrypted?: boolean }).encrypted\n ? \"https\"\n : \"http\";\n req[urlKey] = `${protocol}://${host}${incoming.url || \"/\"}`;\n\n return req as unknown as Request;\n}\n"],"mappings":";;;;;;;AAUA,MAAM,eAAe,OAAO,eAAe;AAC3C,MAAM,cAAc,OAAO,WAAW;AACtC,MAAM,SAAS,OAAO,MAAM;AAC5B,MAAM,aAAa,OAAO,UAAU;;;;AAKpC,SAAS,aAAa,YAA+B;CACnD,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;EAC7C,MAAM,MAAM,WAAW;EACvB,MAAM,QAAQ,WAAW,IAAI;AAE7B,MAAI,IAAI,WAAW,EAAE,KAAK,GACxB,SAAQ,OAAO,KAAK,MAAM;;AAG9B,QAAO;;;;;;AAOT,SAAS,YACP,YAC4B;AAG5B,QAAO;;;;;AAeT,SAAS,kBAAkB,OAAsC;CAC/D,MAAM,WAAW,MAAM;CACvB,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,OAA0C;EAC9C;EACA,SAAS,MAAM,eAAe,aAAa,SAAS,WAAW;EAChE;AAGD,KAAI,WAAW,SAAS,WAAW,QAAQ;AAKzC,OAAK,OAAO,YAHU,SAAS,MAC7B,SACD,CACqC;AACtC,OAAK,SAAS;;AAGhB,QAAO,IAAI,QAAQ,MAAM,SAAS,KAAK;;;;;;AAOzC,MAAM,mBAA2B,EAAE;AAGnC,OAAO,eAAe,kBAAkB,UAAU;CAChD,MAAM;AAEJ,SADa,KACD,aAAa,UAAU;;CAErC,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,OAAO;CAC7C,MAAM;AAEJ,SADa,KACD;;CAEd,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,WAAW;CACjD,MAAM;EACJ,MAAM,OAAO;AACb,MAAI,CAAC,KAAK,YACR,MAAK,cAAc,aAAa,KAAK,aAAa,WAAW;AAE/D,SAAO,KAAK;;CAEd,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,eAAe;CACrD,OAAO,WAAY;EACjB,MAAM,OAAO;AACb,MAAI,CAAC,KAAK,cACR,MAAK,gBAAgB,kBAAkB,KAAK;AAE9C,SAAO,KAAK;;CAEd,YAAY;CACb,CAAC;AAGmB;CACnB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAEY,SAAS,QAAQ;AAC5B,QAAO,eAAe,kBAAkB,KAAK;EAC3C,MAAM;AAEJ,UADa,KACD,aAAa,CAAC;;EAE5B,YAAY;EACb,CAAC;EACF;AAGmB;CACnB;CACA;CACA;CACA;CACA;CACA;CACD,CAEY,SAAS,QAAQ;AAC5B,QAAO,eAAe,kBAAkB,KAAK;EAC3C,OAAO,WAAY;GAEjB,MAAM,MADO,KACI,aAAa;AAC9B,UAAQ,IAAI,KAAiD,KAAK,IAAI;;EAExE,YAAY;EACb,CAAC;EACF;AAGF,OAAO,eAAe,kBAAkB,QAAQ,UAAU;;;;;;AAO1D,SAAgB,mBACd,UACA,aACS;CACT,MAAM,MAAM,OAAO,OAAO,iBAAiB;AAC3C,KAAI,eAAe;CAGnB,MAAM,OAAO,SAAS,QAAQ,QAAQ;AAItC,KAAI,UAAU,GAHI,SAAS,OAAmC,YAC1D,UACA,OACsB,KAAK,OAAO,SAAS,OAAO;AAEtD,QAAO"}
1
+ {"version":3,"file":"request-B-Nct5f7.mjs","names":[],"sources":["../src/node-server/request.ts"],"sourcesContent":["/**\n * 优化的 Request 代理\n * 延迟创建真实 Request,减少不必要的对象分配\n */\n\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport type { IncomingMessage } from \"node:http\";\n\n// 内部 Symbol\nconst requestCache = Symbol(\"requestCache\");\nconst incomingKey = Symbol(\"incoming\");\nconst urlKey = Symbol(\"url\");\nconst headersKey = Symbol(\"headers\");\n\n/**\n * 从 rawHeaders 高效解析 Headers\n */\nfunction parseHeaders(rawHeaders: string[]): Headers {\n const headers = new Headers();\n for (let i = 0; i < rawHeaders.length; i += 2) {\n const key = rawHeaders[i];\n const value = rawHeaders[i + 1];\n // 跳过 HTTP/2 伪头 (以 : 开头)\n if (key.charCodeAt(0) !== 58) {\n headers.append(key, value);\n }\n }\n return headers;\n}\n\n/**\n * 将 Node.js ReadableStream 转换为 Web 标准 ReadableStream\n * Node.js 和 Web 标准的 ReadableStream 在运行时兼容,但 TypeScript 类型不同\n */\nfunction toWebStream(\n nodeStream: NodeReadableStream<Uint8Array>,\n): ReadableStream<Uint8Array> {\n // Node.js ReadableStream 和 Web ReadableStream 在运行时是兼容的\n // 这里使用类型断言是安全的,因为 Node.js >= 18 的 stream/web 完全实现了 WHATWG Streams 标准\n return nodeStream as unknown as ReadableStream<Uint8Array>;\n}\n\n/** 代理 Request 内部接口 */\ninterface ProxyRequestInternal {\n [requestCache]?: Request;\n [incomingKey]: IncomingMessage;\n [urlKey]: string;\n [headersKey]?: Headers;\n _getRequest(): Request;\n}\n\n/**\n * 创建真实的 Request 对象\n */\nfunction createRealRequest(proxy: ProxyRequestInternal): Request {\n const incoming = proxy[incomingKey];\n const method = incoming.method || \"GET\";\n const init: RequestInit & { duplex?: string } = {\n method,\n headers: proxy[headersKey] || parseHeaders(incoming.rawHeaders),\n };\n\n // 只有非 GET/HEAD 请求才有 body\n if (method !== \"GET\" && method !== \"HEAD\") {\n // 使用 Node.js 原生流转换,避免收集 chunks\n const nodeWebStream = Readable.toWeb(\n incoming,\n ) as NodeReadableStream<Uint8Array>;\n init.body = toWebStream(nodeWebStream);\n init.duplex = \"half\";\n }\n\n return new Request(proxy[urlKey], init);\n}\n\n/**\n * Request 代理原型\n * 使用 Object.defineProperty 定义属性以支持 this 绑定\n */\nconst requestPrototype: object = {};\n\n// 定义 method 属性\nObject.defineProperty(requestPrototype, \"method\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[incomingKey].method || \"GET\";\n },\n enumerable: true,\n});\n\n// 定义 url 属性\nObject.defineProperty(requestPrototype, \"url\", {\n get() {\n const self = this as ProxyRequestInternal;\n return self[urlKey];\n },\n enumerable: true,\n});\n\n// 定义 headers 属性(延迟解析)\nObject.defineProperty(requestPrototype, \"headers\", {\n get() {\n const self = this as ProxyRequestInternal;\n if (!self[headersKey]) {\n self[headersKey] = parseHeaders(self[incomingKey].rawHeaders);\n }\n return self[headersKey];\n },\n enumerable: true,\n});\n\n// 定义 _getRequest 方法(获取或创建真实 Request)\nObject.defineProperty(requestPrototype, \"_getRequest\", {\n value: function () {\n const self = this as ProxyRequestInternal;\n if (!self[requestCache]) {\n self[requestCache] = createRealRequest(self);\n }\n return self[requestCache]!;\n },\n enumerable: false,\n});\n\n// 代理需要访问真实 Request 的属性\nconst proxyGetters = [\n \"body\",\n \"bodyUsed\",\n \"signal\",\n \"cache\",\n \"credentials\",\n \"destination\",\n \"integrity\",\n \"mode\",\n \"redirect\",\n \"referrer\",\n \"referrerPolicy\",\n \"keepalive\",\n];\n\nproxyGetters.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n get() {\n const self = this as ProxyRequestInternal;\n return self._getRequest()[key as keyof Request];\n },\n enumerable: true,\n });\n});\n\n// 代理需要调用真实 Request 的方法\nconst proxyMethods = [\n \"arrayBuffer\",\n \"blob\",\n \"clone\",\n \"formData\",\n \"json\",\n \"text\",\n];\n\nproxyMethods.forEach((key) => {\n Object.defineProperty(requestPrototype, key, {\n value: function () {\n const self = this as ProxyRequestInternal;\n const req = self._getRequest();\n return (req[key as keyof Request] as () => Promise<unknown>).call(req);\n },\n enumerable: true,\n });\n});\n\n// 设置原型链\nObject.setPrototypeOf(requestPrototype, Request.prototype);\n\n/**\n * 创建代理 Request\n * @param incoming Node.js IncomingMessage\n * @param defaultHost 默认主机名\n */\nexport function createProxyRequest(\n incoming: IncomingMessage,\n defaultHost: string,\n): Request {\n const req = Object.create(requestPrototype) as ProxyRequestInternal;\n req[incomingKey] = incoming;\n\n // 构建 URL\n const host = incoming.headers.host || defaultHost;\n const protocol = (incoming.socket as { encrypted?: boolean }).encrypted\n ? \"https\"\n : \"http\";\n req[urlKey] = `${protocol}://${host}${incoming.url || \"/\"}`;\n\n return req as unknown as Request;\n}\n"],"mappings":";;;;;;;AAUA,MAAM,eAAe,OAAO,eAAe;AAC3C,MAAM,cAAc,OAAO,WAAW;AACtC,MAAM,SAAS,OAAO,MAAM;AAC5B,MAAM,aAAa,OAAO,UAAU;;;;AAKpC,SAAS,aAAa,YAA+B;CACnD,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;EAC7C,MAAM,MAAM,WAAW;EACvB,MAAM,QAAQ,WAAW,IAAI;AAE7B,MAAI,IAAI,WAAW,EAAE,KAAK,GACxB,SAAQ,OAAO,KAAK,MAAM;;AAG9B,QAAO;;;;;;AAOT,SAAS,YACP,YAC4B;AAG5B,QAAO;;;;;AAeT,SAAS,kBAAkB,OAAsC;CAC/D,MAAM,WAAW,MAAM;CACvB,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,OAA0C;EAC9C;EACA,SAAS,MAAM,eAAe,aAAa,SAAS,WAAW;EAChE;AAGD,KAAI,WAAW,SAAS,WAAW,QAAQ;AAKzC,OAAK,OAAO,YAHU,SAAS,MAC7B,SACD,CACqC;AACtC,OAAK,SAAS;;AAGhB,QAAO,IAAI,QAAQ,MAAM,SAAS,KAAK;;;;;;AAOzC,MAAM,mBAA2B,EAAE;AAGnC,OAAO,eAAe,kBAAkB,UAAU;CAChD,MAAM;AAEJ,SADa,KACD,aAAa,UAAU;;CAErC,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,OAAO;CAC7C,MAAM;AAEJ,SADa,KACD;;CAEd,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,WAAW;CACjD,MAAM;EACJ,MAAM,OAAO;AACb,MAAI,CAAC,KAAK,YACR,MAAK,cAAc,aAAa,KAAK,aAAa,WAAW;AAE/D,SAAO,KAAK;;CAEd,YAAY;CACb,CAAC;AAGF,OAAO,eAAe,kBAAkB,eAAe;CACrD,OAAO,WAAY;EACjB,MAAM,OAAO;AACb,MAAI,CAAC,KAAK,cACR,MAAK,gBAAgB,kBAAkB,KAAK;AAE9C,SAAO,KAAK;;CAEd,YAAY;CACb,CAAC;AAGmB;CACnB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAEY,SAAS,QAAQ;AAC5B,QAAO,eAAe,kBAAkB,KAAK;EAC3C,MAAM;AAEJ,UADa,KACD,aAAa,CAAC;;EAE5B,YAAY;EACb,CAAC;EACF;AAGmB;CACnB;CACA;CACA;CACA;CACA;CACA;CACD,CAEY,SAAS,QAAQ;AAC5B,QAAO,eAAe,kBAAkB,KAAK;EAC3C,OAAO,WAAY;GAEjB,MAAM,MADO,KACI,aAAa;AAC9B,UAAQ,IAAI,KAAiD,KAAK,IAAI;;EAExE,YAAY;EACb,CAAC;EACF;AAGF,OAAO,eAAe,kBAAkB,QAAQ,UAAU;;;;;;AAO1D,SAAgB,mBACd,UACA,aACS;CACT,MAAM,MAAM,OAAO,OAAO,iBAAiB;AAC3C,KAAI,eAAe;CAGnB,MAAM,OAAO,SAAS,QAAQ,QAAQ;AAItC,KAAI,UAAU,GAHI,SAAS,OAAmC,YAC1D,UACA,OACsB,KAAK,OAAO,SAAS,OAAO;AAEtD,QAAO"}
@@ -1,5 +1,5 @@
1
- import { a as parseCookies, l as parseHeaders, r as parseBody, u as parseQuery } from "./parsers-CI_TZ7pO.mjs";
2
- import { a as validateAllSchemas } from "./validators-BBrGePBr.mjs";
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
3
 
4
4
  //#region src/utils/request-validator.ts
5
5
  /**
@@ -74,4 +74,4 @@ function createRequestValidator(config) {
74
74
 
75
75
  //#endregion
76
76
  export { validateRequest as i, parseAndValidateRequest as n, parseRequest as r, createRequestValidator as t };
77
- //# sourceMappingURL=request-validator-_J5HloRq.mjs.map
77
+ //# sourceMappingURL=request-validator-Bz9X48FX.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-validator-_J5HloRq.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
+ {"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,4 +1,4 @@
1
- import { t as SchemaConfig } from "./validators-CPmnj_y9.mjs";
1
+ import { t as SchemaConfig } from "./validators-Ch71zkT8.mjs";
2
2
  import { Static, TSchema } from "@sinclair/typebox";
3
3
 
4
4
  //#region src/utils/request-validator.d.ts
@@ -64,4 +64,4 @@ declare function parseAndValidateRequest<T extends SchemaConfig>(request: Reques
64
64
  declare function createRequestValidator<T extends SchemaConfig>(config: T): (request: Request, params?: Record<string, string>) => Promise<ValidationResult<T>>;
65
65
  //#endregion
66
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-42lY21gn.d.mts.map
67
+ //# sourceMappingURL=request-validator-Coo8dI-p.d.mts.map
@@ -0,0 +1,48 @@
1
+ import { t as VafastError } from "./middleware-KXEoefLX.mjs";
2
+
3
+ //#region src/utils/response.d.ts
4
+ /** 生成 JSON 响应 */
5
+ declare function json(data: unknown, status?: number, headers?: HeadersInit): Response;
6
+ /**
7
+ * 类型特化的响应映射
8
+ * 根据返回值类型直接生成 Response,避免不必要的检查
9
+ */
10
+ declare function mapResponse(response: unknown): Response;
11
+ /** 生成重定向响应 */
12
+ declare function redirect(location: string, status?: 301 | 302): Response;
13
+ /** 生成纯文本响应 */
14
+ declare function text(content: string, status?: number, headers?: HeadersInit): Response;
15
+ /** 生成HTML响应 */
16
+ declare function html(content: string, status?: number, headers?: HeadersInit): Response;
17
+ /** 生成空响应(204 No Content) */
18
+ declare function empty(status?: number, headers?: HeadersInit): Response;
19
+ /** 生成流式响应 */
20
+ declare function stream(stream: ReadableStream, status?: number, headers?: HeadersInit): Response;
21
+ /**
22
+ * 创建错误响应
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // 自定义错误
27
+ * throw err('用户不存在', 404, 'NOT_FOUND')
28
+ *
29
+ * // 预定义错误
30
+ * throw err.notFound('用户不存在')
31
+ * throw err.badRequest('参数错误')
32
+ * throw err.unauthorized('请先登录')
33
+ * ```
34
+ */
35
+ declare function err(message: string, status?: number, type?: string): VafastError;
36
+ declare namespace err {
37
+ var badRequest: (message?: string) => VafastError;
38
+ var unauthorized: (message?: string) => VafastError;
39
+ var forbidden: (message?: string) => VafastError;
40
+ var notFound: (message?: string) => VafastError;
41
+ var conflict: (message?: string) => VafastError;
42
+ var unprocessable: (message?: string) => VafastError;
43
+ var tooMany: (message?: string) => VafastError;
44
+ var internal: (message?: string) => VafastError;
45
+ }
46
+ //#endregion
47
+ export { mapResponse as a, text as c, json as i, err as n, redirect as o, html as r, stream as s, empty as t };
48
+ //# sourceMappingURL=response-BMfdEcTm.d.mts.map
@@ -69,4 +69,4 @@ async function writeResponseSimple(response, outgoing) {
69
69
 
70
70
  //#endregion
71
71
  export { writeResponseSimple as n, writeResponse as t };
72
- //# sourceMappingURL=response-Cf5FgtmE.mjs.map
72
+ //# sourceMappingURL=response-BnkYA4pj.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"response-Cf5FgtmE.mjs","names":[],"sources":["../src/node-server/response.ts"],"sourcesContent":["/**\n * 优化的 Response 写入\n * 流式写入,避免内存拷贝\n */\n\nimport type { ServerResponse } from \"node:http\";\n\n/**\n * 构建 Node.js 响应头\n * 处理 set-cookie 多值情况\n */\nfunction buildOutgoingHeaders(\n headers: Headers,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n const cookies: string[] = [];\n\n headers.forEach((value, key) => {\n if (key === \"set-cookie\") {\n cookies.push(value);\n } else {\n result[key] = value;\n }\n });\n\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n\n return result;\n}\n\n/**\n * 流式写入 Response body 到 ServerResponse\n * 支持背压处理,避免内存溢出\n */\nasync function writeBodyStream(\n body: ReadableStream<Uint8Array>,\n outgoing: ServerResponse,\n): Promise<void> {\n const reader = body.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n // 背压处理:如果写入返回 false,等待 drain 事件\n const canContinue = outgoing.write(value);\n if (!canContinue) {\n await new Promise<void>((resolve) => {\n outgoing.once(\"drain\", resolve);\n });\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * 将 Web Response 写入 Node.js ServerResponse\n * 流式写入,零拷贝\n */\nexport async function writeResponse(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n // 设置状态码\n outgoing.statusCode = response.status;\n\n // 设置响应头\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n\n // 无 body 的情况\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 流式写入 body\n try {\n await writeBodyStream(body, outgoing);\n outgoing.end();\n } catch (error) {\n // 处理客户端提前断开等情况\n if (!outgoing.destroyed) {\n outgoing.destroy(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n}\n\n/**\n * 简化版写入(用于已知小体积响应)\n * 直接 arrayBuffer 转换,适用于确定的小响应\n */\nexport async function writeResponseSimple(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n outgoing.statusCode = response.status;\n\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 对于小响应,直接读取全部内容\n const buffer = await response.arrayBuffer();\n outgoing.end(Buffer.from(buffer));\n}\n"],"mappings":";;;;;AAWA,SAAS,qBACP,SACmC;CACnC,MAAM,SAA4C,EAAE;CACpD,MAAM,UAAoB,EAAE;AAE5B,SAAQ,SAAS,OAAO,QAAQ;AAC9B,MAAI,QAAQ,aACV,SAAQ,KAAK,MAAM;MAEnB,QAAO,OAAO;GAEhB;AAEF,KAAI,QAAQ,SAAS,EACnB,QAAO,gBAAgB;AAGzB,QAAO;;;;;;AAOT,eAAe,gBACb,MACA,UACe;CACf,MAAM,SAAS,KAAK,WAAW;AAE/B,KAAI;AACF,SAAO,MAAM;GACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAE3C,OAAI,KACF;AAKF,OAAI,CADgB,SAAS,MAAM,MAAM,CAEvC,OAAM,IAAI,SAAe,YAAY;AACnC,aAAS,KAAK,SAAS,QAAQ;KAC/B;;WAGE;AACR,SAAO,aAAa;;;;;;;AAQxB,eAAsB,cACpB,UACA,UACe;AAEf,UAAS,aAAa,SAAS;CAG/B,MAAM,UAAU,qBAAqB,SAAS,QAAQ;AACtD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,UAAS,UAAU,KAAK,MAAM;CAGhC,MAAM,OAAO,SAAS;AAGtB,KAAI,CAAC,MAAM;AACT,WAAS,KAAK;AACd;;AAIF,KAAI;AACF,QAAM,gBAAgB,MAAM,SAAS;AACrC,WAAS,KAAK;UACP,OAAO;AAEd,MAAI,CAAC,SAAS,UACZ,UAAS,QACP,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAC1D;;;;;;;AASP,eAAsB,oBACpB,UACA,UACe;AACf,UAAS,aAAa,SAAS;CAE/B,MAAM,UAAU,qBAAqB,SAAS,QAAQ;AACtD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,UAAS,UAAU,KAAK,MAAM;AAIhC,KAAI,CADS,SAAS,MACX;AACT,WAAS,KAAK;AACd;;CAIF,MAAM,SAAS,MAAM,SAAS,aAAa;AAC3C,UAAS,IAAI,OAAO,KAAK,OAAO,CAAC"}
1
+ {"version":3,"file":"response-BnkYA4pj.mjs","names":[],"sources":["../src/node-server/response.ts"],"sourcesContent":["/**\n * 优化的 Response 写入\n * 流式写入,避免内存拷贝\n */\n\nimport type { ServerResponse } from \"node:http\";\n\n/**\n * 构建 Node.js 响应头\n * 处理 set-cookie 多值情况\n */\nfunction buildOutgoingHeaders(\n headers: Headers,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n const cookies: string[] = [];\n\n headers.forEach((value, key) => {\n if (key === \"set-cookie\") {\n cookies.push(value);\n } else {\n result[key] = value;\n }\n });\n\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n\n return result;\n}\n\n/**\n * 流式写入 Response body 到 ServerResponse\n * 支持背压处理,避免内存溢出\n */\nasync function writeBodyStream(\n body: ReadableStream<Uint8Array>,\n outgoing: ServerResponse,\n): Promise<void> {\n const reader = body.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n // 背压处理:如果写入返回 false,等待 drain 事件\n const canContinue = outgoing.write(value);\n if (!canContinue) {\n await new Promise<void>((resolve) => {\n outgoing.once(\"drain\", resolve);\n });\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * 将 Web Response 写入 Node.js ServerResponse\n * 流式写入,零拷贝\n */\nexport async function writeResponse(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n // 设置状态码\n outgoing.statusCode = response.status;\n\n // 设置响应头\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n\n // 无 body 的情况\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 流式写入 body\n try {\n await writeBodyStream(body, outgoing);\n outgoing.end();\n } catch (error) {\n // 处理客户端提前断开等情况\n if (!outgoing.destroyed) {\n outgoing.destroy(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n}\n\n/**\n * 简化版写入(用于已知小体积响应)\n * 直接 arrayBuffer 转换,适用于确定的小响应\n */\nexport async function writeResponseSimple(\n response: Response,\n outgoing: ServerResponse,\n): Promise<void> {\n outgoing.statusCode = response.status;\n\n const headers = buildOutgoingHeaders(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n outgoing.setHeader(key, value);\n }\n\n const body = response.body;\n if (!body) {\n outgoing.end();\n return;\n }\n\n // 对于小响应,直接读取全部内容\n const buffer = await response.arrayBuffer();\n outgoing.end(Buffer.from(buffer));\n}\n"],"mappings":";;;;;AAWA,SAAS,qBACP,SACmC;CACnC,MAAM,SAA4C,EAAE;CACpD,MAAM,UAAoB,EAAE;AAE5B,SAAQ,SAAS,OAAO,QAAQ;AAC9B,MAAI,QAAQ,aACV,SAAQ,KAAK,MAAM;MAEnB,QAAO,OAAO;GAEhB;AAEF,KAAI,QAAQ,SAAS,EACnB,QAAO,gBAAgB;AAGzB,QAAO;;;;;;AAOT,eAAe,gBACb,MACA,UACe;CACf,MAAM,SAAS,KAAK,WAAW;AAE/B,KAAI;AACF,SAAO,MAAM;GACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAE3C,OAAI,KACF;AAKF,OAAI,CADgB,SAAS,MAAM,MAAM,CAEvC,OAAM,IAAI,SAAe,YAAY;AACnC,aAAS,KAAK,SAAS,QAAQ;KAC/B;;WAGE;AACR,SAAO,aAAa;;;;;;;AAQxB,eAAsB,cACpB,UACA,UACe;AAEf,UAAS,aAAa,SAAS;CAG/B,MAAM,UAAU,qBAAqB,SAAS,QAAQ;AACtD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,UAAS,UAAU,KAAK,MAAM;CAGhC,MAAM,OAAO,SAAS;AAGtB,KAAI,CAAC,MAAM;AACT,WAAS,KAAK;AACd;;AAIF,KAAI;AACF,QAAM,gBAAgB,MAAM,SAAS;AACrC,WAAS,KAAK;UACP,OAAO;AAEd,MAAI,CAAC,SAAS,UACZ,UAAS,QACP,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAC1D;;;;;;;AASP,eAAsB,oBACpB,UACA,UACe;AACf,UAAS,aAAa,SAAS;CAE/B,MAAM,UAAU,qBAAqB,SAAS,QAAQ;AACtD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,UAAS,UAAU,KAAK,MAAM;AAIhC,KAAI,CADS,SAAS,MACX;AACT,WAAS,KAAK;AACd;;CAIF,MAAM,SAAS,MAAM,SAAS,aAAa;AAC3C,UAAS,IAAI,OAAO,KAAK,OAAO,CAAC"}
@@ -1,4 +1,4 @@
1
- import { c as ResponseBody, l as Route } from "./types-DuTa8AVN.mjs";
1
+ import { c as ResponseBody, l as Route } from "./types-D1PUFkda.mjs";
2
2
 
3
3
  //#region src/types/route.d.ts
4
4
  interface Middleware {
@@ -41,4 +41,4 @@ declare function createTypedRoute(config: ExtendedRouteConfig): ExtendedRouteCon
41
41
  declare function isTypedRoute(route: any): route is TypedRoute;
42
42
  //#endregion
43
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-BJ-40LNI.d.mts.map
44
+ //# sourceMappingURL=route-6A7umH7b.d.mts.map
@@ -8,4 +8,4 @@ function isTypedRoute(route) {
8
8
 
9
9
  //#endregion
10
10
  export { isTypedRoute as n, createTypedRoute as t };
11
- //# sourceMappingURL=route-9pAVP1GC.mjs.map
11
+ //# sourceMappingURL=route-Ds53PR4M.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"route-9pAVP1GC.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
+ {"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,4 +1,4 @@
1
- import { a as Method, n as FlattenedRoute } from "./types-DuTa8AVN.mjs";
1
+ import { a as Method, n as FlattenedRoute } from "./types-D1PUFkda.mjs";
2
2
 
3
3
  //#region src/utils/route-registry.d.ts
4
4
 
@@ -173,4 +173,4 @@ declare function getAllRoutes(): RouteMeta[];
173
173
  declare function filterRoutes<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[];
174
174
  //#endregion
175
175
  export { getAllRoutes as a, setGlobalRegistry as c, filterRoutes as i, RouteRegistry as n, getRoute as o, createRouteRegistry as r, getRouteRegistry as s, RouteMeta as t };
176
- //# sourceMappingURL=route-registry--tx1PNui.d.mts.map
176
+ //# sourceMappingURL=route-registry-CmABJA2V.d.mts.map