vafast 0.4.3 → 0.4.4

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 (163) hide show
  1. package/dist/{base-server-Bq4_lJWK.mjs → base-server-CSkyjEaY.mjs} +2 -2
  2. package/dist/{base-server-Bq4_lJWK.mjs.map → base-server-CSkyjEaY.mjs.map} +1 -1
  3. package/dist/{base-server-Gakrozqk.d.mts → base-server-DvGS6ATg.d.mts} +2 -2
  4. package/dist/{base64url-BY-HBSpL.d.mts → base64url-0N9uQPjZ.d.mts} +1 -1
  5. package/dist/{base64url-DLDOeXsk.mjs → base64url-CwQnvZyp.mjs} +1 -1
  6. package/dist/{base64url-DLDOeXsk.mjs.map → base64url-CwQnvZyp.mjs.map} +1 -1
  7. package/dist/{component-route-BYV_X1rA.d.mts → component-route-CZawYn61.d.mts} +2 -2
  8. package/dist/{component-router-DXUXLp1R.mjs → component-router-CErbGh2A.mjs} +2 -2
  9. package/dist/{component-router-DXUXLp1R.mjs.map → component-router-CErbGh2A.mjs.map} +1 -1
  10. package/dist/{component-server-BOz4Q-Qt.d.mts → component-server-CGzU4bss.d.mts} +4 -4
  11. package/dist/{component-server-ARXvZJUQ.mjs → component-server-DAbIyIPI.mjs} +7 -7
  12. package/dist/{component-server-ARXvZJUQ.mjs.map → component-server-DAbIyIPI.mjs.map} +1 -1
  13. package/dist/{create-handler-CbSoroA1.mjs → create-handler-B_pfxh3m.mjs} +5 -5
  14. package/dist/{create-handler-CbSoroA1.mjs.map → create-handler-B_pfxh3m.mjs.map} +1 -1
  15. package/dist/{create-handler-Dtt0xv6g.d.mts → create-handler-Bo-hvWp-.d.mts} +2 -2
  16. package/dist/defineRoute.d.mts +3 -3
  17. package/dist/{dependency-manager-Dbug5INp.d.mts → dependency-manager-C6vFWP2L.d.mts} +1 -1
  18. package/dist/{dependency-manager-CPkwMI7J.mjs → dependency-manager-Czg7Po2j.mjs} +2 -2
  19. package/dist/{dependency-manager-CPkwMI7J.mjs.map → dependency-manager-Czg7Po2j.mjs.map} +1 -1
  20. package/dist/{formats-BSqJWCsG.d.mts → formats-CYLwo9GJ.d.mts} +1 -1
  21. package/dist/{go-await-B-KP-K8x.mjs → go-await-BGAGJfrB.mjs} +1 -1
  22. package/dist/{go-await-B-KP-K8x.mjs.map → go-await-BGAGJfrB.mjs.map} +1 -1
  23. package/dist/{go-await-CqPx9dVQ.d.mts → go-await-DRItVwwh.d.mts} +1 -1
  24. package/dist/{handle-BhpqNgGf.mjs → handle-Csjtywdc.mjs} +2 -2
  25. package/dist/{handle-BhpqNgGf.mjs.map → handle-Csjtywdc.mjs.map} +1 -1
  26. package/dist/{handle-DOidKTI-.d.mts → handle-D0TFoOiX.d.mts} +1 -1
  27. package/dist/{html-renderer-C3LKTLme.d.mts → html-renderer-CMGKJoIy.d.mts} +1 -1
  28. package/dist/{html-renderer-CJ3B2Hft.mjs → html-renderer-CczE8mwC.mjs} +2 -2
  29. package/dist/{html-renderer-CJ3B2Hft.mjs.map → html-renderer-CczE8mwC.mjs.map} +1 -1
  30. package/dist/{index-DFsQyT61.d.mts → index-Ci52vt55.d.mts} +5 -5
  31. package/dist/index.d.mts +24 -29
  32. package/dist/index.mjs +22 -27
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/middleware/component-router.d.mts +1 -1
  35. package/dist/middleware/component-router.mjs +1 -1
  36. package/dist/{middleware-3ShRJyd1.mjs → middleware-Byp3Hjae.mjs} +3 -3
  37. package/dist/{middleware-3ShRJyd1.mjs.map → middleware-Byp3Hjae.mjs.map} +1 -1
  38. package/dist/middleware.d.mts +3 -3
  39. package/dist/middleware.mjs +1 -1
  40. package/dist/monitoring/index.d.mts +6 -6
  41. package/dist/monitoring/index.mjs +3 -3
  42. package/dist/monitoring/native-monitor.d.mts +6 -6
  43. package/dist/monitoring/native-monitor.mjs +4 -4
  44. package/dist/node-server/index.d.mts +1 -1
  45. package/dist/node-server/index.mjs +3 -3
  46. package/dist/node-server/request.mjs +1 -1
  47. package/dist/node-server/response.mjs +1 -1
  48. package/dist/node-server/serve.d.mts +1 -1
  49. package/dist/node-server/serve.mjs +2 -2
  50. package/dist/{parsers-CodQFP1Z.d.mts → parsers-7lvt3Oss.d.mts} +1 -1
  51. package/dist/{parsers-ROIZWSGI.mjs → parsers-CI_TZ7pO.mjs} +1 -1
  52. package/dist/{parsers-ROIZWSGI.mjs.map → parsers-CI_TZ7pO.mjs.map} +1 -1
  53. package/dist/{path-matcher-CXMJ-IrG.mjs → path-matcher-73cJd5Y7.mjs} +2 -2
  54. package/dist/{path-matcher-CXMJ-IrG.mjs.map → path-matcher-73cJd5Y7.mjs.map} +1 -1
  55. package/dist/{radix-tree-BWmhTLhT.mjs → radix-tree-D0XYaJKb.mjs} +2 -2
  56. package/dist/{radix-tree-BWmhTLhT.mjs.map → radix-tree-D0XYaJKb.mjs.map} +1 -1
  57. package/dist/{request-B2BkUecT.mjs → request-CKC3Ox6M.mjs} +1 -1
  58. package/dist/{request-B2BkUecT.mjs.map → request-CKC3Ox6M.mjs.map} +1 -1
  59. package/dist/{request-validator-u2Ccj3_x.d.mts → request-validator-42lY21gn.d.mts} +2 -2
  60. package/dist/{request-validator-Dyqng-H_.mjs → request-validator-_J5HloRq.mjs} +3 -3
  61. package/dist/{request-validator-Dyqng-H_.mjs.map → request-validator-_J5HloRq.mjs.map} +1 -1
  62. package/dist/{response-CUyV5FIm.d.mts → response-A-sZZiJ7.d.mts} +1 -1
  63. package/dist/{response-BhFKEphr.mjs → response-Cf5FgtmE.mjs} +1 -1
  64. package/dist/{response-BhFKEphr.mjs.map → response-Cf5FgtmE.mjs.map} +1 -1
  65. package/dist/{response-CSKW5hsS.mjs → response-DXg4i_yh.mjs} +2 -2
  66. package/dist/{response-CSKW5hsS.mjs.map → response-DXg4i_yh.mjs.map} +1 -1
  67. package/dist/{route-BRR15b-p.mjs → route-9pAVP1GC.mjs} +1 -1
  68. package/dist/{route-BRR15b-p.mjs.map → route-9pAVP1GC.mjs.map} +1 -1
  69. package/dist/{route-BqmWCG4e.d.mts → route-BJ-40LNI.d.mts} +2 -2
  70. package/dist/{route-registry-ykzRmaHB.d.mts → route-registry--tx1PNui.d.mts} +2 -2
  71. package/dist/{route-registry-AlkDgbcE.mjs → route-registry-mcTG0M-t.mjs} +2 -2
  72. package/dist/{route-registry-AlkDgbcE.mjs.map → route-registry-mcTG0M-t.mjs.map} +1 -1
  73. package/dist/router/index.d.mts +2 -2
  74. package/dist/router/index.mjs +2 -2
  75. package/dist/router/radix-tree.d.mts +3 -3
  76. package/dist/router/radix-tree.mjs +1 -1
  77. package/dist/{router-BOeVQrjz.mjs → router-B9HUUCkR.mjs} +2 -2
  78. package/dist/{router-BOeVQrjz.mjs.map → router-B9HUUCkR.mjs.map} +1 -1
  79. package/dist/router.d.mts +3 -3
  80. package/dist/router.mjs +1 -1
  81. package/dist/{schema-CVuttFSw.d.mts → schema-CPQudJpE.d.mts} +1 -1
  82. package/dist/{serve-BQQ2JzIH.d.mts → serve-B5WmhK6m.d.mts} +1 -1
  83. package/dist/{serve-MRGGK7-q.mjs → serve-Be6NvuQk.mjs} +3 -3
  84. package/dist/{serve-MRGGK7-q.mjs.map → serve-Be6NvuQk.mjs.map} +1 -1
  85. package/dist/serve.d.mts +1 -1
  86. package/dist/serve.mjs +2 -2
  87. package/dist/server/base-server.d.mts +3 -3
  88. package/dist/server/base-server.mjs +1 -1
  89. package/dist/server/component-server.d.mts +4 -4
  90. package/dist/server/component-server.mjs +2 -2
  91. package/dist/server/index.d.mts +6 -6
  92. package/dist/server/index.mjs +5 -5
  93. package/dist/server/server-factory.d.mts +6 -6
  94. package/dist/server/server-factory.mjs +3 -3
  95. package/dist/server/server.d.mts +4 -4
  96. package/dist/server/server.mjs +1 -1
  97. package/dist/{server-C8WCshmG.mjs → server-BmPKs8oM.mjs} +8 -8
  98. package/dist/{server-C8WCshmG.mjs.map → server-BmPKs8oM.mjs.map} +1 -1
  99. package/dist/{server-B0nzGCG5.mjs → server-Cbd3Ia51.mjs} +5 -5
  100. package/dist/{server-B0nzGCG5.mjs.map → server-Cbd3Ia51.mjs.map} +1 -1
  101. package/dist/{server-Drc2kSxp.d.mts → server-D9gjszHe.d.mts} +3 -3
  102. package/dist/{sse-BOd2pvUK.d.mts → sse-BMM6KTfy.d.mts} +2 -2
  103. package/dist/{sse-US5D9mgE.mjs → sse-BT5yyLgX.mjs} +3 -3
  104. package/dist/{sse-US5D9mgE.mjs.map → sse-BT5yyLgX.mjs.map} +1 -1
  105. package/dist/types/component-route.d.mts +1 -1
  106. package/dist/types/index.d.mts +5 -5
  107. package/dist/types/index.mjs +1 -1
  108. package/dist/types/route.d.mts +1 -1
  109. package/dist/types/route.mjs +1 -1
  110. package/dist/types/schema.d.mts +1 -1
  111. package/dist/types/types.d.mts +1 -1
  112. package/dist/{types-Cb7_2VSt.d.mts → types-DuTa8AVN.d.mts} +1 -1
  113. package/dist/utils/base64url.d.mts +1 -1
  114. package/dist/utils/base64url.mjs +1 -1
  115. package/dist/utils/create-handler.d.mts +2 -2
  116. package/dist/utils/create-handler.mjs +3 -3
  117. package/dist/utils/dependency-manager.d.mts +1 -1
  118. package/dist/utils/dependency-manager.mjs +1 -1
  119. package/dist/utils/formats.d.mts +1 -1
  120. package/dist/utils/go-await.d.mts +1 -1
  121. package/dist/utils/go-await.mjs +1 -1
  122. package/dist/utils/handle.d.mts +1 -1
  123. package/dist/utils/handle.mjs +2 -2
  124. package/dist/utils/html-renderer.d.mts +1 -1
  125. package/dist/utils/html-renderer.mjs +1 -1
  126. package/dist/utils/index.d.mts +15 -15
  127. package/dist/utils/index.mjs +12 -12
  128. package/dist/utils/parsers.d.mts +1 -1
  129. package/dist/utils/parsers.mjs +1 -1
  130. package/dist/utils/path-matcher.mjs +1 -1
  131. package/dist/utils/request-validator.d.mts +2 -2
  132. package/dist/utils/request-validator.mjs +3 -3
  133. package/dist/utils/response.d.mts +1 -1
  134. package/dist/utils/response.mjs +1 -1
  135. package/dist/utils/route-registry.d.mts +3 -3
  136. package/dist/utils/route-registry.mjs +1 -1
  137. package/dist/utils/sse.d.mts +2 -2
  138. package/dist/utils/sse.mjs +3 -3
  139. package/dist/utils/validators/validators.d.mts +1 -1
  140. package/dist/utils/validators/validators.mjs +1 -1
  141. package/dist/{validators-CbCLj0Rc.mjs → validators-BBrGePBr.mjs} +1 -1
  142. package/dist/{validators-CbCLj0Rc.mjs.map → validators-BBrGePBr.mjs.map} +1 -1
  143. package/dist/{validators-C0eZyxPh.d.mts → validators-CPmnj_y9.d.mts} +1 -1
  144. package/package.json +1 -1
  145. package/dist/auth/token.d.mts +0 -44
  146. package/dist/auth/token.mjs +0 -105
  147. package/dist/auth/token.mjs.map +0 -1
  148. package/dist/middleware/auth.d.mts +0 -20
  149. package/dist/middleware/auth.mjs +0 -98
  150. package/dist/middleware/auth.mjs.map +0 -1
  151. package/dist/middleware/authMiddleware.d.mts +0 -9
  152. package/dist/middleware/authMiddleware.mjs +0 -19
  153. package/dist/middleware/authMiddleware.mjs.map +0 -1
  154. package/dist/middleware/cors.d.mts +0 -16
  155. package/dist/middleware/cors.mjs +0 -38
  156. package/dist/middleware/cors.mjs.map +0 -1
  157. package/dist/middleware/rateLimit.d.mts +0 -14
  158. package/dist/middleware/rateLimit.mjs +0 -34
  159. package/dist/middleware/rateLimit.mjs.map +0 -1
  160. /package/dist/{chunk-67U6L5Jh.mjs → chunk-DW4-Jl94.mjs} +0 -0
  161. /package/dist/{component-route-Do2yyYTi.mjs → component-route-CYxLOnci.mjs} +0 -0
  162. /package/dist/{index-DXJd7-2Z.d.mts → index-CzItj62a.d.mts} +0 -0
  163. /package/dist/{schema-CbAaktsZ.mjs → schema-CtVBNfnQ.mjs} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"sse-US5D9mgE.mjs","names":[],"sources":["../src/utils/sse.ts"],"sourcesContent":["/**\n * Server-Sent Events (SSE) 支持\n *\n * 用于实现流式响应,如 AI 聊天、实时通知等\n *\n * @example\n * ```typescript\n * import { createSSEHandler, Type } from 'vafast'\n *\n * const streamHandler = createSSEHandler(\n * { query: Type.Object({ prompt: Type.String() }) },\n * async function* ({ query }) {\n * yield { event: 'start', data: { message: 'Starting...' } }\n *\n * for await (const chunk of aiStream(query.prompt)) {\n * yield { data: chunk }\n * }\n *\n * yield { event: 'end', data: { message: 'Done!' } }\n * }\n * )\n * ```\n */\n\nimport type { RouteSchema, HandlerContext } from \"../types/schema\";\nimport { parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { precompileSchemas, validateAllSchemas } from \"./validators/validators\";\n\n/**\n * SSE 事件类型\n */\nexport interface SSEEvent<T = unknown> {\n /** 事件名称(可选,默认为 message) */\n event?: string;\n /** 事件数据 */\n data: T;\n /** 事件 ID(可选) */\n id?: string;\n /** 重试间隔(毫秒,可选) */\n retry?: number;\n}\n\n/**\n * SSE 生成器函数类型\n */\nexport type SSEGenerator<T extends RouteSchema = RouteSchema> = (\n ctx: HandlerContext<T>\n) => AsyncGenerator<SSEEvent<unknown>, void, unknown>;\n\n/**\n * 格式化 SSE 事件为字符串\n */\nfunction formatSSEEvent(event: SSEEvent): string {\n const lines: string[] = [];\n\n if (event.id !== undefined) {\n lines.push(`id: ${event.id}`);\n }\n\n if (event.event !== undefined) {\n lines.push(`event: ${event.event}`);\n }\n\n if (event.retry !== undefined) {\n lines.push(`retry: ${event.retry}`);\n }\n\n // 数据可能是多行的,需要分行处理\n const dataStr = typeof event.data === 'string'\n ? event.data\n : JSON.stringify(event.data);\n\n const dataLines = dataStr.split('\\n');\n for (const line of dataLines) {\n lines.push(`data: ${line}`);\n }\n\n return lines.join('\\n') + '\\n\\n';\n}\n\n/**\n * SSE 标记类型 - 使用字面量品牌类型\n */\nexport type SSEMarker = { readonly __brand: 'SSE' }\n\n/**\n * SSE Handler 类型标记\n */\nexport interface SSEHandler<TSchema extends RouteSchema = RouteSchema> {\n (req: Request): Promise<Response>;\n /** 返回类型标记 - SSE 流的数据类型 */\n readonly __returnType: unknown;\n /** Schema 类型标记 */\n readonly __schema: TSchema;\n /** SSE 标记 - 使用品牌类型确保不被扩展 */\n readonly __sse: SSEMarker;\n}\n\n/**\n * 创建 SSE 流式响应处理器\n *\n * @example\n * ```typescript\n * // 基础用法\n * const streamChat = createSSEHandler(\n * { query: Type.Object({ message: Type.String() }) },\n * async function* ({ query }) {\n * const response = await ai.chat(query.message);\n *\n * for await (const chunk of response) {\n * yield { data: { text: chunk } };\n * }\n * }\n * );\n *\n * // 使用路由\n * route('GET', '/chat/stream', streamChat)\n * ```\n */\nexport function createSSEHandler<const T extends RouteSchema>(\n schema: T,\n generator: SSEGenerator<T>\n): SSEHandler<T>;\n\nexport function createSSEHandler(\n generator: SSEGenerator<RouteSchema>\n): SSEHandler<RouteSchema>;\n\nexport function createSSEHandler<const T extends RouteSchema>(\n schemaOrGenerator: T | SSEGenerator<T>,\n maybeGenerator?: SSEGenerator<T>\n): SSEHandler<T> {\n // 判断调用方式\n const hasSchema = typeof schemaOrGenerator !== 'function';\n const schema = hasSchema ? (schemaOrGenerator as T) : ({} as T);\n const generator = hasSchema\n ? maybeGenerator!\n : (schemaOrGenerator as SSEGenerator<T>);\n\n // 预编译 schema\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\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 = ((req as unknown as Record<string, unknown>).params as Record<string, string>) || {};\n\n // 验证 schema\n const data = { body: undefined, query, params, headers, cookies };\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\n validateAllSchemas(schema, data);\n }\n\n // 创建 SSE 流\n const stream = new ReadableStream({\n async start(controller) {\n const encoder = new TextEncoder();\n\n try {\n const gen = generator({\n req,\n body: undefined 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 for await (const event of gen) {\n const formatted = formatSSEEvent(event);\n controller.enqueue(encoder.encode(formatted));\n }\n } catch (error) {\n // 发送错误事件\n const errorEvent = formatSSEEvent({\n event: 'error',\n data: {\n message: error instanceof Error ? error.message : 'Unknown error'\n }\n });\n controller.enqueue(encoder.encode(errorEvent));\n } finally {\n controller.close();\n }\n }\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no', // Nginx 禁用缓冲\n }\n });\n } catch (error) {\n // 验证错误等\n return new Response(\n JSON.stringify({\n success: false,\n error: 'Validation Error',\n message: error instanceof Error ? error.message : 'Unknown error'\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n };\n\n // 添加类型标记\n const handler = handlerFn as SSEHandler<T>;\n (handler as unknown as { __sse: SSEMarker }).__sse = { __brand: 'SSE' } as const;\n (handler as unknown as { __schema: T }).__schema = schema;\n (handler as unknown as { __returnType: unknown }).__returnType = undefined;\n return handler;\n}\n\n\n"],"mappings":";;;;;;;AAoDA,SAAS,eAAe,OAAyB;CAC/C,MAAM,QAAkB,EAAE;AAE1B,KAAI,MAAM,OAAO,OACf,OAAM,KAAK,OAAO,MAAM,KAAK;AAG/B,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;AAGrC,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;CAQrC,MAAM,aAJU,OAAO,MAAM,SAAS,WAClC,MAAM,OACN,KAAK,UAAU,MAAM,KAAK,EAEJ,MAAM,KAAK;AACrC,MAAK,MAAM,QAAQ,UACjB,OAAM,KAAK,SAAS,OAAO;AAG7B,QAAO,MAAM,KAAK,KAAK,GAAG;;AAmD5B,SAAgB,iBACd,mBACA,gBACe;CAEf,MAAM,YAAY,OAAO,sBAAsB;CAC/C,MAAM,SAAS,YAAa,oBAA2B,EAAE;CACzD,MAAM,YAAY,YACd,iBACC;AAGL,KAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,mBAAkB,OAAO;CAG3B,MAAM,YAAY,OAAO,QAAoC;AAC3D,MAAI;GAEF,MAAM,QAAQ,WAAW,IAAI;GAC7B,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,SAAW,IAA2C,UAAqC,EAAE;GAGnG,MAAM,OAAO;IAAE,MAAM;IAAW;IAAO;IAAQ;IAAS;IAAS;AACjE,OAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,oBAAmB,QAAQ,KAAK;GAIlC,MAAM,SAAS,IAAI,eAAe,EAChC,MAAM,MAAM,YAAY;IACtB,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAI;KACF,MAAM,MAAM,UAAU;MACpB;MACA,MAAM;MACC;MACC;MACC;MACA;MACV,CAAC;AAEF,gBAAW,MAAM,SAAS,KAAK;MAC7B,MAAM,YAAY,eAAe,MAAM;AACvC,iBAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;;aAExC,OAAO;KAEd,MAAM,aAAa,eAAe;MAChC,OAAO;MACP,MAAM,EACJ,SAAS,iBAAiB,QAAQ,MAAM,UAAU,iBACnD;MACF,CAAC;AACF,gBAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;cACtC;AACR,gBAAW,OAAO;;MAGvB,CAAC;AAEF,UAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IACjB,cAAc;IACd,qBAAqB;IACtB,EACF,CAAC;WACK,OAAO;AAEd,UAAO,IAAI,SACT,KAAK,UAAU;IACb,SAAS;IACT,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IACnD,CAAC,EACF;IACE,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAChD,CACF;;;CAKL,MAAM,UAAU;AAChB,CAAC,QAA4C,QAAQ,EAAE,SAAS,OAAO;AACvE,CAAC,QAAuC,WAAW;AACnD,CAAC,QAAiD,eAAe;AACjE,QAAO"}
1
+ {"version":3,"file":"sse-BT5yyLgX.mjs","names":[],"sources":["../src/utils/sse.ts"],"sourcesContent":["/**\n * Server-Sent Events (SSE) 支持\n *\n * 用于实现流式响应,如 AI 聊天、实时通知等\n *\n * @example\n * ```typescript\n * import { createSSEHandler, Type } from 'vafast'\n *\n * const streamHandler = createSSEHandler(\n * { query: Type.Object({ prompt: Type.String() }) },\n * async function* ({ query }) {\n * yield { event: 'start', data: { message: 'Starting...' } }\n *\n * for await (const chunk of aiStream(query.prompt)) {\n * yield { data: chunk }\n * }\n *\n * yield { event: 'end', data: { message: 'Done!' } }\n * }\n * )\n * ```\n */\n\nimport type { RouteSchema, HandlerContext } from \"../types/schema\";\nimport { parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { precompileSchemas, validateAllSchemas } from \"./validators/validators\";\n\n/**\n * SSE 事件类型\n */\nexport interface SSEEvent<T = unknown> {\n /** 事件名称(可选,默认为 message) */\n event?: string;\n /** 事件数据 */\n data: T;\n /** 事件 ID(可选) */\n id?: string;\n /** 重试间隔(毫秒,可选) */\n retry?: number;\n}\n\n/**\n * SSE 生成器函数类型\n */\nexport type SSEGenerator<T extends RouteSchema = RouteSchema> = (\n ctx: HandlerContext<T>\n) => AsyncGenerator<SSEEvent<unknown>, void, unknown>;\n\n/**\n * 格式化 SSE 事件为字符串\n */\nfunction formatSSEEvent(event: SSEEvent): string {\n const lines: string[] = [];\n\n if (event.id !== undefined) {\n lines.push(`id: ${event.id}`);\n }\n\n if (event.event !== undefined) {\n lines.push(`event: ${event.event}`);\n }\n\n if (event.retry !== undefined) {\n lines.push(`retry: ${event.retry}`);\n }\n\n // 数据可能是多行的,需要分行处理\n const dataStr = typeof event.data === 'string'\n ? event.data\n : JSON.stringify(event.data);\n\n const dataLines = dataStr.split('\\n');\n for (const line of dataLines) {\n lines.push(`data: ${line}`);\n }\n\n return lines.join('\\n') + '\\n\\n';\n}\n\n/**\n * SSE 标记类型 - 使用字面量品牌类型\n */\nexport type SSEMarker = { readonly __brand: 'SSE' }\n\n/**\n * SSE Handler 类型标记\n */\nexport interface SSEHandler<TSchema extends RouteSchema = RouteSchema> {\n (req: Request): Promise<Response>;\n /** 返回类型标记 - SSE 流的数据类型 */\n readonly __returnType: unknown;\n /** Schema 类型标记 */\n readonly __schema: TSchema;\n /** SSE 标记 - 使用品牌类型确保不被扩展 */\n readonly __sse: SSEMarker;\n}\n\n/**\n * 创建 SSE 流式响应处理器\n *\n * @example\n * ```typescript\n * // 基础用法\n * const streamChat = createSSEHandler(\n * { query: Type.Object({ message: Type.String() }) },\n * async function* ({ query }) {\n * const response = await ai.chat(query.message);\n *\n * for await (const chunk of response) {\n * yield { data: { text: chunk } };\n * }\n * }\n * );\n *\n * // 使用路由\n * route('GET', '/chat/stream', streamChat)\n * ```\n */\nexport function createSSEHandler<const T extends RouteSchema>(\n schema: T,\n generator: SSEGenerator<T>\n): SSEHandler<T>;\n\nexport function createSSEHandler(\n generator: SSEGenerator<RouteSchema>\n): SSEHandler<RouteSchema>;\n\nexport function createSSEHandler<const T extends RouteSchema>(\n schemaOrGenerator: T | SSEGenerator<T>,\n maybeGenerator?: SSEGenerator<T>\n): SSEHandler<T> {\n // 判断调用方式\n const hasSchema = typeof schemaOrGenerator !== 'function';\n const schema = hasSchema ? (schemaOrGenerator as T) : ({} as T);\n const generator = hasSchema\n ? maybeGenerator!\n : (schemaOrGenerator as SSEGenerator<T>);\n\n // 预编译 schema\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\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 = ((req as unknown as Record<string, unknown>).params as Record<string, string>) || {};\n\n // 验证 schema\n const data = { body: undefined, query, params, headers, cookies };\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\n validateAllSchemas(schema, data);\n }\n\n // 创建 SSE 流\n const stream = new ReadableStream({\n async start(controller) {\n const encoder = new TextEncoder();\n\n try {\n const gen = generator({\n req,\n body: undefined 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 for await (const event of gen) {\n const formatted = formatSSEEvent(event);\n controller.enqueue(encoder.encode(formatted));\n }\n } catch (error) {\n // 发送错误事件\n const errorEvent = formatSSEEvent({\n event: 'error',\n data: {\n message: error instanceof Error ? error.message : 'Unknown error'\n }\n });\n controller.enqueue(encoder.encode(errorEvent));\n } finally {\n controller.close();\n }\n }\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no', // Nginx 禁用缓冲\n }\n });\n } catch (error) {\n // 验证错误等\n return new Response(\n JSON.stringify({\n success: false,\n error: 'Validation Error',\n message: error instanceof Error ? error.message : 'Unknown error'\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n };\n\n // 添加类型标记\n const handler = handlerFn as SSEHandler<T>;\n (handler as unknown as { __sse: SSEMarker }).__sse = { __brand: 'SSE' } as const;\n (handler as unknown as { __schema: T }).__schema = schema;\n (handler as unknown as { __returnType: unknown }).__returnType = undefined;\n return handler;\n}\n\n\n"],"mappings":";;;;;;;AAoDA,SAAS,eAAe,OAAyB;CAC/C,MAAM,QAAkB,EAAE;AAE1B,KAAI,MAAM,OAAO,OACf,OAAM,KAAK,OAAO,MAAM,KAAK;AAG/B,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;AAGrC,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;CAQrC,MAAM,aAJU,OAAO,MAAM,SAAS,WAClC,MAAM,OACN,KAAK,UAAU,MAAM,KAAK,EAEJ,MAAM,KAAK;AACrC,MAAK,MAAM,QAAQ,UACjB,OAAM,KAAK,SAAS,OAAO;AAG7B,QAAO,MAAM,KAAK,KAAK,GAAG;;AAmD5B,SAAgB,iBACd,mBACA,gBACe;CAEf,MAAM,YAAY,OAAO,sBAAsB;CAC/C,MAAM,SAAS,YAAa,oBAA2B,EAAE;CACzD,MAAM,YAAY,YACd,iBACC;AAGL,KAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,mBAAkB,OAAO;CAG3B,MAAM,YAAY,OAAO,QAAoC;AAC3D,MAAI;GAEF,MAAM,QAAQ,WAAW,IAAI;GAC7B,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,SAAW,IAA2C,UAAqC,EAAE;GAGnG,MAAM,OAAO;IAAE,MAAM;IAAW;IAAO;IAAQ;IAAS;IAAS;AACjE,OAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,oBAAmB,QAAQ,KAAK;GAIlC,MAAM,SAAS,IAAI,eAAe,EAChC,MAAM,MAAM,YAAY;IACtB,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAI;KACF,MAAM,MAAM,UAAU;MACpB;MACA,MAAM;MACC;MACC;MACC;MACA;MACV,CAAC;AAEF,gBAAW,MAAM,SAAS,KAAK;MAC7B,MAAM,YAAY,eAAe,MAAM;AACvC,iBAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;;aAExC,OAAO;KAEd,MAAM,aAAa,eAAe;MAChC,OAAO;MACP,MAAM,EACJ,SAAS,iBAAiB,QAAQ,MAAM,UAAU,iBACnD;MACF,CAAC;AACF,gBAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;cACtC;AACR,gBAAW,OAAO;;MAGvB,CAAC;AAEF,UAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IACjB,cAAc;IACd,qBAAqB;IACtB,EACF,CAAC;WACK,OAAO;AAEd,UAAO,IAAI,SACT,KAAK,UAAU;IACb,SAAS;IACT,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IACnD,CAAC,EACF;IACE,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAChD,CACF;;;CAKL,MAAM,UAAU;AAChB,CAAC,QAA4C,QAAQ,EAAE,SAAS,OAAO;AACvE,CAAC,QAAuC,WAAW;AACnD,CAAC,QAAiD,eAAe;AACjE,QAAO"}
@@ -1,2 +1,2 @@
1
- import { n as FlattenedComponentRoute, r as NestedComponentRoute, t as ComponentRoute } from "../component-route-BYV_X1rA.mjs";
1
+ import { n as FlattenedComponentRoute, r as NestedComponentRoute, t as ComponentRoute } from "../component-route-CZawYn61.mjs";
2
2
  export { ComponentRoute, FlattenedComponentRoute, NestedComponentRoute };
@@ -1,6 +1,6 @@
1
- import { a as Method, c as ResponseBody, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute } from "../types-Cb7_2VSt.mjs";
2
- import { c as createTypedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BqmWCG4e.mjs";
3
- import { n as FlattenedComponentRoute, r as NestedComponentRoute, t as ComponentRoute } from "../component-route-BYV_X1rA.mjs";
4
- import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CVuttFSw.mjs";
5
- import "../index-DXJd7-2Z.mjs";
1
+ import { a as Method, c as ResponseBody, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute } from "../types-DuTa8AVN.mjs";
2
+ import { c as createTypedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BJ-40LNI.mjs";
3
+ import { n as FlattenedComponentRoute, r as NestedComponentRoute, t as ComponentRoute } from "../component-route-CZawYn61.mjs";
4
+ import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CPQudJpE.mjs";
5
+ import "../index-CzItj62a.mjs";
6
6
  export { BaseRouteConfig, CompatibleRoute, ComponentRoute, ExtendedRouteConfig, FlattenedComponentRoute, FlattenedRoute, Handler, HandlerContext, HandlerContextWithExtra, InferSchema, Method, Middleware, NestedComponentRoute, NestedRoute, NestedRouteConfig, ResponseBody, Route, RouteSchema, TypedHandler, TypedRoute, TypedRouteConfig, createTypedRoute, isTypedRoute };
@@ -1,3 +1,3 @@
1
- import { n as isTypedRoute, t as createTypedRoute } from "../route-BRR15b-p.mjs";
1
+ import { n as isTypedRoute, t as createTypedRoute } from "../route-9pAVP1GC.mjs";
2
2
 
3
3
  export { createTypedRoute, isTypedRoute };
@@ -1,2 +1,2 @@
1
- import { a as Middleware, c as createTypedRoute, i as FlattenedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BqmWCG4e.mjs";
1
+ import { a as Middleware, c as createTypedRoute, i as FlattenedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BJ-40LNI.mjs";
2
2
  export { BaseRouteConfig, CompatibleRoute, ExtendedRouteConfig, FlattenedRoute, Middleware, NestedRouteConfig, TypedRoute, createTypedRoute, isTypedRoute };
@@ -1,3 +1,3 @@
1
- import { n as isTypedRoute, t as createTypedRoute } from "../route-BRR15b-p.mjs";
1
+ import { n as isTypedRoute, t as createTypedRoute } from "../route-9pAVP1GC.mjs";
2
2
 
3
3
  export { createTypedRoute, isTypedRoute };
@@ -1,2 +1,2 @@
1
- import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CVuttFSw.mjs";
1
+ import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CPQudJpE.mjs";
2
2
  export { HandlerContext, HandlerContextWithExtra, InferSchema, RouteSchema, TypedHandler, TypedRouteConfig };
@@ -1,2 +1,2 @@
1
- import { a as Method, c as ResponseBody, i as LegacyHandler, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute, t as FactoryHandler } from "../types-Cb7_2VSt.mjs";
1
+ import { a as Method, c as ResponseBody, i as LegacyHandler, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute, t as FactoryHandler } from "../types-DuTa8AVN.mjs";
2
2
  export { FactoryHandler, FlattenedRoute, Handler, LegacyHandler, Method, Middleware, NestedRoute, ResponseBody, Route };
@@ -42,4 +42,4 @@ interface FlattenedRoute extends Route {
42
42
  }
43
43
  //#endregion
44
44
  export { Method as a, ResponseBody as c, LegacyHandler as i, Route as l, FlattenedRoute as n, Middleware as o, Handler as r, NestedRoute as s, FactoryHandler as t };
45
- //# sourceMappingURL=types-Cb7_2VSt.d.mts.map
45
+ //# sourceMappingURL=types-DuTa8AVN.d.mts.map
@@ -1,2 +1,2 @@
1
- import { n as base64urlEncode, t as base64urlDecode } from "../base64url-BY-HBSpL.mjs";
1
+ import { n as base64urlEncode, t as base64urlDecode } from "../base64url-0N9uQPjZ.mjs";
2
2
  export { base64urlDecode, base64urlEncode };
@@ -1,3 +1,3 @@
1
- import { n as base64urlEncode, t as base64urlDecode } from "../base64url-DLDOeXsk.mjs";
1
+ import { n as base64urlEncode, t as base64urlDecode } from "../base64url-CwQnvZyp.mjs";
2
2
 
3
3
  export { base64urlDecode, base64urlEncode };
@@ -1,3 +1,3 @@
1
- import "../schema-CVuttFSw.mjs";
2
- import { i as simpleHandler, n as createHandler, r as createHandlerWithExtra, t as InferableHandler } from "../create-handler-Dtt0xv6g.mjs";
1
+ import "../schema-CPQudJpE.mjs";
2
+ import { i as simpleHandler, n as createHandler, r as createHandlerWithExtra, t as InferableHandler } from "../create-handler-Bo-hvWp-.mjs";
3
3
  export { InferableHandler, createHandler, createHandlerWithExtra, simpleHandler };
@@ -1,5 +1,5 @@
1
- import "../parsers-ROIZWSGI.mjs";
2
- import "../validators-CbCLj0Rc.mjs";
3
- import { n as createHandlerWithExtra, r as simpleHandler, t as createHandler } from "../create-handler-CbSoroA1.mjs";
1
+ import "../parsers-CI_TZ7pO.mjs";
2
+ import "../validators-BBrGePBr.mjs";
3
+ import { n as createHandlerWithExtra, r as simpleHandler, t as createHandler } from "../create-handler-B_pfxh3m.mjs";
4
4
 
5
5
  export { createHandler, createHandlerWithExtra, simpleHandler };
@@ -1,2 +1,2 @@
1
- import { t as DependencyManager } from "../dependency-manager-Dbug5INp.mjs";
1
+ import { t as DependencyManager } from "../dependency-manager-C6vFWP2L.mjs";
2
2
  export { DependencyManager };
@@ -1,4 +1,4 @@
1
- import { n as init_dependency_manager, t as DependencyManager } from "../dependency-manager-CPkwMI7J.mjs";
1
+ import { n as init_dependency_manager, t as DependencyManager } from "../dependency-manager-Czg7Po2j.mjs";
2
2
 
3
3
  init_dependency_manager();
4
4
  export { DependencyManager };
@@ -1,2 +1,2 @@
1
- import { i as registerFormats, n as hasFormat, r as registerFormat, t as Patterns } from "../formats-BSqJWCsG.mjs";
1
+ import { i as registerFormats, n as hasFormat, r as registerFormat, t as Patterns } from "../formats-CYLwo9GJ.mjs";
2
2
  export { Patterns, hasFormat, registerFormat, registerFormats };
@@ -1,2 +1,2 @@
1
- import { t as goAwait } from "../go-await-CqPx9dVQ.mjs";
1
+ import { t as goAwait } from "../go-await-DRItVwwh.mjs";
2
2
  export { goAwait };
@@ -1,3 +1,3 @@
1
- import { t as goAwait } from "../go-await-B-KP-K8x.mjs";
1
+ import { t as goAwait } from "../go-await-BGAGJfrB.mjs";
2
2
 
3
3
  export { goAwait };
@@ -1,2 +1,2 @@
1
- import { i as setLocals, n as getLocals, r as setCookie, t as getCookie } from "../handle-DOidKTI-.mjs";
1
+ import { i as setLocals, n as getLocals, r as setCookie, t as getCookie } from "../handle-D0TFoOiX.mjs";
2
2
  export { getCookie, getLocals, setCookie, setLocals };
@@ -1,4 +1,4 @@
1
- import "../parsers-ROIZWSGI.mjs";
2
- import { i as setLocals, n as getLocals, r as setCookie, t as getCookie } from "../handle-BhpqNgGf.mjs";
1
+ import "../parsers-CI_TZ7pO.mjs";
2
+ import { i as setLocals, n as getLocals, r as setCookie, t as getCookie } from "../handle-Csjtywdc.mjs";
3
3
 
4
4
  export { getCookie, getLocals, setCookie, setLocals };
@@ -1,2 +1,2 @@
1
- import { t as HtmlRenderer } from "../html-renderer-C3LKTLme.mjs";
1
+ import { t as HtmlRenderer } from "../html-renderer-CMGKJoIy.mjs";
2
2
  export { HtmlRenderer };
@@ -1,4 +1,4 @@
1
- import { n as init_html_renderer, t as HtmlRenderer } from "../html-renderer-CJ3B2Hft.mjs";
1
+ import { n as init_html_renderer, t as HtmlRenderer } from "../html-renderer-CczE8mwC.mjs";
2
2
 
3
3
  init_html_renderer();
4
4
  export { HtmlRenderer };
@@ -1,16 +1,16 @@
1
- import "../schema-CVuttFSw.mjs";
2
- import "../index-DXJd7-2Z.mjs";
3
- import { i as simpleHandler, n as createHandler, r as createHandlerWithExtra, t as InferableHandler } from "../create-handler-Dtt0xv6g.mjs";
4
- import { t as DependencyManager } from "../dependency-manager-Dbug5INp.mjs";
5
- import { a as parseBody, c as parseCookiesFast, d as parseHeaders, f as parseQuery, i as getHeader, p as parseQueryFast, r as getCookie, s as parseCookies } from "../parsers-CodQFP1Z.mjs";
6
- import { a as redirect, n as html, o as stream, r as json, s as text, t as empty } from "../response-CUyV5FIm.mjs";
7
- import { t as goAwait } from "../go-await-CqPx9dVQ.mjs";
8
- import { n as base64urlEncode, t as base64urlDecode } from "../base64url-BY-HBSpL.mjs";
9
- import { i as setLocals, n as getLocals } from "../handle-DOidKTI-.mjs";
10
- import { a as ValidationError, c as getValidatorCacheStats, d as validateFast, f as validateSchema, l as precompileSchemas, o as ValidationResult, p as validateSchemaOrThrow, s as createValidator, t as SchemaConfig, u as validateAllSchemas } from "../validators-C0eZyxPh.mjs";
11
- import { a as parseAndValidateRequest, i as createRequestValidator, o as parseRequest, s as validateRequest } from "../request-validator-u2Ccj3_x.mjs";
12
- import { t as HtmlRenderer } from "../html-renderer-C3LKTLme.mjs";
13
- import { i as registerFormats, n as hasFormat, r as registerFormat, t as Patterns } from "../formats-BSqJWCsG.mjs";
14
- import { a as createSSEHandler, i as SSEMarker, r as SSEHandler, t as SSEEvent } from "../sse-BOd2pvUK.mjs";
15
- import { a as getAllRoutes, i as filterRoutes, n as RouteRegistry, o as getRoute, r as createRouteRegistry, s as getRouteRegistry, t as RouteMeta } from "../route-registry-ykzRmaHB.mjs";
1
+ import "../schema-CPQudJpE.mjs";
2
+ import "../index-CzItj62a.mjs";
3
+ import { i as simpleHandler, n as createHandler, r as createHandlerWithExtra, t as InferableHandler } from "../create-handler-Bo-hvWp-.mjs";
4
+ import { t as DependencyManager } from "../dependency-manager-C6vFWP2L.mjs";
5
+ import { a as parseBody, c as parseCookiesFast, d as parseHeaders, f as parseQuery, i as getHeader, p as parseQueryFast, r as getCookie, s as parseCookies } from "../parsers-7lvt3Oss.mjs";
6
+ import { a as redirect, n as html, o as stream, r as json, s as text, t as empty } from "../response-A-sZZiJ7.mjs";
7
+ import { t as goAwait } from "../go-await-DRItVwwh.mjs";
8
+ import { n as base64urlEncode, t as base64urlDecode } from "../base64url-0N9uQPjZ.mjs";
9
+ import { i as setLocals, n as getLocals } from "../handle-D0TFoOiX.mjs";
10
+ import { a as ValidationError, c as getValidatorCacheStats, d as validateFast, f as validateSchema, l as precompileSchemas, o as ValidationResult, p as validateSchemaOrThrow, s as createValidator, t as SchemaConfig, u as validateAllSchemas } from "../validators-CPmnj_y9.mjs";
11
+ import { a as parseAndValidateRequest, i as createRequestValidator, o as parseRequest, s as validateRequest } from "../request-validator-42lY21gn.mjs";
12
+ import { t as HtmlRenderer } from "../html-renderer-CMGKJoIy.mjs";
13
+ import { i as registerFormats, n as hasFormat, r as registerFormat, t as Patterns } from "../formats-CYLwo9GJ.mjs";
14
+ import { a as createSSEHandler, i as SSEMarker, r as SSEHandler, t as SSEEvent } from "../sse-BMM6KTfy.mjs";
15
+ import { a as getAllRoutes, i as filterRoutes, n as RouteRegistry, o as getRoute, r as createRouteRegistry, s as getRouteRegistry, t as RouteMeta } from "../route-registry--tx1PNui.mjs";
16
16
  export { DependencyManager, HtmlRenderer, type InferableHandler, Patterns, type RouteMeta, RouteRegistry, type SSEEvent, type SSEHandler, type SSEMarker, type SchemaConfig, type ValidationError, type ValidationResult, base64urlDecode, base64urlEncode, createHandler, createHandlerWithExtra, createRequestValidator, createRouteRegistry, createSSEHandler, createValidator, empty, filterRoutes, getAllRoutes, getCookie, getHeader, getLocals, getRoute, getRouteRegistry, getValidatorCacheStats, goAwait, hasFormat, html, json, parseAndValidateRequest, parseBody, parseCookies, parseCookiesFast, parseHeaders, parseQuery, parseQueryFast, parseRequest, precompileSchemas, redirect, registerFormat, registerFormats, setLocals, simpleHandler, stream, text, validateAllSchemas, validateFast, validateRequest, validateSchema, validateSchemaOrThrow };
@@ -1,16 +1,16 @@
1
- import { c as text, i as json, n as html, o as redirect, r as init_response, s as stream, t as empty } from "../response-CSKW5hsS.mjs";
2
- import { a as getRoute, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, s as init_route_registry, t as RouteRegistry } from "../route-registry-AlkDgbcE.mjs";
3
- import { n as init_html_renderer, t as HtmlRenderer } from "../html-renderer-CJ3B2Hft.mjs";
4
- import { n as init_dependency_manager, t as DependencyManager } from "../dependency-manager-CPkwMI7J.mjs";
5
- import { a as parseCookies, d as parseQueryFast, l as parseHeaders, n as getHeader, o as parseCookiesFast, r as parseBody, t as getCookie, u as parseQuery } from "../parsers-ROIZWSGI.mjs";
6
- import { t as goAwait } from "../go-await-B-KP-K8x.mjs";
7
- import { a as validateAllSchemas, c as validateSchemaOrThrow, i as precompileSchemas, n as createValidator, o as validateFast, r as getValidatorCacheStats, s as validateSchema } from "../validators-CbCLj0Rc.mjs";
8
- import { n as createHandlerWithExtra, r as simpleHandler, t as createHandler } from "../create-handler-CbSoroA1.mjs";
9
- import { n as base64urlEncode, t as base64urlDecode } from "../base64url-DLDOeXsk.mjs";
10
- import { i as setLocals, n as getLocals } from "../handle-BhpqNgGf.mjs";
11
- import { i as validateRequest, n as parseAndValidateRequest, r as parseRequest, t as createRequestValidator } from "../request-validator-Dyqng-H_.mjs";
1
+ import { c as text, i as json, n as html, o as redirect, r as init_response, s as stream, t as empty } from "../response-DXg4i_yh.mjs";
2
+ import { a as getRoute, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, s as init_route_registry, t as RouteRegistry } from "../route-registry-mcTG0M-t.mjs";
3
+ import { n as init_html_renderer, t as HtmlRenderer } from "../html-renderer-CczE8mwC.mjs";
4
+ import { n as init_dependency_manager, t as DependencyManager } from "../dependency-manager-Czg7Po2j.mjs";
5
+ import { a as parseCookies, d as parseQueryFast, l as parseHeaders, n as getHeader, o as parseCookiesFast, r as parseBody, t as getCookie, u as parseQuery } from "../parsers-CI_TZ7pO.mjs";
6
+ import { t as goAwait } from "../go-await-BGAGJfrB.mjs";
7
+ import { a as validateAllSchemas, c as validateSchemaOrThrow, i as precompileSchemas, n as createValidator, o as validateFast, r as getValidatorCacheStats, s as validateSchema } from "../validators-BBrGePBr.mjs";
8
+ import { n as createHandlerWithExtra, r as simpleHandler, t as createHandler } from "../create-handler-B_pfxh3m.mjs";
9
+ import { n as base64urlEncode, t as base64urlDecode } from "../base64url-CwQnvZyp.mjs";
10
+ import { i as setLocals, n as getLocals } from "../handle-Csjtywdc.mjs";
11
+ import { i as validateRequest, n as parseAndValidateRequest, r as parseRequest, t as createRequestValidator } from "../request-validator-_J5HloRq.mjs";
12
12
  import { Patterns, hasFormat, registerFormat, registerFormats } from "./formats.mjs";
13
- import { t as createSSEHandler } from "../sse-US5D9mgE.mjs";
13
+ import { t as createSSEHandler } from "../sse-BT5yyLgX.mjs";
14
14
 
15
15
  //#region src/utils/index.ts
16
16
  init_response();
@@ -1,2 +1,2 @@
1
- import { a as parseBody, c as parseCookiesFast, d as parseHeaders, f as parseQuery, i as getHeader, l as parseFile, n as FormData, o as parseBodyAs, p as parseQueryFast, r as getCookie, s as parseCookies, t as FileInfo, u as parseFormData } from "../parsers-CodQFP1Z.mjs";
1
+ import { a as parseBody, c as parseCookiesFast, d as parseHeaders, f as parseQuery, i as getHeader, l as parseFile, n as FormData, o as parseBodyAs, p as parseQueryFast, r as getCookie, s as parseCookies, t as FileInfo, u as parseFormData } from "../parsers-7lvt3Oss.mjs";
2
2
  export { FileInfo, FormData, getCookie, getHeader, parseBody, parseBodyAs, parseCookies, parseCookiesFast, parseFile, parseFormData, parseHeaders, parseQuery, parseQueryFast };
@@ -1,3 +1,3 @@
1
- import { a as parseCookies, c as parseFormData, d as parseQueryFast, i as parseBodyAs, l as parseHeaders, n as getHeader, o as parseCookiesFast, r as parseBody, s as parseFile, t as getCookie, u as parseQuery } from "../parsers-ROIZWSGI.mjs";
1
+ import { a as parseCookies, c as parseFormData, d as parseQueryFast, i as parseBodyAs, l as parseHeaders, n as getHeader, o as parseCookiesFast, r as parseBody, s as parseFile, t as getCookie, u as parseQuery } from "../parsers-CI_TZ7pO.mjs";
2
2
 
3
3
  export { getCookie, getHeader, parseBody, parseBodyAs, parseCookies, parseCookiesFast, parseFile, parseFormData, parseHeaders, parseQuery, parseQueryFast };
@@ -1,4 +1,4 @@
1
- import { n as init_path_matcher, t as PathMatcher } from "../path-matcher-CXMJ-IrG.mjs";
1
+ import { n as init_path_matcher, t as PathMatcher } from "../path-matcher-73cJd5Y7.mjs";
2
2
 
3
3
  init_path_matcher();
4
4
  export { PathMatcher };
@@ -1,3 +1,3 @@
1
- import "../validators-C0eZyxPh.mjs";
2
- import { a as parseAndValidateRequest, i as createRequestValidator, n as ValidatedRequestData, o as parseRequest, r as ValidationResult, s as validateRequest, t as RequestData } from "../request-validator-u2Ccj3_x.mjs";
1
+ import "../validators-CPmnj_y9.mjs";
2
+ import { a as parseAndValidateRequest, i as createRequestValidator, n as ValidatedRequestData, o as parseRequest, r as ValidationResult, s as validateRequest, t as RequestData } from "../request-validator-42lY21gn.mjs";
3
3
  export { RequestData, ValidatedRequestData, ValidationResult, createRequestValidator, parseAndValidateRequest, parseRequest, validateRequest };
@@ -1,5 +1,5 @@
1
- import "../parsers-ROIZWSGI.mjs";
2
- import "../validators-CbCLj0Rc.mjs";
3
- import { i as validateRequest, n as parseAndValidateRequest, r as parseRequest, t as createRequestValidator } from "../request-validator-Dyqng-H_.mjs";
1
+ import "../parsers-CI_TZ7pO.mjs";
2
+ import "../validators-BBrGePBr.mjs";
3
+ import { i as validateRequest, n as parseAndValidateRequest, r as parseRequest, t as createRequestValidator } from "../request-validator-_J5HloRq.mjs";
4
4
 
5
5
  export { createRequestValidator, parseAndValidateRequest, parseRequest, validateRequest };
@@ -1,2 +1,2 @@
1
- import { a as redirect, i as mapResponse, n as html, o as stream, r as json, s as text, t as empty } from "../response-CUyV5FIm.mjs";
1
+ import { a as redirect, i as mapResponse, n as html, o as stream, r as json, s as text, t as empty } from "../response-A-sZZiJ7.mjs";
2
2
  export { empty, html, json, mapResponse, redirect, stream, text };
@@ -1,4 +1,4 @@
1
- import { a as mapResponse, c as text, i as json, n as html, o as redirect, r as init_response, s as stream, t as empty } from "../response-CSKW5hsS.mjs";
1
+ import { a as mapResponse, c as text, i as json, n as html, o as redirect, r as init_response, s as stream, t as empty } from "../response-DXg4i_yh.mjs";
2
2
 
3
3
  init_response();
4
4
  export { empty, html, json, mapResponse, redirect, stream, text };
@@ -1,4 +1,4 @@
1
- import "../schema-CVuttFSw.mjs";
2
- import "../index-DXJd7-2Z.mjs";
3
- import { a as getAllRoutes, c as setGlobalRegistry, i as filterRoutes, n as RouteRegistry, o as getRoute, r as createRouteRegistry, s as getRouteRegistry, t as RouteMeta } from "../route-registry-ykzRmaHB.mjs";
1
+ import "../schema-CPQudJpE.mjs";
2
+ import "../index-CzItj62a.mjs";
3
+ import { a as getAllRoutes, c as setGlobalRegistry, i as filterRoutes, n as RouteRegistry, o as getRoute, r as createRouteRegistry, s as getRouteRegistry, t as RouteMeta } from "../route-registry--tx1PNui.mjs";
4
4
  export { RouteMeta, RouteRegistry, createRouteRegistry, filterRoutes, getAllRoutes, getRoute, getRouteRegistry, setGlobalRegistry };
@@ -1,4 +1,4 @@
1
- import { a as getRoute, c as setGlobalRegistry, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, s as init_route_registry, t as RouteRegistry } from "../route-registry-AlkDgbcE.mjs";
1
+ import { a as getRoute, c as setGlobalRegistry, i as getAllRoutes, n as createRouteRegistry, o as getRouteRegistry, r as filterRoutes, s as init_route_registry, t as RouteRegistry } from "../route-registry-mcTG0M-t.mjs";
2
2
 
3
3
  init_route_registry();
4
4
  export { RouteRegistry, createRouteRegistry, filterRoutes, getAllRoutes, getRoute, getRouteRegistry, setGlobalRegistry };
@@ -1,3 +1,3 @@
1
- import "../schema-CVuttFSw.mjs";
2
- import { a as createSSEHandler, i as SSEMarker, n as SSEGenerator, r as SSEHandler, t as SSEEvent } from "../sse-BOd2pvUK.mjs";
1
+ import "../schema-CPQudJpE.mjs";
2
+ import { a as createSSEHandler, i as SSEMarker, n as SSEGenerator, r as SSEHandler, t as SSEEvent } from "../sse-BMM6KTfy.mjs";
3
3
  export { SSEEvent, SSEGenerator, SSEHandler, SSEMarker, createSSEHandler };
@@ -1,5 +1,5 @@
1
- import "../parsers-ROIZWSGI.mjs";
2
- import "../validators-CbCLj0Rc.mjs";
3
- import { t as createSSEHandler } from "../sse-US5D9mgE.mjs";
1
+ import "../parsers-CI_TZ7pO.mjs";
2
+ import "../validators-BBrGePBr.mjs";
3
+ import { t as createSSEHandler } from "../sse-BT5yyLgX.mjs";
4
4
 
5
5
  export { createSSEHandler };
@@ -1,2 +1,2 @@
1
- import { a as ValidationError, c as getValidatorCacheStats, d as validateFast, f as validateSchema, i as Type, l as precompileSchemas, n as Static, o as ValidationResult, p as validateSchemaOrThrow, r as TSchema, s as createValidator, t as SchemaConfig, u as validateAllSchemas } from "../../validators-C0eZyxPh.mjs";
1
+ import { a as ValidationError, c as getValidatorCacheStats, d as validateFast, f as validateSchema, i as Type, l as precompileSchemas, n as Static, o as ValidationResult, p as validateSchemaOrThrow, r as TSchema, s as createValidator, t as SchemaConfig, u as validateAllSchemas } from "../../validators-CPmnj_y9.mjs";
2
2
  export { SchemaConfig, Static, TSchema, Type, ValidationError, ValidationResult, createValidator, getValidatorCacheStats, precompileSchemas, validateAllSchemas, validateFast, validateSchema, validateSchemaOrThrow };
@@ -1,3 +1,3 @@
1
- import { a as validateAllSchemas, c as validateSchemaOrThrow, i as precompileSchemas, n as createValidator, o as validateFast, r as getValidatorCacheStats, s as validateSchema, t as Type } from "../../validators-CbCLj0Rc.mjs";
1
+ import { a as validateAllSchemas, c as validateSchemaOrThrow, i as precompileSchemas, n as createValidator, o as validateFast, r as getValidatorCacheStats, s as validateSchema, t as Type } from "../../validators-BBrGePBr.mjs";
2
2
 
3
3
  export { Type, createValidator, getValidatorCacheStats, precompileSchemas, validateAllSchemas, validateFast, validateSchema, validateSchemaOrThrow };
@@ -109,4 +109,4 @@ function getValidatorCacheStats() {
109
109
 
110
110
  //#endregion
111
111
  export { validateAllSchemas as a, validateSchemaOrThrow as c, precompileSchemas as i, createValidator as n, validateFast as o, getValidatorCacheStats as r, validateSchema as s, Type as t };
112
- //# sourceMappingURL=validators-CbCLj0Rc.mjs.map
112
+ //# sourceMappingURL=validators-BBrGePBr.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators-CbCLj0Rc.mjs","names":[],"sources":["../src/utils/validators/validators.ts"],"sourcesContent":["/**\n * Schema 验证器 - 简洁版\n *\n * 特点:\n * - WeakMap 缓存避免内存泄漏\n * - TypeCompiler JIT 编译,性能最佳\n * - 支持 FormatRegistry(需确保同一实例)\n *\n * @version 7.0.0\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\nimport { TypeCompiler, type TypeCheck } from \"@sinclair/typebox/compiler\";\nimport { Value } from \"@sinclair/typebox/value\";\n\n// ============== 类型定义 ==============\n\n/** Schema 配置接口 */\nexport interface SchemaConfig {\n body?: TSchema;\n query?: TSchema;\n params?: TSchema;\n headers?: TSchema;\n cookies?: TSchema;\n}\n\n/** 验证错误接口 */\nexport interface ValidationError {\n path: string;\n message: string;\n code: string;\n value?: unknown;\n}\n\n/** 验证结果 */\nexport type ValidationResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; errors: ValidationError[] };\n\n// ============== 缓存 ==============\n\n/** 编译器缓存 - WeakMap 避免内存泄漏 */\nconst compilerCache = new WeakMap<TSchema, TypeCheck<TSchema>>();\n\n// ============== 核心函数 ==============\n\n/**\n * 获取或创建编译后的验证器\n */\nfunction getCompiledValidator<T extends TSchema>(schema: T): TypeCheck<T> {\n let compiler = compilerCache.get(schema);\n if (!compiler) {\n compiler = TypeCompiler.Compile(schema);\n compilerCache.set(schema, compiler);\n }\n return compiler as TypeCheck<T>;\n}\n\n/**\n * 验证单个 Schema(返回结果对象)\n */\nexport function validateSchema<T extends TSchema>(\n schema: T,\n data: unknown,\n): ValidationResult<Static<T>> {\n try {\n const compiler = getCompiledValidator(schema);\n\n if (compiler.Check(data)) {\n return { success: true, data: data as Static<T> };\n }\n\n // 收集错误\n const errors: ValidationError[] = [];\n for (const error of compiler.Errors(data)) {\n errors.push({\n path: error.path,\n message: error.message,\n code: \"VALIDATION_FAILED\",\n value: error.value,\n });\n }\n return { success: false, errors };\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n path: \"\",\n message: error instanceof Error ? error.message : \"验证异常\",\n code: \"VALIDATION_EXCEPTION\",\n },\n ],\n };\n }\n}\n\n/**\n * 验证 Schema(抛出异常版本,用于框架内部)\n */\nexport function validateSchemaOrThrow<T extends TSchema>(\n schema: T,\n data: unknown,\n context: string,\n): Static<T> {\n const compiler = getCompiledValidator(schema);\n\n if (!compiler.Check(data)) {\n throw new Error(`${context}验证失败`);\n }\n\n return data as Static<T>;\n}\n\n/**\n * 快速验证(只返回布尔值)\n */\nexport function validateFast<T extends TSchema>(\n schema: T,\n data: unknown,\n): data is Static<T> {\n const compiler = getCompiledValidator(schema);\n return compiler.Check(data);\n}\n\n/**\n * 批量验证所有 Schema(用于请求验证)\n */\nexport function validateAllSchemas(\n config: SchemaConfig,\n data: {\n body: unknown;\n query: unknown;\n params: unknown;\n headers: unknown;\n cookies: unknown;\n },\n): typeof data {\n if (config.body) {\n validateSchemaOrThrow(config.body, data.body, \"请求体\");\n }\n if (config.query) {\n validateSchemaOrThrow(config.query, data.query, \"Query参数\");\n }\n if (config.params) {\n validateSchemaOrThrow(config.params, data.params, \"路径参数\");\n }\n if (config.headers) {\n validateSchemaOrThrow(config.headers, data.headers, \"请求头\");\n }\n if (config.cookies) {\n validateSchemaOrThrow(config.cookies, data.cookies, \"Cookie\");\n }\n return data;\n}\n\n/**\n * 预编译 Schema(启动时调用,避免首次请求开销)\n */\nexport function precompileSchemas(config: SchemaConfig): void {\n if (config.body) getCompiledValidator(config.body);\n if (config.query) getCompiledValidator(config.query);\n if (config.params) getCompiledValidator(config.params);\n if (config.headers) getCompiledValidator(config.headers);\n if (config.cookies) getCompiledValidator(config.cookies);\n}\n\n/**\n * 创建类型特化的验证器(高频使用场景)\n */\nexport function createValidator<T extends TSchema>(\n schema: T,\n): (data: unknown) => ValidationResult<Static<T>> {\n return (data: unknown) => validateSchema(schema, data);\n}\n\n/**\n * 获取缓存统计(调试用)\n */\nexport function getValidatorCacheStats(): { cacheType: string; note: string } {\n return {\n cacheType: \"WeakMap\",\n note: \"WeakMap 缓存会随 Schema 对象自动清理,无内存泄漏风险\",\n };\n}\n\n// 导出 TypeBox 类型\nexport { Type, Static, TSchema };\n"],"mappings":";;;;;;;;;;;;;;;AA2CA,MAAM,gCAAgB,IAAI,SAAsC;;;;AAOhE,SAAS,qBAAwC,QAAyB;CACxE,IAAI,WAAW,cAAc,IAAI,OAAO;AACxC,KAAI,CAAC,UAAU;AACb,aAAW,aAAa,QAAQ,OAAO;AACvC,gBAAc,IAAI,QAAQ,SAAS;;AAErC,QAAO;;;;;AAMT,SAAgB,eACd,QACA,MAC6B;AAC7B,KAAI;EACF,MAAM,WAAW,qBAAqB,OAAO;AAE7C,MAAI,SAAS,MAAM,KAAK,CACtB,QAAO;GAAE,SAAS;GAAY;GAAmB;EAInD,MAAM,SAA4B,EAAE;AACpC,OAAK,MAAM,SAAS,SAAS,OAAO,KAAK,CACvC,QAAO,KAAK;GACV,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,MAAM;GACN,OAAO,MAAM;GACd,CAAC;AAEJ,SAAO;GAAE,SAAS;GAAO;GAAQ;UAC1B,OAAO;AACd,SAAO;GACL,SAAS;GACT,QAAQ,CACN;IACE,MAAM;IACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IAClD,MAAM;IACP,CACF;GACF;;;;;;AAOL,SAAgB,sBACd,QACA,MACA,SACW;AAGX,KAAI,CAFa,qBAAqB,OAAO,CAE/B,MAAM,KAAK,CACvB,OAAM,IAAI,MAAM,GAAG,QAAQ,MAAM;AAGnC,QAAO;;;;;AAMT,SAAgB,aACd,QACA,MACmB;AAEnB,QADiB,qBAAqB,OAAO,CAC7B,MAAM,KAAK;;;;;AAM7B,SAAgB,mBACd,QACA,MAOa;AACb,KAAI,OAAO,KACT,uBAAsB,OAAO,MAAM,KAAK,MAAM,MAAM;AAEtD,KAAI,OAAO,MACT,uBAAsB,OAAO,OAAO,KAAK,OAAO,UAAU;AAE5D,KAAI,OAAO,OACT,uBAAsB,OAAO,QAAQ,KAAK,QAAQ,OAAO;AAE3D,KAAI,OAAO,QACT,uBAAsB,OAAO,SAAS,KAAK,SAAS,MAAM;AAE5D,KAAI,OAAO,QACT,uBAAsB,OAAO,SAAS,KAAK,SAAS,SAAS;AAE/D,QAAO;;;;;AAMT,SAAgB,kBAAkB,QAA4B;AAC5D,KAAI,OAAO,KAAM,sBAAqB,OAAO,KAAK;AAClD,KAAI,OAAO,MAAO,sBAAqB,OAAO,MAAM;AACpD,KAAI,OAAO,OAAQ,sBAAqB,OAAO,OAAO;AACtD,KAAI,OAAO,QAAS,sBAAqB,OAAO,QAAQ;AACxD,KAAI,OAAO,QAAS,sBAAqB,OAAO,QAAQ;;;;;AAM1D,SAAgB,gBACd,QACgD;AAChD,SAAQ,SAAkB,eAAe,QAAQ,KAAK;;;;;AAMxD,SAAgB,yBAA8D;AAC5E,QAAO;EACL,WAAW;EACX,MAAM;EACP"}
1
+ {"version":3,"file":"validators-BBrGePBr.mjs","names":[],"sources":["../src/utils/validators/validators.ts"],"sourcesContent":["/**\n * Schema 验证器 - 简洁版\n *\n * 特点:\n * - WeakMap 缓存避免内存泄漏\n * - TypeCompiler JIT 编译,性能最佳\n * - 支持 FormatRegistry(需确保同一实例)\n *\n * @version 7.0.0\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\nimport { TypeCompiler, type TypeCheck } from \"@sinclair/typebox/compiler\";\nimport { Value } from \"@sinclair/typebox/value\";\n\n// ============== 类型定义 ==============\n\n/** Schema 配置接口 */\nexport interface SchemaConfig {\n body?: TSchema;\n query?: TSchema;\n params?: TSchema;\n headers?: TSchema;\n cookies?: TSchema;\n}\n\n/** 验证错误接口 */\nexport interface ValidationError {\n path: string;\n message: string;\n code: string;\n value?: unknown;\n}\n\n/** 验证结果 */\nexport type ValidationResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; errors: ValidationError[] };\n\n// ============== 缓存 ==============\n\n/** 编译器缓存 - WeakMap 避免内存泄漏 */\nconst compilerCache = new WeakMap<TSchema, TypeCheck<TSchema>>();\n\n// ============== 核心函数 ==============\n\n/**\n * 获取或创建编译后的验证器\n */\nfunction getCompiledValidator<T extends TSchema>(schema: T): TypeCheck<T> {\n let compiler = compilerCache.get(schema);\n if (!compiler) {\n compiler = TypeCompiler.Compile(schema);\n compilerCache.set(schema, compiler);\n }\n return compiler as TypeCheck<T>;\n}\n\n/**\n * 验证单个 Schema(返回结果对象)\n */\nexport function validateSchema<T extends TSchema>(\n schema: T,\n data: unknown,\n): ValidationResult<Static<T>> {\n try {\n const compiler = getCompiledValidator(schema);\n\n if (compiler.Check(data)) {\n return { success: true, data: data as Static<T> };\n }\n\n // 收集错误\n const errors: ValidationError[] = [];\n for (const error of compiler.Errors(data)) {\n errors.push({\n path: error.path,\n message: error.message,\n code: \"VALIDATION_FAILED\",\n value: error.value,\n });\n }\n return { success: false, errors };\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n path: \"\",\n message: error instanceof Error ? error.message : \"验证异常\",\n code: \"VALIDATION_EXCEPTION\",\n },\n ],\n };\n }\n}\n\n/**\n * 验证 Schema(抛出异常版本,用于框架内部)\n */\nexport function validateSchemaOrThrow<T extends TSchema>(\n schema: T,\n data: unknown,\n context: string,\n): Static<T> {\n const compiler = getCompiledValidator(schema);\n\n if (!compiler.Check(data)) {\n throw new Error(`${context}验证失败`);\n }\n\n return data as Static<T>;\n}\n\n/**\n * 快速验证(只返回布尔值)\n */\nexport function validateFast<T extends TSchema>(\n schema: T,\n data: unknown,\n): data is Static<T> {\n const compiler = getCompiledValidator(schema);\n return compiler.Check(data);\n}\n\n/**\n * 批量验证所有 Schema(用于请求验证)\n */\nexport function validateAllSchemas(\n config: SchemaConfig,\n data: {\n body: unknown;\n query: unknown;\n params: unknown;\n headers: unknown;\n cookies: unknown;\n },\n): typeof data {\n if (config.body) {\n validateSchemaOrThrow(config.body, data.body, \"请求体\");\n }\n if (config.query) {\n validateSchemaOrThrow(config.query, data.query, \"Query参数\");\n }\n if (config.params) {\n validateSchemaOrThrow(config.params, data.params, \"路径参数\");\n }\n if (config.headers) {\n validateSchemaOrThrow(config.headers, data.headers, \"请求头\");\n }\n if (config.cookies) {\n validateSchemaOrThrow(config.cookies, data.cookies, \"Cookie\");\n }\n return data;\n}\n\n/**\n * 预编译 Schema(启动时调用,避免首次请求开销)\n */\nexport function precompileSchemas(config: SchemaConfig): void {\n if (config.body) getCompiledValidator(config.body);\n if (config.query) getCompiledValidator(config.query);\n if (config.params) getCompiledValidator(config.params);\n if (config.headers) getCompiledValidator(config.headers);\n if (config.cookies) getCompiledValidator(config.cookies);\n}\n\n/**\n * 创建类型特化的验证器(高频使用场景)\n */\nexport function createValidator<T extends TSchema>(\n schema: T,\n): (data: unknown) => ValidationResult<Static<T>> {\n return (data: unknown) => validateSchema(schema, data);\n}\n\n/**\n * 获取缓存统计(调试用)\n */\nexport function getValidatorCacheStats(): { cacheType: string; note: string } {\n return {\n cacheType: \"WeakMap\",\n note: \"WeakMap 缓存会随 Schema 对象自动清理,无内存泄漏风险\",\n };\n}\n\n// 导出 TypeBox 类型\nexport { Type, Static, TSchema };\n"],"mappings":";;;;;;;;;;;;;;;AA2CA,MAAM,gCAAgB,IAAI,SAAsC;;;;AAOhE,SAAS,qBAAwC,QAAyB;CACxE,IAAI,WAAW,cAAc,IAAI,OAAO;AACxC,KAAI,CAAC,UAAU;AACb,aAAW,aAAa,QAAQ,OAAO;AACvC,gBAAc,IAAI,QAAQ,SAAS;;AAErC,QAAO;;;;;AAMT,SAAgB,eACd,QACA,MAC6B;AAC7B,KAAI;EACF,MAAM,WAAW,qBAAqB,OAAO;AAE7C,MAAI,SAAS,MAAM,KAAK,CACtB,QAAO;GAAE,SAAS;GAAY;GAAmB;EAInD,MAAM,SAA4B,EAAE;AACpC,OAAK,MAAM,SAAS,SAAS,OAAO,KAAK,CACvC,QAAO,KAAK;GACV,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,MAAM;GACN,OAAO,MAAM;GACd,CAAC;AAEJ,SAAO;GAAE,SAAS;GAAO;GAAQ;UAC1B,OAAO;AACd,SAAO;GACL,SAAS;GACT,QAAQ,CACN;IACE,MAAM;IACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IAClD,MAAM;IACP,CACF;GACF;;;;;;AAOL,SAAgB,sBACd,QACA,MACA,SACW;AAGX,KAAI,CAFa,qBAAqB,OAAO,CAE/B,MAAM,KAAK,CACvB,OAAM,IAAI,MAAM,GAAG,QAAQ,MAAM;AAGnC,QAAO;;;;;AAMT,SAAgB,aACd,QACA,MACmB;AAEnB,QADiB,qBAAqB,OAAO,CAC7B,MAAM,KAAK;;;;;AAM7B,SAAgB,mBACd,QACA,MAOa;AACb,KAAI,OAAO,KACT,uBAAsB,OAAO,MAAM,KAAK,MAAM,MAAM;AAEtD,KAAI,OAAO,MACT,uBAAsB,OAAO,OAAO,KAAK,OAAO,UAAU;AAE5D,KAAI,OAAO,OACT,uBAAsB,OAAO,QAAQ,KAAK,QAAQ,OAAO;AAE3D,KAAI,OAAO,QACT,uBAAsB,OAAO,SAAS,KAAK,SAAS,MAAM;AAE5D,KAAI,OAAO,QACT,uBAAsB,OAAO,SAAS,KAAK,SAAS,SAAS;AAE/D,QAAO;;;;;AAMT,SAAgB,kBAAkB,QAA4B;AAC5D,KAAI,OAAO,KAAM,sBAAqB,OAAO,KAAK;AAClD,KAAI,OAAO,MAAO,sBAAqB,OAAO,MAAM;AACpD,KAAI,OAAO,OAAQ,sBAAqB,OAAO,OAAO;AACtD,KAAI,OAAO,QAAS,sBAAqB,OAAO,QAAQ;AACxD,KAAI,OAAO,QAAS,sBAAqB,OAAO,QAAQ;;;;;AAM1D,SAAgB,gBACd,QACgD;AAChD,SAAQ,SAAkB,eAAe,QAAQ,KAAK;;;;;AAMxD,SAAgB,yBAA8D;AAC5E,QAAO;EACL,WAAW;EACX,MAAM;EACP"}
@@ -64,4 +64,4 @@ declare function getValidatorCacheStats(): {
64
64
  };
65
65
  //#endregion
66
66
  export { ValidationError as a, getValidatorCacheStats as c, validateFast as d, validateSchema as f, Type as i, precompileSchemas as l, Static$1 as n, ValidationResult as o, validateSchemaOrThrow as p, TSchema$1 as r, createValidator as s, SchemaConfig as t, validateAllSchemas as u };
67
- //# sourceMappingURL=validators-C0eZyxPh.d.mts.map
67
+ //# sourceMappingURL=validators-CPmnj_y9.d.mts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vafast",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "极简结构化Web框架,支持 Bun 和 Node.js。Go风格,函数优先。",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,44 +0,0 @@
1
- //#region src/auth/token.d.ts
2
- interface TokenPayload {
3
- [key: string]: any;
4
- exp?: number;
5
- iat?: number;
6
- sub?: string;
7
- aud?: string;
8
- iss?: string;
9
- }
10
- interface TokenResult {
11
- payload: TokenPayload;
12
- token: string;
13
- expiresAt: number;
14
- }
15
- interface TokenOptions {
16
- expiresIn?: number;
17
- issuer?: string;
18
- audience?: string;
19
- subject?: string;
20
- }
21
- declare class TokenError extends Error {
22
- code: "INVALID_TOKEN" | "EXPIRED_TOKEN" | "INVALID_SIGNATURE" | "MALFORMED_TOKEN" | "INVALID_PAYLOAD";
23
- constructor(message: string, code: "INVALID_TOKEN" | "EXPIRED_TOKEN" | "INVALID_SIGNATURE" | "MALFORMED_TOKEN" | "INVALID_PAYLOAD");
24
- }
25
- /** 生成令牌 */
26
- declare function generateToken(payload: TokenPayload, secret: string, options?: TokenOptions): Promise<TokenResult>;
27
- /** 验证令牌 */
28
- declare function verifyToken(token: string, secret: string): Promise<TokenPayload | null>;
29
- /** 解析令牌(不验证签名) */
30
- declare function parseToken(token: string): TokenPayload | null;
31
- /** 检查令牌是否过期 */
32
- declare function isTokenExpired(token: string): boolean;
33
- /** 获取令牌剩余有效时间(秒) */
34
- declare function getTokenTimeRemaining(token: string): number;
35
- /** 刷新令牌 */
36
- declare function refreshToken(token: string, secret: string, options?: TokenOptions): Promise<TokenResult | null>;
37
- /** 创建访问令牌和刷新令牌对 */
38
- declare function createTokenPair(payload: TokenPayload, secret: string, options?: TokenOptions): Promise<{
39
- accessToken: TokenResult;
40
- refreshToken: TokenResult;
41
- }>;
42
- //#endregion
43
- export { TokenError, TokenOptions, TokenPayload, TokenResult, createTokenPair, generateToken, getTokenTimeRemaining, isTokenExpired, parseToken, refreshToken, verifyToken };
44
- //# sourceMappingURL=token.d.mts.map
@@ -1,105 +0,0 @@
1
- import { n as base64urlEncode, t as base64urlDecode } from "../base64url-DLDOeXsk.mjs";
2
-
3
- //#region src/auth/token.ts
4
- var TokenError = class extends Error {
5
- constructor(message, code) {
6
- super(message);
7
- this.code = code;
8
- this.name = "TokenError";
9
- }
10
- };
11
- const encoder = new TextEncoder();
12
- /** 使用 HMAC-SHA256 进行签名 */
13
- async function sign(data, secret) {
14
- const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
15
- name: "HMAC",
16
- hash: "SHA-256"
17
- }, false, ["sign"]);
18
- const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
19
- return btoa(String.fromCharCode.apply(null, Array.from(new Uint8Array(signature))));
20
- }
21
- /** 生成令牌 */
22
- async function generateToken(payload, secret, options = {}) {
23
- const { expiresIn = 3600, issuer, audience, subject } = options;
24
- const now = Math.floor(Date.now() / 1e3);
25
- const tokenPayload = {
26
- ...payload,
27
- iat: now,
28
- exp: now + expiresIn
29
- };
30
- if (issuer) tokenPayload.iss = issuer;
31
- if (audience) tokenPayload.aud = audience;
32
- if (subject) tokenPayload.sub = subject;
33
- const data = base64urlEncode(JSON.stringify(tokenPayload));
34
- return {
35
- payload: tokenPayload,
36
- token: `${data}.${base64urlEncode(await sign(data, secret))}`,
37
- expiresAt: tokenPayload.exp * 1e3
38
- };
39
- }
40
- /** 验证令牌 */
41
- async function verifyToken(token, secret) {
42
- try {
43
- const [data, sig] = token.split(".");
44
- if (!data || !sig) throw new TokenError("令牌格式无效", "MALFORMED_TOKEN");
45
- if (sig !== base64urlEncode(await sign(data, secret))) throw new TokenError("令牌签名无效", "INVALID_SIGNATURE");
46
- const payload = JSON.parse(base64urlDecode(data));
47
- if (payload.exp && Date.now() / 1e3 > payload.exp) throw new TokenError("令牌已过期", "EXPIRED_TOKEN");
48
- return payload;
49
- } catch (error) {
50
- if (error instanceof TokenError) throw error;
51
- throw new TokenError("令牌验证失败", "INVALID_TOKEN");
52
- }
53
- }
54
- /** 解析令牌(不验证签名) */
55
- function parseToken(token) {
56
- try {
57
- const [data] = token.split(".");
58
- if (!data) return null;
59
- return JSON.parse(base64urlDecode(data));
60
- } catch {
61
- return null;
62
- }
63
- }
64
- /** 检查令牌是否过期 */
65
- function isTokenExpired(token) {
66
- const payload = parseToken(token);
67
- if (!payload || !payload.exp) return true;
68
- return Date.now() / 1e3 > payload.exp;
69
- }
70
- /** 获取令牌剩余有效时间(秒) */
71
- function getTokenTimeRemaining(token) {
72
- const payload = parseToken(token);
73
- if (!payload || !payload.exp) return 0;
74
- const remaining = payload.exp - Date.now() / 1e3;
75
- return Math.max(0, Math.floor(remaining));
76
- }
77
- /** 刷新令牌 */
78
- async function refreshToken(token, secret, options = {}) {
79
- try {
80
- const payload = await verifyToken(token, secret);
81
- if (!payload) return null;
82
- const { exp, iat, ...cleanPayload } = payload;
83
- await new Promise((resolve) => setTimeout(resolve, 10));
84
- return await generateToken(cleanPayload, secret, options);
85
- } catch {
86
- return null;
87
- }
88
- }
89
- /** 创建访问令牌和刷新令牌对 */
90
- async function createTokenPair(payload, secret, options = {}) {
91
- return {
92
- accessToken: await generateToken(payload, secret, {
93
- ...options,
94
- expiresIn: options.expiresIn || 3600
95
- }),
96
- refreshToken: await generateToken(payload, secret, {
97
- ...options,
98
- expiresIn: 168 * 3600
99
- })
100
- };
101
- }
102
-
103
- //#endregion
104
- export { TokenError, createTokenPair, generateToken, getTokenTimeRemaining, isTokenExpired, parseToken, refreshToken, verifyToken };
105
- //# sourceMappingURL=token.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token.mjs","names":[],"sources":["../../src/auth/token.ts"],"sourcesContent":["// src/auth/token.ts\nimport { base64urlEncode, base64urlDecode } from \"../utils/base64url\";\n\n// 类型定义\nexport interface TokenPayload {\n [key: string]: any;\n exp?: number; // 过期时间戳\n iat?: number; // 签发时间戳\n sub?: string; // 主题(通常是用户ID)\n aud?: string; // 受众\n iss?: string; // 签发者\n}\n\nexport interface TokenResult {\n payload: TokenPayload;\n token: string;\n expiresAt: number;\n}\n\nexport interface TokenOptions {\n expiresIn?: number; // 过期时间(秒)\n issuer?: string; // 签发者\n audience?: string; // 受众\n subject?: string; // 主题\n}\n\nexport class TokenError extends Error {\n constructor(\n message: string,\n public code:\n | \"INVALID_TOKEN\"\n | \"EXPIRED_TOKEN\"\n | \"INVALID_SIGNATURE\"\n | \"MALFORMED_TOKEN\"\n | \"INVALID_PAYLOAD\",\n ) {\n super(message);\n this.name = \"TokenError\";\n }\n}\n\nconst encoder = new TextEncoder();\n\n/** 使用 HMAC-SHA256 进行签名 */\nasync function sign(data: string, secret: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const signature = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(data));\n return btoa(\n String.fromCharCode.apply(null, Array.from(new Uint8Array(signature))),\n );\n}\n\n/** 生成令牌 */\nexport async function generateToken(\n payload: TokenPayload,\n secret: string,\n options: TokenOptions = {},\n): Promise<TokenResult> {\n const { expiresIn = 3600, issuer, audience, subject } = options;\n\n // 创建令牌载荷,强制使用当前时间\n const now = Math.floor(Date.now() / 1000);\n const tokenPayload: TokenPayload = {\n ...payload,\n iat: now,\n exp: now + expiresIn,\n };\n\n // 添加可选字段\n if (issuer) tokenPayload.iss = issuer;\n if (audience) tokenPayload.aud = audience;\n if (subject) tokenPayload.sub = subject;\n\n const data = base64urlEncode(JSON.stringify(tokenPayload));\n const sig = await sign(data, secret);\n const token = `${data}.${base64urlEncode(sig)}`;\n\n return {\n payload: tokenPayload,\n token,\n expiresAt: tokenPayload.exp! * 1000, // 转换为毫秒\n };\n}\n\n/** 验证令牌 */\nexport async function verifyToken(\n token: string,\n secret: string,\n): Promise<TokenPayload | null> {\n try {\n const [data, sig] = token.split(\".\");\n if (!data || !sig) {\n throw new TokenError(\"令牌格式无效\", \"MALFORMED_TOKEN\");\n }\n\n const expectedSig = await sign(data, secret);\n const expected = base64urlEncode(expectedSig);\n\n if (sig !== expected) {\n throw new TokenError(\"令牌签名无效\", \"INVALID_SIGNATURE\");\n }\n\n const payload = JSON.parse(base64urlDecode(data)) as TokenPayload;\n\n // 检查过期时间\n if (payload.exp && Date.now() / 1000 > payload.exp) {\n throw new TokenError(\"令牌已过期\", \"EXPIRED_TOKEN\");\n }\n\n return payload;\n } catch (error) {\n if (error instanceof TokenError) {\n throw error;\n }\n throw new TokenError(\"令牌验证失败\", \"INVALID_TOKEN\");\n }\n}\n\n/** 解析令牌(不验证签名) */\nexport function parseToken(token: string): TokenPayload | null {\n try {\n const [data] = token.split(\".\");\n if (!data) return null;\n\n return JSON.parse(base64urlDecode(data));\n } catch {\n return null;\n }\n}\n\n/** 检查令牌是否过期 */\nexport function isTokenExpired(token: string): boolean {\n const payload = parseToken(token);\n if (!payload || !payload.exp) return true;\n\n return Date.now() / 1000 > payload.exp;\n}\n\n/** 获取令牌剩余有效时间(秒) */\nexport function getTokenTimeRemaining(token: string): number {\n const payload = parseToken(token);\n if (!payload || !payload.exp) return 0;\n\n const remaining = payload.exp - Date.now() / 1000;\n return Math.max(0, Math.floor(remaining));\n}\n\n/** 刷新令牌 */\nexport async function refreshToken(\n token: string,\n secret: string,\n options: TokenOptions = {},\n): Promise<TokenResult | null> {\n try {\n const payload = await verifyToken(token, secret);\n if (!payload) return null;\n\n // 移除时间相关字段,重新生成\n const { exp, iat, ...cleanPayload } = payload;\n\n // 添加延迟确保时间戳不同\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n return await generateToken(cleanPayload, secret, options);\n } catch {\n return null;\n }\n}\n\n/** 创建访问令牌和刷新令牌对 */\nexport async function createTokenPair(\n payload: TokenPayload,\n secret: string,\n options: TokenOptions = {},\n): Promise<{\n accessToken: TokenResult;\n refreshToken: TokenResult;\n}> {\n const accessToken = await generateToken(payload, secret, {\n ...options,\n expiresIn: options.expiresIn || 3600, // 1小时\n });\n\n const refreshToken = await generateToken(payload, secret, {\n ...options,\n expiresIn: 7 * 24 * 3600, // 7天\n });\n\n return { accessToken, refreshToken };\n}\n"],"mappings":";;;AA0BA,IAAa,aAAb,cAAgC,MAAM;CACpC,YACE,SACA,AAAO,MAMP;AACA,QAAM,QAAQ;EAPP;AAQP,OAAK,OAAO;;;AAIhB,MAAM,UAAU,IAAI,aAAa;;AAGjC,eAAe,KAAK,MAAc,QAAiC;CACjE,MAAM,MAAM,MAAM,OAAO,OAAO,UAC9B,OACA,QAAQ,OAAO,OAAO,EACtB;EAAE,MAAM;EAAQ,MAAM;EAAW,EACjC,OACA,CAAC,OAAO,CACT;CAED,MAAM,YAAY,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,KAAK,CAAC;AAC7E,QAAO,KACL,OAAO,aAAa,MAAM,MAAM,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC,CAAC,CACvE;;;AAIH,eAAsB,cACpB,SACA,QACA,UAAwB,EAAE,EACJ;CACtB,MAAM,EAAE,YAAY,MAAM,QAAQ,UAAU,YAAY;CAGxD,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CACzC,MAAM,eAA6B;EACjC,GAAG;EACH,KAAK;EACL,KAAK,MAAM;EACZ;AAGD,KAAI,OAAQ,cAAa,MAAM;AAC/B,KAAI,SAAU,cAAa,MAAM;AACjC,KAAI,QAAS,cAAa,MAAM;CAEhC,MAAM,OAAO,gBAAgB,KAAK,UAAU,aAAa,CAAC;AAI1D,QAAO;EACL,SAAS;EACT,OAJY,GAAG,KAAK,GAAG,gBADb,MAAM,KAAK,MAAM,OAAO,CACS;EAK3C,WAAW,aAAa,MAAO;EAChC;;;AAIH,eAAsB,YACpB,OACA,QAC8B;AAC9B,KAAI;EACF,MAAM,CAAC,MAAM,OAAO,MAAM,MAAM,IAAI;AACpC,MAAI,CAAC,QAAQ,CAAC,IACZ,OAAM,IAAI,WAAW,UAAU,kBAAkB;AAMnD,MAAI,QAFa,gBADG,MAAM,KAAK,MAAM,OAAO,CACC,CAG3C,OAAM,IAAI,WAAW,UAAU,oBAAoB;EAGrD,MAAM,UAAU,KAAK,MAAM,gBAAgB,KAAK,CAAC;AAGjD,MAAI,QAAQ,OAAO,KAAK,KAAK,GAAG,MAAO,QAAQ,IAC7C,OAAM,IAAI,WAAW,SAAS,gBAAgB;AAGhD,SAAO;UACA,OAAO;AACd,MAAI,iBAAiB,WACnB,OAAM;AAER,QAAM,IAAI,WAAW,UAAU,gBAAgB;;;;AAKnD,SAAgB,WAAW,OAAoC;AAC7D,KAAI;EACF,MAAM,CAAC,QAAQ,MAAM,MAAM,IAAI;AAC/B,MAAI,CAAC,KAAM,QAAO;AAElB,SAAO,KAAK,MAAM,gBAAgB,KAAK,CAAC;SAClC;AACN,SAAO;;;;AAKX,SAAgB,eAAe,OAAwB;CACrD,MAAM,UAAU,WAAW,MAAM;AACjC,KAAI,CAAC,WAAW,CAAC,QAAQ,IAAK,QAAO;AAErC,QAAO,KAAK,KAAK,GAAG,MAAO,QAAQ;;;AAIrC,SAAgB,sBAAsB,OAAuB;CAC3D,MAAM,UAAU,WAAW,MAAM;AACjC,KAAI,CAAC,WAAW,CAAC,QAAQ,IAAK,QAAO;CAErC,MAAM,YAAY,QAAQ,MAAM,KAAK,KAAK,GAAG;AAC7C,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,CAAC;;;AAI3C,eAAsB,aACpB,OACA,QACA,UAAwB,EAAE,EACG;AAC7B,KAAI;EACF,MAAM,UAAU,MAAM,YAAY,OAAO,OAAO;AAChD,MAAI,CAAC,QAAS,QAAO;EAGrB,MAAM,EAAE,KAAK,KAAK,GAAG,iBAAiB;AAGtC,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;AAEvD,SAAO,MAAM,cAAc,cAAc,QAAQ,QAAQ;SACnD;AACN,SAAO;;;;AAKX,eAAsB,gBACpB,SACA,QACA,UAAwB,EAAE,EAIzB;AAWD,QAAO;EAAE,aAVW,MAAM,cAAc,SAAS,QAAQ;GACvD,GAAG;GACH,WAAW,QAAQ,aAAa;GACjC,CAAC;EAOoB,cALD,MAAM,cAAc,SAAS,QAAQ;GACxD,GAAG;GACH,WAAW,MAAS;GACrB,CAAC;EAEkC"}