vafast 0.6.2 → 0.7.0

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 (78) hide show
  1. package/README.md +13 -19
  2. package/dist/{base-server-D7ny0Kwm.d.mts → base-server-CeJ8LTBk.d.mts} +2 -2
  3. package/dist/{base64url-DNUGwekK.d.mts → base64url-CAmasWF0.d.mts} +1 -1
  4. package/dist/{component-route-Bxb-08X7.d.mts → component-route-CGbmQm5P.d.mts} +2 -2
  5. package/dist/{component-server-DQ3nZWFc.d.mts → component-server-CKcXIvMg.d.mts} +4 -4
  6. package/dist/{contract-CuruqP6h.d.mts → contract-C-xQoZ6r.d.mts} +1 -1
  7. package/dist/{contract-Cwmmo-Nn.mjs → contract-vSyKiRwz.mjs} +2 -2
  8. package/dist/contract-vSyKiRwz.mjs.map +1 -0
  9. package/dist/{defineRoute-DyPa9FHa.d.mts → defineRoute-B9VdaoQA.d.mts} +49 -5
  10. package/dist/defineRoute.d.mts +2 -2
  11. package/dist/defineRoute.mjs +107 -74
  12. package/dist/defineRoute.mjs.map +1 -1
  13. package/dist/{dependency-manager-DIN9X0Gj.d.mts → dependency-manager-mqzLAocb.d.mts} +1 -1
  14. package/dist/{formats-DDDSFWP0.d.mts → formats-Ca7ASaYH.d.mts} +1 -1
  15. package/dist/{go-await-DPtVBug4.d.mts → go-await-Dz1CRSTT.d.mts} +1 -1
  16. package/dist/{html-renderer-DhQxRuyi.d.mts → html-renderer-Up52eIS6.d.mts} +1 -1
  17. package/dist/{index-Cek4HyXL.d.mts → index-CRU-u6NT.d.mts} +5 -5
  18. package/dist/index.d.mts +21 -21
  19. package/dist/index.mjs +4 -5
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/middleware/component-router.d.mts +1 -1
  22. package/dist/{middleware-DXssDt1F.d.mts → middleware-BTg4GbjC.d.mts} +2 -2
  23. package/dist/middleware.d.mts +1 -1
  24. package/dist/monitoring/index.d.mts +3 -3
  25. package/dist/monitoring/native-monitor.d.mts +3 -3
  26. package/dist/node-server/index.d.mts +1 -1
  27. package/dist/node-server/index.mjs +3 -3
  28. package/dist/node-server/request.mjs +1 -1
  29. package/dist/node-server/response.mjs +1 -1
  30. package/dist/node-server/serve.d.mts +1 -1
  31. package/dist/node-server/serve.mjs +2 -2
  32. package/dist/{parsers-8hIAx0OV.d.mts → parsers-BAQtDA1q.d.mts} +1 -1
  33. package/dist/{request-D202oxO9.mjs → request-DEWtcK8t.mjs} +1 -1
  34. package/dist/{request-D202oxO9.mjs.map → request-DEWtcK8t.mjs.map} +1 -1
  35. package/dist/{response-DNdvtn-K.mjs → response-BlHLmKys.mjs} +1 -1
  36. package/dist/{response-DNdvtn-K.mjs.map → response-BlHLmKys.mjs.map} +1 -1
  37. package/dist/{response-F-VxN-cB.d.mts → response-lI0YZoia.d.mts} +2 -2
  38. package/dist/{route-registry-CAX54I8j.d.mts → route-registry-C6h13Mks.d.mts} +3 -3
  39. package/dist/router/radix-tree.d.mts +1 -1
  40. package/dist/{serve-BNSr7-5v.mjs → serve-DVlDG92Y.mjs} +3 -3
  41. package/dist/{serve-BNSr7-5v.mjs.map → serve-DVlDG92Y.mjs.map} +1 -1
  42. package/dist/{serve-Ds8Px1wD.d.mts → serve-Dw-GHkc3.d.mts} +1 -1
  43. package/dist/serve.d.mts +1 -1
  44. package/dist/serve.mjs +2 -2
  45. package/dist/server/base-server.d.mts +1 -1
  46. package/dist/server/component-server.d.mts +1 -1
  47. package/dist/server/index.d.mts +5 -5
  48. package/dist/server/server-factory.d.mts +3 -3
  49. package/dist/server/server.d.mts +2 -2
  50. package/dist/{server-3uMr8Ujo.d.mts → server-CQ-_WgQN.d.mts} +4 -4
  51. package/dist/sse-D77CKcsH.d.mts +45 -0
  52. package/dist/types/component-route.d.mts +1 -1
  53. package/dist/types/index.d.mts +2 -2
  54. package/dist/types/types.d.mts +1 -1
  55. package/dist/{types-D4pCpFZ_.d.mts → types-aczawQFE.d.mts} +1 -1
  56. package/dist/utils/base64url.d.mts +1 -1
  57. package/dist/utils/contract.d.mts +1 -1
  58. package/dist/utils/contract.mjs +1 -1
  59. package/dist/utils/dependency-manager.d.mts +1 -1
  60. package/dist/utils/formats.d.mts +1 -1
  61. package/dist/utils/go-await.d.mts +1 -1
  62. package/dist/utils/html-renderer.d.mts +1 -1
  63. package/dist/utils/index.d.mts +13 -13
  64. package/dist/utils/index.mjs +2 -3
  65. package/dist/utils/parsers.d.mts +1 -1
  66. package/dist/utils/response.d.mts +1 -1
  67. package/dist/utils/route-registry.d.mts +2 -2
  68. package/dist/utils/sse.d.mts +2 -3
  69. package/dist/utils/sse.mjs +1 -5
  70. package/dist/utils/validators/validators.d.mts +1 -1
  71. package/dist/{validators-BFC6S_fr.d.mts → validators-D5KJCSZr.d.mts} +1 -1
  72. package/package.json +1 -1
  73. package/dist/contract-Cwmmo-Nn.mjs.map +0 -1
  74. package/dist/sse-C0_ODr4_.mjs +0 -111
  75. package/dist/sse-C0_ODr4_.mjs.map +0 -1
  76. package/dist/sse-CjIH9WjQ.d.mts +0 -81
  77. /package/dist/{component-route-BiUHBq7a.mjs → component-route-DdKFowzp.mjs} +0 -0
  78. /package/dist/{index-Dflz2i1X.d.mts → index-D4DUvwPf.d.mts} +0 -0
package/README.md CHANGED
@@ -528,33 +528,27 @@ defineRoute({
528
528
 
529
529
  ### SSE 流式响应
530
530
 
531
- 内置 `createSSEHandler` 支持 Server-Sent Events,适用于 AI 聊天、进度更新等场景:
531
+ 通过 `sse: true` 显式声明 SSE 端点,适用于 AI 聊天、进度更新等场景:
532
532
 
533
533
  ```typescript
534
- import { createSSEHandler, defineRoute, defineRoutes, Type } from 'vafast'
534
+ import { defineRoute, defineRoutes, Type } from 'vafast'
535
535
 
536
- // 创建 SSE handler
537
- const progressHandler = createSSEHandler(
538
- { params: Type.Object({ taskId: Type.String() }) },
539
- async function* ({ params }) {
540
- yield { event: 'start', data: { taskId: params.taskId } }
541
-
542
- for (let i = 0; i <= 100; i += 10) {
543
- yield { data: { progress: i } }
544
- await new Promise(r => setTimeout(r, 100))
545
- }
546
-
547
- yield { event: 'complete', data: { message: 'Done!' } }
548
- }
549
- )
550
-
551
- // 在 defineRoute 中使用
552
536
  const routes = defineRoutes([
553
537
  defineRoute({
554
538
  method: 'GET',
555
539
  path: '/tasks/:taskId/progress',
540
+ sse: true, // 显式声明 SSE 端点
556
541
  schema: { params: Type.Object({ taskId: Type.String() }) },
557
- handler: progressHandler,
542
+ handler: async function* ({ params }) {
543
+ yield { event: 'start', data: { taskId: params.taskId } }
544
+
545
+ for (let i = 0; i <= 100; i += 10) {
546
+ yield { data: { progress: i } }
547
+ await new Promise(r => setTimeout(r, 100))
548
+ }
549
+
550
+ yield { event: 'complete', data: { message: 'Done!' } }
551
+ },
558
552
  }),
559
553
  ])
560
554
  ```
@@ -1,4 +1,4 @@
1
- import { r as Middleware } from "./types-D4pCpFZ_.mjs";
1
+ import { r as Middleware } from "./types-aczawQFE.mjs";
2
2
 
3
3
  //#region src/server/base-server.d.ts
4
4
 
@@ -36,4 +36,4 @@ declare abstract class BaseServer {
36
36
  }
37
37
  //#endregion
38
38
  export { BaseServer as t };
39
- //# sourceMappingURL=base-server-D7ny0Kwm.d.mts.map
39
+ //# sourceMappingURL=base-server-CeJ8LTBk.d.mts.map
@@ -3,4 +3,4 @@ declare function base64urlEncode(str: string): string;
3
3
  declare function base64urlDecode(str: string): string;
4
4
  //#endregion
5
5
  export { base64urlEncode as n, base64urlDecode as t };
6
- //# sourceMappingURL=base64url-DNUGwekK.d.mts.map
6
+ //# sourceMappingURL=base64url-CAmasWF0.d.mts.map
@@ -1,4 +1,4 @@
1
- import { r as Middleware } from "./types-D4pCpFZ_.mjs";
1
+ import { r as Middleware } from "./types-aczawQFE.mjs";
2
2
 
3
3
  //#region src/types/component-route.d.ts
4
4
 
@@ -28,4 +28,4 @@ interface FlattenedComponentRoute extends ComponentRoute {
28
28
  }
29
29
  //#endregion
30
30
  export { FlattenedComponentRoute as n, NestedComponentRoute as r, ComponentRoute as t };
31
- //# sourceMappingURL=component-route-Bxb-08X7.d.mts.map
31
+ //# sourceMappingURL=component-route-CGbmQm5P.d.mts.map
@@ -1,6 +1,6 @@
1
- import { r as NestedComponentRoute, t as ComponentRoute } from "./component-route-Bxb-08X7.mjs";
2
- import { t as BaseServer } from "./base-server-D7ny0Kwm.mjs";
3
- import { t as DependencyManager } from "./dependency-manager-DIN9X0Gj.mjs";
1
+ import { r as NestedComponentRoute, t as ComponentRoute } from "./component-route-CGbmQm5P.mjs";
2
+ import { t as BaseServer } from "./base-server-CeJ8LTBk.mjs";
3
+ import { t as DependencyManager } from "./dependency-manager-mqzLAocb.mjs";
4
4
 
5
5
  //#region src/server/component-server.d.ts
6
6
 
@@ -35,4 +35,4 @@ declare class ComponentServer extends BaseServer {
35
35
  }
36
36
  //#endregion
37
37
  export { ComponentServer as t };
38
- //# sourceMappingURL=component-server-DQ3nZWFc.d.mts.map
38
+ //# sourceMappingURL=component-server-CKcXIvMg.d.mts.map
@@ -71,4 +71,4 @@ declare function generateAITools(routes: readonly unknown[]): AITool[];
71
71
  declare function getApiSpec(routesOrContext?: readonly unknown[] | Record<string, unknown>): ApiSpec;
72
72
  //#endregion
73
73
  export { generateAITools as n, getApiSpec as r, ApiSpec as t };
74
- //# sourceMappingURL=contract-CuruqP6h.d.mts.map
74
+ //# sourceMappingURL=contract-C-xQoZ6r.d.mts.map
@@ -16,7 +16,7 @@ function generateSpec(routes) {
16
16
  };
17
17
  if (r.name) spec.name = r.name;
18
18
  if (r.description) spec.description = r.description;
19
- if (r.sse === true || r.handler?.__sse?.__brand === "SSE") spec.sse = true;
19
+ if (r.sse === true) spec.sse = true;
20
20
  if (r.schema) {
21
21
  const schema = r.schema;
22
22
  if (schema.body || schema.query || schema.params || schema.headers || schema.cookies || schema.response) {
@@ -113,4 +113,4 @@ function getRoutesFromRegistry() {
113
113
 
114
114
  //#endregion
115
115
  export { getApiSpec as n, generateAITools as t };
116
- //# sourceMappingURL=contract-Cwmmo-Nn.mjs.map
116
+ //# sourceMappingURL=contract-vSyKiRwz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-vSyKiRwz.mjs","names":[],"sources":["../src/utils/contract.ts"],"sourcesContent":["/**\n * API Spec 生成器\n *\n * 用于生成 API 规范,支持:\n * - 跨仓库类型同步\n * - AI 工具函数生成\n * - Swagger/OpenAPI 文档生成\n *\n * @example\n * ```typescript\n * import { getApiSpec } from 'vafast'\n *\n * // 方式 1:直接作为 handler(推荐,自动从全局 Registry 获取)\n * const allRoutes = [\n * ...routes,\n * { method: 'GET', path: '/api-spec', handler: getApiSpec }\n * ]\n *\n * // 方式 2:显式传参(灵活场景,如只暴露公开 API)\n * { handler: () => getApiSpec(publicRoutes) }\n * ```\n */\n\nimport type { TSchema } from '@sinclair/typebox'\nimport type { RouteSchema } from '../defineRoute'\nimport { getRouteRegistry } from './route-registry'\n\n/** 路由规范信息 */\ninterface RouteSpec {\n method: string\n path: string\n name?: string\n description?: string\n /** 是否为 SSE 端点(Server-Sent Events) */\n sse?: boolean\n schema?: {\n body?: TSchema\n query?: TSchema\n params?: TSchema\n headers?: TSchema\n cookies?: TSchema\n response?: TSchema\n }\n}\n\n/** API 规范 */\nexport interface ApiSpec {\n version: string\n generatedAt: string\n routes: RouteSpec[]\n}\n\n/** AI 工具函数格式 */\ninterface AITool {\n name: string\n description?: string\n parameters?: TSchema\n}\n\n/**\n * 从路由数组生成 API 规范\n */\nfunction generateSpec(routes: readonly unknown[]): ApiSpec {\n const routeSpecs: RouteSpec[] = []\n\n for (const route of routes) {\n const r = route as {\n method?: string\n path?: string\n name?: string\n description?: string\n schema?: RouteSchema\n sse?: boolean\n }\n\n if (!r.method || !r.path) continue\n\n // 跳过 spec 接口本身\n if (r.path === '/api-spec' || r.path === '/__spec__') continue\n\n const spec: RouteSpec = {\n method: r.method,\n path: r.path,\n }\n\n // 直接从路由获取 name 和 description\n if (r.name) spec.name = r.name\n if (r.description) spec.description = r.description\n\n // SSE 标记\n if (r.sse === true) {\n spec.sse = true\n }\n\n // 直接从路由获取 schema\n if (r.schema) {\n const schema = r.schema\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies || schema.response) {\n spec.schema = {}\n if (schema.body) spec.schema.body = schema.body\n if (schema.query) spec.schema.query = schema.query\n if (schema.params) spec.schema.params = schema.params\n if (schema.headers) spec.schema.headers = schema.headers\n if (schema.cookies) spec.schema.cookies = schema.cookies\n if (schema.response) spec.schema.response = schema.response\n }\n }\n\n routeSpecs.push(spec)\n }\n\n return {\n version: '1.0.0',\n generatedAt: new Date().toISOString(),\n routes: routeSpecs,\n }\n}\n\n/**\n * 从路由数组生成 AI 工具函数\n *\n * 可直接用于 OpenAI Function Calling / Claude Tools\n *\n * @example\n * ```typescript\n * const tools = generateAITools(routes)\n * // [{ name: 'get_users', description: '获取用户列表', parameters: {...} }]\n * ```\n */\nexport function generateAITools(routes: readonly unknown[]): AITool[] {\n const tools: AITool[] = []\n\n for (const route of routes) {\n const r = route as {\n method?: string\n path?: string\n name?: string\n description?: string\n schema?: RouteSchema\n }\n\n if (!r.method || !r.path) continue\n if (r.path === '/api-spec' || r.path === '/__spec__') continue\n\n // 使用 name 或从 path 生成\n const name = r.name || pathToToolName(r.method, r.path)\n\n const tool: AITool = { name }\n if (r.description) tool.description = r.description\n\n // GET 用 query,其他用 body\n if (r.schema) {\n if (r.method === 'GET' && r.schema.query) {\n tool.parameters = r.schema.query\n } else if (r.schema.body) {\n tool.parameters = r.schema.body\n }\n }\n\n tools.push(tool)\n }\n\n return tools\n}\n\n/** 从路径生成工具名 */\nfunction pathToToolName(method: string, path: string): string {\n const segments = path.split('/').filter(Boolean)\n const cleanSegments = segments\n .map(s => s.startsWith(':') ? '' : s)\n .filter(Boolean)\n\n const prefix = method.toLowerCase()\n const suffix = cleanSegments.join('_')\n\n return suffix ? `${prefix}_${suffix}` : prefix\n}\n\n/**\n * 获取 API 规范\n *\n * 支持多种调用方式:\n * 1. 直接作为 handler:自动从全局 Registry 获取(推荐)\n * 2. 无参调用:同上,用于 CLI/测试\n * 3. 有参调用:显式传递路由数组(灵活场景)\n *\n * @param routesOrContext - 可选,路由数组或 handler context。不传则从全局 Registry 获取\n * @returns ApiSpec 对象\n *\n * @example\n * ```typescript\n * import { getApiSpec } from 'vafast'\n *\n * // 方式 1:直接作为 handler(推荐,最简洁)\n * { method: 'GET', path: '/api-spec', handler: getApiSpec }\n *\n * // 方式 2:显式传参(只暴露公开 API)\n * { handler: () => getApiSpec(publicRoutes) }\n *\n * // 方式 3:本地使用(CLI、测试)\n * const spec = getApiSpec()\n * ```\n */\nexport function getApiSpec(routesOrContext?: readonly unknown[] | Record<string, unknown>): ApiSpec {\n // 智能检测:是路由数组还是 handler context\n // 路由数组:Array && 第一个元素有 method 属性\n const isRoutesArray = Array.isArray(routesOrContext) &&\n routesOrContext.length > 0 &&\n typeof (routesOrContext[0] as Record<string, unknown>)?.method === 'string'\n\n const routeList = isRoutesArray\n ? routesOrContext\n : getRoutesFromRegistry()\n\n return generateSpec(routeList)\n}\n\n/**\n * 从全局 Registry 获取路由列表\n * 包含 schema 信息(Registry 存储完整路由)\n */\nfunction getRoutesFromRegistry(): readonly unknown[] {\n try {\n const registry = getRouteRegistry()\n return registry.getAll()\n } catch {\n // Registry 未初始化时返回空数组\n return []\n }\n}\n"],"mappings":";;;;;;AA8DA,SAAS,aAAa,QAAqC;CACzD,MAAM,aAA0B,EAAE;AAElC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,IAAI;AASV,MAAI,CAAC,EAAE,UAAU,CAAC,EAAE,KAAM;AAG1B,MAAI,EAAE,SAAS,eAAe,EAAE,SAAS,YAAa;EAEtD,MAAM,OAAkB;GACtB,QAAQ,EAAE;GACV,MAAM,EAAE;GACT;AAGD,MAAI,EAAE,KAAM,MAAK,OAAO,EAAE;AAC1B,MAAI,EAAE,YAAa,MAAK,cAAc,EAAE;AAGxC,MAAI,EAAE,QAAQ,KACZ,MAAK,MAAM;AAIb,MAAI,EAAE,QAAQ;GACZ,MAAM,SAAS,EAAE;AACjB,OAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,WAAW,OAAO,UAAU;AACvG,SAAK,SAAS,EAAE;AAChB,QAAI,OAAO,KAAM,MAAK,OAAO,OAAO,OAAO;AAC3C,QAAI,OAAO,MAAO,MAAK,OAAO,QAAQ,OAAO;AAC7C,QAAI,OAAO,OAAQ,MAAK,OAAO,SAAS,OAAO;AAC/C,QAAI,OAAO,QAAS,MAAK,OAAO,UAAU,OAAO;AACjD,QAAI,OAAO,QAAS,MAAK,OAAO,UAAU,OAAO;AACjD,QAAI,OAAO,SAAU,MAAK,OAAO,WAAW,OAAO;;;AAIvD,aAAW,KAAK,KAAK;;AAGvB,QAAO;EACL,SAAS;EACT,8BAAa,IAAI,MAAM,EAAC,aAAa;EACrC,QAAQ;EACT;;;;;;;;;;;;;AAcH,SAAgB,gBAAgB,QAAsC;CACpE,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,IAAI;AAQV,MAAI,CAAC,EAAE,UAAU,CAAC,EAAE,KAAM;AAC1B,MAAI,EAAE,SAAS,eAAe,EAAE,SAAS,YAAa;EAKtD,MAAM,OAAe,EAAE,MAFV,EAAE,QAAQ,eAAe,EAAE,QAAQ,EAAE,KAAK,EAE1B;AAC7B,MAAI,EAAE,YAAa,MAAK,cAAc,EAAE;AAGxC,MAAI,EAAE,QACJ;OAAI,EAAE,WAAW,SAAS,EAAE,OAAO,MACjC,MAAK,aAAa,EAAE,OAAO;YAClB,EAAE,OAAO,KAClB,MAAK,aAAa,EAAE,OAAO;;AAI/B,QAAM,KAAK,KAAK;;AAGlB,QAAO;;;AAIT,SAAS,eAAe,QAAgB,MAAsB;CAE5D,MAAM,gBADW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAE7C,KAAI,MAAK,EAAE,WAAW,IAAI,GAAG,KAAK,EAAE,CACpC,OAAO,QAAQ;CAElB,MAAM,SAAS,OAAO,aAAa;CACnC,MAAM,SAAS,cAAc,KAAK,IAAI;AAEtC,QAAO,SAAS,GAAG,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B1C,SAAgB,WAAW,iBAAyE;AAWlG,QAAO,aARe,MAAM,QAAQ,gBAAgB,IAClD,gBAAgB,SAAS,KACzB,OAAQ,gBAAgB,IAAgC,WAAW,WAGjE,kBACA,uBAAuB,CAEG;;;;;;AAOhC,SAAS,wBAA4C;AACnD,KAAI;AAEF,SADiB,kBAAkB,CACnB,QAAQ;SAClB;AAEN,SAAO,EAAE"}
@@ -2,6 +2,15 @@ import { Static, TSchema } from "@sinclair/typebox";
2
2
 
3
3
  //#region src/defineRoute.d.ts
4
4
 
5
+ /** SSE 事件 */
6
+ interface SSEEventType<T = unknown> {
7
+ event?: string;
8
+ data: T;
9
+ id?: string;
10
+ retry?: number;
11
+ }
12
+ /** SSE Generator 类型 */
13
+ type SSEGeneratorType<TSchema$1 extends RouteSchema = RouteSchema> = (ctx: HandlerContext<TSchema$1>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>;
5
14
  /** 路由 Schema 配置 */
6
15
  interface RouteSchema {
7
16
  body?: TSchema;
@@ -47,6 +56,12 @@ interface HandlerContext<TSchema$1 extends RouteSchema = RouteSchema> {
47
56
  type HandlerContextWithExtra<TSchema$1 extends RouteSchema, TExtra> = HandlerContext<TSchema$1> & TExtra;
48
57
  /** HTTP 方法 */
49
58
  type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
59
+ /** Handler 上下文类型(带中间件扩展) */
60
+ type HandlerCtx<TSchema$1 extends RouteSchema, TMiddleware extends readonly AnyMiddleware[]> = HandlerContextWithExtra<TSchema$1, MergeMiddlewareContexts<TMiddleware>>;
61
+ /** 普通 Handler 类型 */
62
+ type NormalHandler<TSchema$1 extends RouteSchema, TReturn, TMiddleware extends readonly AnyMiddleware[]> = (ctx: HandlerCtx<TSchema$1, TMiddleware>) => TReturn | Promise<TReturn>;
63
+ /** SSE Generator Handler 类型(直接写 async function*,无需 createSSEHandler 包装) */
64
+ type SSEHandler<TSchema$1 extends RouteSchema, TMiddleware extends readonly AnyMiddleware[]> = (ctx: HandlerCtx<TSchema$1, TMiddleware>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>;
50
65
  /** 叶子路由配置(有 method 和 handler) */
51
66
  interface LeafRouteConfig<TMethod extends HTTPMethod = HTTPMethod, TPath extends string = string, TSchema$1 extends RouteSchema = RouteSchema, TReturn = unknown, TMiddleware extends readonly AnyMiddleware[] = readonly AnyMiddleware[]> {
52
67
  readonly method: TMethod;
@@ -54,7 +69,22 @@ interface LeafRouteConfig<TMethod extends HTTPMethod = HTTPMethod, TPath extends
54
69
  readonly name?: string;
55
70
  readonly description?: string;
56
71
  readonly schema?: TSchema$1;
57
- readonly handler: (ctx: HandlerContextWithExtra<TSchema$1, MergeMiddlewareContexts<TMiddleware>>) => TReturn | Promise<TReturn>;
72
+ /**
73
+ * 是否为 SSE 端点(显式声明,推荐)
74
+ *
75
+ * 设置为 true 时,handler 应返回 AsyncGenerator:
76
+ * ```typescript
77
+ * sse: true,
78
+ * handler: async function* (ctx) { yield { data: ... } }
79
+ * ```
80
+ */
81
+ readonly sse?: boolean;
82
+ /**
83
+ * Handler 支持两种写法:
84
+ * 1. 普通函数: `async (ctx) => { return result }`
85
+ * 2. SSE Generator(需配合 sse: true): `async function* (ctx) { yield { data: ... } }`
86
+ */
87
+ readonly handler: NormalHandler<TSchema$1, TReturn, TMiddleware> | SSEHandler<TSchema$1, TMiddleware>;
58
88
  readonly middleware?: TMiddleware;
59
89
  readonly docs?: {
60
90
  tags?: string[];
@@ -79,6 +109,8 @@ interface ProcessedRoute {
79
109
  name?: string;
80
110
  description?: string;
81
111
  schema?: RouteSchema;
112
+ /** 是否为 SSE 端点 */
113
+ sse?: boolean;
82
114
  handler: (req: Request) => Promise<Response>;
83
115
  middleware?: readonly AnyMiddleware[];
84
116
  docs?: {
@@ -135,9 +167,11 @@ declare function defineRoute<const TSchema$1 extends RouteSchema, TReturn, const
135
167
  readonly name?: string;
136
168
  readonly description?: string;
137
169
  readonly schema?: TSchema$1;
170
+ /** 是否为 SSE 端点,设置为 true 时 handler 应返回 AsyncGenerator */
171
+ readonly sse?: boolean;
138
172
  /** 显式声明上下文类型(用于父级中间件注入的场景) */
139
173
  readonly context?: TContext;
140
- readonly handler: (ctx: HandlerContextWithExtra<TSchema$1, TContext & MergeMiddlewareContexts<TMiddleware>>) => TReturn | Promise<TReturn>;
174
+ readonly handler: (ctx: HandlerContextWithExtra<TSchema$1, TContext & MergeMiddlewareContexts<TMiddleware>>) => TReturn | Promise<TReturn> | AsyncGenerator<SSEEventType<unknown>, void, unknown>;
141
175
  readonly middleware?: TMiddleware;
142
176
  readonly docs?: {
143
177
  tags?: string[];
@@ -199,13 +233,23 @@ declare function defineRoute<const TMiddleware extends readonly AnyMiddleware[],
199
233
  * })
200
234
  * ```
201
235
  */
236
+ /** withContext Handler 上下文类型 */
237
+ type WithContextHandlerCtx<TSchema$1 extends RouteSchema, TContext extends object, TMiddleware extends readonly AnyMiddleware[]> = HandlerContextWithExtra<TSchema$1, TContext & MergeMiddlewareContexts<TMiddleware>>;
238
+ /** withContext 支持的 Handler 类型(普通函数 + SSE Generator) */
239
+ type WithContextHandler<TSchema$1 extends RouteSchema, TContext extends object, TMiddleware extends readonly AnyMiddleware[], TReturn> = ((ctx: WithContextHandlerCtx<TSchema$1, TContext, TMiddleware>) => TReturn | Promise<TReturn>) | ((ctx: WithContextHandlerCtx<TSchema$1, TContext, TMiddleware>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>);
202
240
  declare function withContext<TContext extends object, TExtensions extends object = object>(): <const TSchema$1 extends RouteSchema, TReturn, const TMiddleware extends readonly AnyMiddleware[], TMethod extends HTTPMethod = HTTPMethod, TPath extends string = string>(config: {
203
241
  readonly method: TMethod;
204
242
  readonly path: TPath;
205
243
  readonly name?: string;
206
244
  readonly description?: string;
207
245
  readonly schema?: TSchema$1;
208
- readonly handler: (ctx: HandlerContextWithExtra<TSchema$1, TContext & MergeMiddlewareContexts<TMiddleware>>) => TReturn | Promise<TReturn>;
246
+ /**
247
+ * 是否为 SSE 端点
248
+ * 设置为 true 时,handler 应返回 AsyncGenerator
249
+ */
250
+ readonly sse?: boolean;
251
+ /** Handler 支持两种写法:普通函数 或 SSE Generator(需配合 sse: true) */
252
+ readonly handler: WithContextHandler<TSchema$1, TContext, TMiddleware, TReturn>;
209
253
  readonly middleware?: TMiddleware;
210
254
  readonly docs?: {
211
255
  tags?: string[];
@@ -248,5 +292,5 @@ type InferableRoute<TMethod extends string = string, TPath extends string = stri
248
292
  readonly middleware?: ReadonlyArray<AnyMiddleware>;
249
293
  };
250
294
  //#endregion
251
- export { ProcessedRoute as a, RoutesWithSource as c, defineRoute as d, defineRoutes as f, NestedRouteConfig as i, TypedMiddleware as l, InferableRoute as n, Route as o, withContext as p, LeafRouteConfig as r, RouteSchema as s, HandlerContext as t, defineMiddleware as u };
252
- //# sourceMappingURL=defineRoute-DyPa9FHa.d.mts.map
295
+ export { ProcessedRoute as a, RoutesWithSource as c, TypedMiddleware as d, defineMiddleware as f, withContext as h, NestedRouteConfig as i, SSEEventType as l, defineRoutes as m, InferableRoute as n, Route as o, defineRoute as p, LeafRouteConfig as r, RouteSchema as s, HandlerContext as t, SSEGeneratorType as u };
296
+ //# sourceMappingURL=defineRoute-B9VdaoQA.d.mts.map
@@ -1,2 +1,2 @@
1
- import { a as ProcessedRoute, c as RoutesWithSource, d as defineRoute, f as defineRoutes, i as NestedRouteConfig, l as TypedMiddleware, n as InferableRoute, o as Route, p as withContext, r as LeafRouteConfig, s as RouteSchema, t as HandlerContext, u as defineMiddleware } from "./defineRoute-DyPa9FHa.mjs";
2
- export { HandlerContext, InferableRoute, LeafRouteConfig, NestedRouteConfig, ProcessedRoute, Route, RouteSchema, RoutesWithSource, TypedMiddleware, defineMiddleware, defineRoute, defineRoutes, withContext };
1
+ import { a as ProcessedRoute, c as RoutesWithSource, d as TypedMiddleware, f as defineMiddleware, h as withContext, i as NestedRouteConfig, l as SSEEventType, m as defineRoutes, n as InferableRoute, o as Route, p as defineRoute, r as LeafRouteConfig, s as RouteSchema, t as HandlerContext, u as SSEGeneratorType } from "./defineRoute-B9VdaoQA.mjs";
2
+ export { HandlerContext, InferableRoute, LeafRouteConfig, NestedRouteConfig, ProcessedRoute, Route, RouteSchema, RoutesWithSource, SSEEventType, SSEGeneratorType, TypedMiddleware, defineMiddleware, defineRoute, defineRoutes, withContext };
@@ -54,37 +54,114 @@ function autoResponse(result) {
54
54
  }
55
55
  return new Response(null, { status: 204 });
56
56
  }
57
- /** 创建包装后的 handler */
57
+ /**
58
+ * 构建 HandlerContext(公共逻辑,供普通 handler 和 SSE handler 复用)
59
+ */
60
+ async function buildHandlerContext(req, schema) {
61
+ const query = parseQuery(req);
62
+ const headers = parseHeaders(req);
63
+ const cookies = parseCookies(req);
64
+ const params = req.params || {};
65
+ let body = void 0;
66
+ if (req.method !== "GET" && req.method !== "HEAD") try {
67
+ body = await parseBody(req);
68
+ } catch {}
69
+ const data = {
70
+ body,
71
+ query,
72
+ params,
73
+ headers,
74
+ cookies
75
+ };
76
+ if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) validateAllSchemas(schema, data);
77
+ const extraCtx = req.__locals || {};
78
+ return {
79
+ req,
80
+ body,
81
+ query,
82
+ params,
83
+ headers,
84
+ cookies,
85
+ ...extraCtx
86
+ };
87
+ }
88
+ /** 创建包装后的 handler(普通路由) */
58
89
  function wrapHandler(schema, userHandler) {
59
90
  if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) precompileSchemas(schema);
60
91
  return async (req) => {
61
92
  try {
62
- const query = parseQuery(req);
63
- const headers = parseHeaders(req);
64
- const cookies = parseCookies(req);
65
- const params = req.params || {};
66
- let body = void 0;
67
- if (req.method !== "GET" && req.method !== "HEAD") try {
68
- body = await parseBody(req);
69
- } catch {}
70
- const data = {
71
- body,
72
- query,
73
- params,
74
- headers,
75
- cookies
76
- };
77
- if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) validateAllSchemas(schema, data);
78
- const extraCtx = req.__locals || {};
79
- return autoResponse(await userHandler({
80
- req,
81
- body,
82
- query,
83
- params,
84
- headers,
85
- cookies,
86
- ...extraCtx
87
- }));
93
+ return autoResponse(await userHandler(await buildHandlerContext(req, schema)));
94
+ } catch (error) {
95
+ if (error instanceof VafastError) throw error;
96
+ if (error instanceof Error && error.message.includes("验证失败")) return json({
97
+ code: 400,
98
+ message: error.message
99
+ }, 400);
100
+ return json({
101
+ code: 500,
102
+ message: error instanceof Error ? error.message : "未知错误"
103
+ }, 500);
104
+ }
105
+ };
106
+ }
107
+ /**
108
+ * 格式化 SSE 事件为字符串(内联,避免循环依赖)
109
+ */
110
+ function formatSSEEvent(event) {
111
+ const lines = [];
112
+ if (event.id !== void 0) lines.push(`id: ${event.id}`);
113
+ if (event.event !== void 0) lines.push(`event: ${event.event}`);
114
+ if (event.retry !== void 0) lines.push(`retry: ${event.retry}`);
115
+ const dataStr = typeof event.data === "string" ? event.data : JSON.stringify(event.data);
116
+ for (const line of dataStr.split("\n")) lines.push(`data: ${line}`);
117
+ return lines.join("\n") + "\n\n";
118
+ }
119
+ /**
120
+ * 将 AsyncGenerator 包装为 SSE Handler
121
+ *
122
+ * 支持用户直接写 `async function* (ctx) { yield ... }` 而无需 createSSEHandler
123
+ */
124
+ function wrapGeneratorToSSEHandler(generator) {
125
+ return async (ctx) => {
126
+ const stream = new ReadableStream({ async start(controller) {
127
+ const encoder = new TextEncoder();
128
+ try {
129
+ for await (const event of generator(ctx)) controller.enqueue(encoder.encode(formatSSEEvent(event)));
130
+ } catch (error) {
131
+ const errorEvent = formatSSEEvent({
132
+ event: "error",
133
+ data: { error: error instanceof Error ? error.message : "未知错误" }
134
+ });
135
+ controller.enqueue(encoder.encode(errorEvent));
136
+ } finally {
137
+ controller.close();
138
+ }
139
+ } });
140
+ return new Response(stream, { headers: {
141
+ "Content-Type": "text/event-stream",
142
+ "Cache-Control": "no-cache",
143
+ "Connection": "keep-alive",
144
+ "X-Accel-Buffering": "no"
145
+ } });
146
+ };
147
+ }
148
+ /**
149
+ * 创建 SSE handler 的请求包装器
150
+ *
151
+ * SSE handler 与普通 handler 使用相同的上下文构建流程(buildHandlerContext),
152
+ * 确保:
153
+ * - body/query/params 解析一致
154
+ * - schema 验证统一
155
+ * - 中间件注入的上下文(如 userInfo)自动可用
156
+ * - 错误处理统一
157
+ *
158
+ * 唯一区别:SSE handler 返回的是 SSE Stream Response,而非普通 JSON Response
159
+ */
160
+ function wrapSSEHandler(schema, sseHandler) {
161
+ if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) precompileSchemas(schema);
162
+ return async (req) => {
163
+ try {
164
+ return await sseHandler(await buildHandlerContext(req, schema));
88
165
  } catch (error) {
89
166
  if (error instanceof VafastError) throw error;
90
167
  if (error instanceof Error && error.message.includes("验证失败")) return json({
@@ -112,50 +189,6 @@ function isNestedRoute(route) {
112
189
  function defineRoute(config) {
113
190
  return config;
114
191
  }
115
- /**
116
- * 创建带预设上下文类型的路由定义器
117
- *
118
- * 用于父级中间件注入上下文的场景,定义一次,多处复用
119
- *
120
- * @example
121
- * ```typescript
122
- * // 1. 在 middleware/index.ts 中定义
123
- * export const defineAuthRoute = withContext<{ userInfo: UserInfo }>()
124
- *
125
- * // 2. 在路由文件中使用
126
- * defineAuthRoute({
127
- * method: 'GET',
128
- * path: '/profile',
129
- * handler: ({ userInfo }) => {
130
- * // userInfo 自动有类型!
131
- * return { id: userInfo.id }
132
- * }
133
- * })
134
- * ```
135
- */
136
- /**
137
- * 带扩展类型的路由定义器
138
- *
139
- * @typeParam TContext - Handler 上下文类型(如 { userInfo: UserInfo })
140
- * @typeParam TExtensions - 路由扩展字段类型(如 { webhook?: boolean })
141
- *
142
- * @example
143
- * ```typescript
144
- * // 定义扩展类型
145
- * interface WebhookExtension {
146
- * webhook?: boolean | { eventKey?: string }
147
- * }
148
- *
149
- * // 使用扩展
150
- * const defineRoute = withContext<MyContext, WebhookExtension>()
151
- * defineRoute({
152
- * method: 'POST',
153
- * path: '/create',
154
- * webhook: true, // TypeScript 严格检查
155
- * handler: ...
156
- * })
157
- * ```
158
- */
159
192
  function withContext() {
160
193
  return (config) => {
161
194
  return config;
@@ -170,18 +203,18 @@ function flattenRoutes(routes, parentPath = "", parentMiddleware = [], parent) {
170
203
  const fullPath = parentPath + route.path;
171
204
  const mergedMiddleware = [...parentMiddleware, ...route.middleware || []];
172
205
  if (isLeafRoute(route)) {
173
- const isSSE = route.handler?.__sse?.__brand === "SSE";
206
+ const isSSE = route.sse === true;
174
207
  const processed = {
175
208
  method: route.method,
176
209
  path: fullPath,
177
210
  name: route.name,
178
211
  description: route.description,
179
212
  schema: route.schema,
180
- handler: isSSE ? route.handler : wrapHandler(route.schema, route.handler),
213
+ sse: isSSE || void 0,
214
+ handler: isSSE ? wrapSSEHandler(route.schema, wrapGeneratorToSSEHandler(route.handler)) : wrapHandler(route.schema, route.handler),
181
215
  middleware: mergedMiddleware.length > 0 ? mergedMiddleware : void 0,
182
216
  docs: route.docs
183
217
  };
184
- if (isSSE) processed.handler.__sse = { __brand: "SSE" };
185
218
  if (parent) processed.parent = parent;
186
219
  const knownKeys = [
187
220
  "method",
@@ -1 +1 @@
1
- {"version":3,"file":"defineRoute.mjs","names":[],"sources":["../src/defineRoute.ts"],"sourcesContent":["/**\n * 路由定义 - Schema 在路由级别定义,支持嵌套路由和中间件类型推断\n *\n * @example\n * ```typescript\n * // 定义带类型的中间件(函数式风格,通过 next 传递上下文)\n * const authMiddleware = defineMiddleware<{ user: User }>((req, next) => {\n * const user = getUser(req)\n * return next({ user }) // 通过 next 参数传递上下文\n * })\n *\n * // 路由自动推断中间件注入的类型\n * const routes = defineRoutes([\n * defineRoute({\n * path: '/api',\n * middleware: [authMiddleware],\n * children: [\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * handler: ({ user }) => ({ name: user.name }) // ✅ user 有类型\n * })\n * ]\n * })\n * ])\n * ```\n */\n\nimport type { TSchema, Static } from \"@sinclair/typebox\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./utils/parsers\";\nimport { validateAllSchemas, precompileSchemas } from \"./utils/validators/validators\";\nimport { json } from \"./utils/response\";\nimport { VafastError } from \"./middleware\";\n\n// ============= Schema 类型 =============\n\n/** 路由 Schema 配置 */\nexport interface RouteSchema {\n body?: TSchema;\n query?: TSchema;\n params?: TSchema;\n headers?: TSchema;\n cookies?: TSchema;\n /** 响应类型 schema(用于类型同步,运行时不做校验) */\n response?: TSchema;\n}\n\n/** 从 Schema 推断类型 */\ntype InferSchemaType<T extends RouteSchema> = {\n body: T[\"body\"] extends TSchema ? Static<T[\"body\"]> : unknown;\n query: T[\"query\"] extends TSchema ? Static<T[\"query\"]> : Record<string, string>;\n params: T[\"params\"] extends TSchema ? Static<T[\"params\"]> : Record<string, string>;\n headers: T[\"headers\"] extends TSchema ? Static<T[\"headers\"]> : Record<string, string>;\n cookies: T[\"cookies\"] extends TSchema ? Static<T[\"cookies\"]> : Record<string, string>;\n};\n\n// ============= 中间件类型系统 =============\n\n/** 带类型标记的中间件 */\nexport interface TypedMiddleware<TContext extends object = object> {\n (req: Request, next: (ctx?: TContext) => Promise<Response>): Response | Promise<Response>;\n /** 类型标记(仅编译时使用) */\n __context?: TContext;\n}\n\n/** 普通中间件(无类型注入) */\ntype PlainMiddleware = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>;\n\n/** 任意中间件类型 */\ntype AnyMiddleware = TypedMiddleware<object> | PlainMiddleware;\n\n/** 从中间件提取上下文类型 */\ntype ExtractMiddlewareContext<T> = T extends TypedMiddleware<infer C> ? C : object;\n\n/** 合并中间件数组的上下文类型 */\ntype MergeMiddlewareContexts<T extends readonly unknown[]> =\n T extends readonly [infer First, ...infer Rest]\n ? ExtractMiddlewareContext<First> & MergeMiddlewareContexts<Rest>\n : object;\n\n// ============= Handler 上下文 =============\n\n/** Handler 上下文(包含 schema 推断) */\nexport interface HandlerContext<TSchema extends RouteSchema = RouteSchema> {\n req: Request;\n body: InferSchemaType<TSchema>[\"body\"];\n query: InferSchemaType<TSchema>[\"query\"];\n params: InferSchemaType<TSchema>[\"params\"];\n headers: InferSchemaType<TSchema>[\"headers\"];\n cookies: InferSchemaType<TSchema>[\"cookies\"];\n}\n\n/** Handler 上下文(带中间件注入的额外类型) */\ntype HandlerContextWithExtra<TSchema extends RouteSchema, TExtra> =\n HandlerContext<TSchema> & TExtra;\n\n// ============= 路由配置类型 =============\n\n/** HTTP 方法 */\ntype HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"OPTIONS\" | \"HEAD\";\n\n/** 叶子路由配置(有 method 和 handler) */\nexport interface LeafRouteConfig<\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string,\n TSchema extends RouteSchema = RouteSchema,\n TReturn = unknown,\n TMiddleware extends readonly AnyMiddleware[] = readonly AnyMiddleware[]\n> {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n readonly handler: (\n ctx: HandlerContextWithExtra<TSchema, MergeMiddlewareContexts<TMiddleware>>\n ) => TReturn | Promise<TReturn>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}\n\n/** 嵌套路由配置(有 children,无 method 和 handler) */\nexport interface NestedRouteConfig<\n TPath extends string = string,\n TMiddleware extends readonly AnyMiddleware[] = readonly AnyMiddleware[]\n> {\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly middleware?: TMiddleware;\n readonly children: ReadonlyArray<RouteConfigResult>;\n}\n\n/** defineRoute 返回的类型 */\ntype RouteConfigResult =\n | LeafRouteConfig<HTTPMethod, string, RouteSchema, unknown, readonly AnyMiddleware[]>\n | NestedRouteConfig<string, readonly AnyMiddleware[]>;\n\n/** 处理后的扁平路由 */\nexport interface ProcessedRoute {\n method: HTTPMethod;\n path: string;\n name?: string;\n description?: string;\n schema?: RouteSchema;\n handler: (req: Request) => Promise<Response>;\n middleware?: readonly AnyMiddleware[];\n docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n /** 允许任意扩展(兼容 Route 类型) */\n [key: string]: unknown;\n}\n\n/** Route 类型别名(便于用户使用) */\nexport type Route = ProcessedRoute;\n\n// ============= defineMiddleware =============\n\n/**\n * 定义带类型的中间件(函数式风格)\n *\n * 通过 next() 参数传递上下文,更符合函数式编程风格\n *\n * @example\n * ```typescript\n * type AuthContext = { user: { id: string; name: string } }\n *\n * const authMiddleware = defineMiddleware<AuthContext>((req, next) => {\n * const user = getUserFromToken(req)\n * return next({ user }) // 通过 next 传递上下文\n * })\n * ```\n */\nexport function defineMiddleware<TContext extends object = object>(\n handler: (\n req: Request,\n next: (ctx?: TContext) => Promise<Response>\n ) => Promise<Response>\n): TypedMiddleware<TContext> {\n // 包装成标准中间件签名\n const middleware = ((req: Request, originalNext: () => Promise<Response>) => {\n // 包装 next,接收上下文参数并存储到 req.__locals\n const nextWithContext = (ctx?: TContext): Promise<Response> => {\n if (ctx) {\n const target = req as unknown as { __locals?: object };\n target.__locals = { ...(target.__locals || {}), ...ctx };\n }\n return originalNext();\n };\n return handler(req, nextWithContext);\n }) as TypedMiddleware<TContext>;\n\n return middleware;\n}\n\n// ============= 响应处理 =============\n\n/** 自动转换返回值为 Response */\nfunction autoResponse(result: unknown): Response {\n if (result instanceof Response) return result;\n if (result === null || result === undefined) return new Response(null, { status: 204 });\n if (typeof result === \"string\") {\n return new Response(result, { headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n if (typeof result === \"number\" || typeof result === \"boolean\") {\n return new Response(String(result), { headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n if (typeof result === \"object\") {\n const obj = result as Record<string, unknown>;\n if (\"data\" in obj && (\"status\" in obj || \"headers\" in obj)) {\n const { data, status = 200, headers = {} } = obj;\n if (data === null || data === undefined) {\n return new Response(null, { status: status === 200 ? 204 : (status as number), headers: headers as HeadersInit });\n }\n return json(data, status as number, headers as Record<string, string>);\n }\n return json(result);\n }\n return new Response(null, { status: 204 });\n}\n\n/** 创建包装后的 handler */\nfunction wrapHandler<TSchema extends RouteSchema>(\n schema: TSchema | undefined,\n userHandler: (ctx: HandlerContext<TSchema>) => unknown | Promise<unknown>\n): (req: Request) => Promise<Response> {\n if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\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 let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n try {\n body = await parseBody(req);\n } catch {\n // 忽略解析错误\n }\n }\n\n const data = { body, query, params, headers, cookies };\n if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) {\n validateAllSchemas(schema, data);\n }\n\n // 获取中间件注入的上下文\n const extraCtx = (req as unknown as { __locals?: unknown }).__locals || {};\n\n const result = await userHandler({\n req,\n body: body as HandlerContext<TSchema>[\"body\"],\n query: query as HandlerContext<TSchema>[\"query\"],\n params: params as HandlerContext<TSchema>[\"params\"],\n headers: headers as HandlerContext<TSchema>[\"headers\"],\n cookies: cookies as HandlerContext<TSchema>[\"cookies\"],\n ...extraCtx,\n } as HandlerContext<TSchema>);\n\n return autoResponse(result);\n } catch (error) {\n // 如果是 VafastError,重新抛出让错误处理中间件处理\n if (error instanceof VafastError) {\n throw error;\n }\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return json({ code: 400, message: error.message }, 400);\n }\n return json({ code: 500, message: error instanceof Error ? error.message : \"未知错误\" }, 500);\n }\n };\n}\n\n// ============= 判断路由类型 =============\n\n/** 判断是否为叶子路由 */\nfunction isLeafRoute(route: RouteConfigResult): route is LeafRouteConfig {\n return \"method\" in route && \"handler\" in route;\n}\n\n/** 判断是否为嵌套路由 */\nfunction isNestedRoute(route: RouteConfigResult): route is NestedRouteConfig {\n return \"children\" in route;\n}\n\n// ============= defineRoute 函数(支持重载) =============\n\n/**\n * 定义叶子路由(有 method 和 handler),支持中间件类型推断和显式上下文类型\n *\n * @example\n * ```typescript\n * // 方式1:通过中间件自动推断上下文\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * middleware: [authMiddleware],\n * handler: ({ user }) => { ... } // user 来自 authMiddleware\n * })\n *\n * // 方式2:显式声明上下文类型(用于父级中间件注入的场景)\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * context: {} as { userInfo: UserInfo },\n * handler: ({ userInfo }) => { ... } // userInfo 有类型\n * })\n * ```\n */\nexport function defineRoute<\n const TSchema extends RouteSchema,\n TReturn,\n const TMiddleware extends readonly AnyMiddleware[],\n TContext extends object = object,\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string\n>(config: {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n /** 显式声明上下文类型(用于父级中间件注入的场景) */\n readonly context?: TContext;\n readonly handler: (\n ctx: HandlerContextWithExtra<TSchema, TContext & MergeMiddlewareContexts<TMiddleware>>\n ) => TReturn | Promise<TReturn>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}): LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware>;\n\n/**\n * 定义嵌套路由(有 children),支持中间件类型推断\n */\nexport function defineRoute<\n const TMiddleware extends readonly AnyMiddleware[],\n TPath extends string = string\n>(config: {\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly middleware?: TMiddleware;\n readonly children: ReadonlyArray<RouteConfigResult>;\n}): NestedRouteConfig<TPath, TMiddleware>;\n\n/**\n * defineRoute 实现\n */\nexport function defineRoute(config: {\n readonly method?: HTTPMethod;\n readonly path: string;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: RouteSchema;\n readonly context?: object;\n readonly handler?: (ctx: HandlerContext<RouteSchema>) => unknown | Promise<unknown>;\n readonly middleware?: readonly AnyMiddleware[];\n readonly children?: ReadonlyArray<RouteConfigResult>;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}): RouteConfigResult {\n return config as RouteConfigResult;\n}\n\n// ============= withContext 工厂函数 =============\n\n/**\n * 创建带预设上下文类型的路由定义器\n *\n * 用于父级中间件注入上下文的场景,定义一次,多处复用\n *\n * @example\n * ```typescript\n * // 1. 在 middleware/index.ts 中定义\n * export const defineAuthRoute = withContext<{ userInfo: UserInfo }>()\n *\n * // 2. 在路由文件中使用\n * defineAuthRoute({\n * method: 'GET',\n * path: '/profile',\n * handler: ({ userInfo }) => {\n * // userInfo 自动有类型!\n * return { id: userInfo.id }\n * }\n * })\n * ```\n */\n/**\n * 带扩展类型的路由定义器\n *\n * @typeParam TContext - Handler 上下文类型(如 { userInfo: UserInfo })\n * @typeParam TExtensions - 路由扩展字段类型(如 { webhook?: boolean })\n *\n * @example\n * ```typescript\n * // 定义扩展类型\n * interface WebhookExtension {\n * webhook?: boolean | { eventKey?: string }\n * }\n *\n * // 使用扩展\n * const defineRoute = withContext<MyContext, WebhookExtension>()\n * defineRoute({\n * method: 'POST',\n * path: '/create',\n * webhook: true, // TypeScript 严格检查\n * handler: ...\n * })\n * ```\n */\nexport function withContext<\n TContext extends object,\n TExtensions extends object = object\n>() {\n return <\n const TSchema extends RouteSchema,\n TReturn,\n const TMiddleware extends readonly AnyMiddleware[],\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string\n >(config: {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n readonly handler: (\n ctx: HandlerContextWithExtra<TSchema, TContext & MergeMiddlewareContexts<TMiddleware>>\n ) => TReturn | Promise<TReturn>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n } & TExtensions): LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware> => {\n return config as unknown as LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware>;\n };\n}\n\n// ============= 扁平化嵌套路由 =============\n\n/** 父级路由信息 */\ninterface ParentRouteInfo {\n /** 父级路由路径 */\n path: string;\n /** 父级路由名称 */\n name?: string;\n /** 父级路由描述 */\n description?: string;\n}\n\n/**\n * 递归扁平化路由,合并路径和中间件\n */\nfunction flattenRoutes(\n routes: ReadonlyArray<RouteConfigResult>,\n parentPath: string = \"\",\n parentMiddleware: readonly AnyMiddleware[] = [],\n parent?: ParentRouteInfo\n): ProcessedRoute[] {\n const result: ProcessedRoute[] = [];\n\n for (const route of routes) {\n const fullPath = parentPath + route.path;\n const mergedMiddleware = [...parentMiddleware, ...(route.middleware || [])];\n\n if (isLeafRoute(route)) {\n // 检测 SSE handler(handler 上有 __sse 标记)\n const originalHandler = route.handler as unknown as { __sse?: { readonly __brand: 'SSE' } };\n const isSSE = originalHandler?.__sse?.__brand === 'SSE';\n \n // 基础属性\n const processed: ProcessedRoute = {\n method: route.method,\n path: fullPath,\n name: route.name,\n description: route.description,\n schema: route.schema,\n // SSE handler 不需要包装,它自己处理请求和响应\n handler: isSSE \n ? (route.handler as unknown as (req: Request) => Promise<Response>)\n : wrapHandler(route.schema, route.handler as (ctx: HandlerContext<RouteSchema>) => unknown),\n middleware: mergedMiddleware.length > 0 ? mergedMiddleware : undefined,\n docs: route.docs,\n };\n \n // 保留 SSE 标记到 handler 上,供契约生成使用\n if (isSSE) {\n (processed.handler as unknown as { __sse: { readonly __brand: 'SSE' } }).__sse = { __brand: 'SSE' };\n }\n \n // 添加父级路由信息\n if (parent) {\n processed.parent = parent;\n }\n // 复制扩展属性(如 webhook, permission 等)\n const knownKeys = ['method', 'path', 'name', 'description', 'schema', 'handler', 'middleware', 'docs'];\n for (const key of Object.keys(route)) {\n if (!knownKeys.includes(key)) {\n processed[key] = (route as unknown as Record<string, unknown>)[key];\n }\n }\n result.push(processed);\n } else if (isNestedRoute(route)) {\n // 传递当前路由信息作为子路由的 parent\n const currentParent: ParentRouteInfo = {\n path: fullPath,\n name: route.name,\n description: route.description,\n };\n result.push(...flattenRoutes(route.children, fullPath, mergedMiddleware, currentParent));\n }\n }\n\n return result;\n}\n\n// ============= defineRoutes 函数 =============\n\n/** 带原始类型信息的路由数组 */\nexport type RoutesWithSource<T extends readonly RouteConfigResult[]> = ProcessedRoute[] & { __source: T };\n\n/**\n * 定义路由数组,支持嵌套路由\n *\n * 使用 `const T` 泛型自动保留字面量类型,无需手动添加 `as const`\n *\n * @example\n * ```typescript\n * const routes = defineRoutes([\n * defineRoute({ method: 'GET', path: '/users', handler: ... }),\n * defineRoute({ method: 'POST', path: '/users', handler: ... }),\n * ])\n *\n * // 类型推断自动工作,无需 as const\n * type Api = InferEden<typeof routes>\n * ```\n */\nexport function defineRoutes<const T extends readonly RouteConfigResult[]>(\n routes: T\n): RoutesWithSource<T> {\n const processed = flattenRoutes(routes);\n // 附加原始类型信息(仅用于类型推断,运行时不使用)\n return Object.assign(processed, { __source: routes }) as RoutesWithSource<T>;\n}\n\n// ============= 用于 API Client 的类型推断 =============\n\n/** 可推断的路由类型(供 vafast-api-client 使用) */\nexport type InferableRoute<\n TMethod extends string = string,\n TPath extends string = string,\n TReturn = unknown,\n TSchema extends RouteSchema = RouteSchema\n> = {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n readonly handler: {\n __returnType: TReturn;\n __schema: TSchema;\n };\n readonly middleware?: ReadonlyArray<AnyMiddleware>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"defineRoute.mjs","names":[],"sources":["../src/defineRoute.ts"],"sourcesContent":["/**\n * 路由定义 - Schema 在路由级别定义,支持嵌套路由和中间件类型推断\n *\n * @example\n * ```typescript\n * // 定义带类型的中间件(函数式风格,通过 next 传递上下文)\n * const authMiddleware = defineMiddleware<{ user: User }>((req, next) => {\n * const user = getUser(req)\n * return next({ user }) // 通过 next 参数传递上下文\n * })\n *\n * // 路由自动推断中间件注入的类型\n * const routes = defineRoutes([\n * defineRoute({\n * path: '/api',\n * middleware: [authMiddleware],\n * children: [\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * handler: ({ user }) => ({ name: user.name }) // ✅ user 有类型\n * })\n * ]\n * })\n * ])\n * ```\n */\n\nimport type { TSchema, Static } from \"@sinclair/typebox\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./utils/parsers\";\nimport { validateAllSchemas, precompileSchemas } from \"./utils/validators/validators\";\nimport { json } from \"./utils/response\";\nimport { VafastError } from \"./middleware\";\n\n// ============= SSE 事件类型(内联定义,避免循环依赖) =============\n\n/** SSE 事件 */\nexport interface SSEEventType<T = unknown> {\n event?: string;\n data: T;\n id?: string;\n retry?: number;\n}\n\n/** SSE Generator 类型 */\nexport type SSEGeneratorType<TSchema extends RouteSchema = RouteSchema> = (\n ctx: HandlerContext<TSchema>\n) => AsyncGenerator<SSEEventType<unknown>, void, unknown>;\n\n// ============= Schema 类型 =============\n\n/** 路由 Schema 配置 */\nexport interface RouteSchema {\n body?: TSchema;\n query?: TSchema;\n params?: TSchema;\n headers?: TSchema;\n cookies?: TSchema;\n /** 响应类型 schema(用于类型同步,运行时不做校验) */\n response?: TSchema;\n}\n\n/** 从 Schema 推断类型 */\ntype InferSchemaType<T extends RouteSchema> = {\n body: T[\"body\"] extends TSchema ? Static<T[\"body\"]> : unknown;\n query: T[\"query\"] extends TSchema ? Static<T[\"query\"]> : Record<string, string>;\n params: T[\"params\"] extends TSchema ? Static<T[\"params\"]> : Record<string, string>;\n headers: T[\"headers\"] extends TSchema ? Static<T[\"headers\"]> : Record<string, string>;\n cookies: T[\"cookies\"] extends TSchema ? Static<T[\"cookies\"]> : Record<string, string>;\n};\n\n// ============= 中间件类型系统 =============\n\n/** 带类型标记的中间件 */\nexport interface TypedMiddleware<TContext extends object = object> {\n (req: Request, next: (ctx?: TContext) => Promise<Response>): Response | Promise<Response>;\n /** 类型标记(仅编译时使用) */\n __context?: TContext;\n}\n\n/** 普通中间件(无类型注入) */\ntype PlainMiddleware = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>;\n\n/** 任意中间件类型 */\ntype AnyMiddleware = TypedMiddleware<object> | PlainMiddleware;\n\n/** 从中间件提取上下文类型 */\ntype ExtractMiddlewareContext<T> = T extends TypedMiddleware<infer C> ? C : object;\n\n/** 合并中间件数组的上下文类型 */\ntype MergeMiddlewareContexts<T extends readonly unknown[]> =\n T extends readonly [infer First, ...infer Rest]\n ? ExtractMiddlewareContext<First> & MergeMiddlewareContexts<Rest>\n : object;\n\n// ============= Handler 上下文 =============\n\n/** Handler 上下文(包含 schema 推断) */\nexport interface HandlerContext<TSchema extends RouteSchema = RouteSchema> {\n req: Request;\n body: InferSchemaType<TSchema>[\"body\"];\n query: InferSchemaType<TSchema>[\"query\"];\n params: InferSchemaType<TSchema>[\"params\"];\n headers: InferSchemaType<TSchema>[\"headers\"];\n cookies: InferSchemaType<TSchema>[\"cookies\"];\n}\n\n/** Handler 上下文(带中间件注入的额外类型) */\ntype HandlerContextWithExtra<TSchema extends RouteSchema, TExtra> =\n HandlerContext<TSchema> & TExtra;\n\n// ============= 路由配置类型 =============\n\n/** HTTP 方法 */\ntype HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"OPTIONS\" | \"HEAD\";\n\n/** Handler 上下文类型(带中间件扩展) */\ntype HandlerCtx<TSchema extends RouteSchema, TMiddleware extends readonly AnyMiddleware[]> =\n HandlerContextWithExtra<TSchema, MergeMiddlewareContexts<TMiddleware>>;\n\n/** 普通 Handler 类型 */\ntype NormalHandler<TSchema extends RouteSchema, TReturn, TMiddleware extends readonly AnyMiddleware[]> = (\n ctx: HandlerCtx<TSchema, TMiddleware>\n) => TReturn | Promise<TReturn>;\n\n/** SSE Generator Handler 类型(直接写 async function*,无需 createSSEHandler 包装) */\ntype SSEHandler<TSchema extends RouteSchema, TMiddleware extends readonly AnyMiddleware[]> = (\n ctx: HandlerCtx<TSchema, TMiddleware>\n) => AsyncGenerator<SSEEventType<unknown>, void, unknown>;\n\n/** 叶子路由配置(有 method 和 handler) */\nexport interface LeafRouteConfig<\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string,\n TSchema extends RouteSchema = RouteSchema,\n TReturn = unknown,\n TMiddleware extends readonly AnyMiddleware[] = readonly AnyMiddleware[]\n> {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n /** \n * 是否为 SSE 端点(显式声明,推荐)\n * \n * 设置为 true 时,handler 应返回 AsyncGenerator:\n * ```typescript\n * sse: true,\n * handler: async function* (ctx) { yield { data: ... } }\n * ```\n */\n readonly sse?: boolean;\n /** \n * Handler 支持两种写法:\n * 1. 普通函数: `async (ctx) => { return result }`\n * 2. SSE Generator(需配合 sse: true): `async function* (ctx) { yield { data: ... } }`\n */\n readonly handler: NormalHandler<TSchema, TReturn, TMiddleware> | SSEHandler<TSchema, TMiddleware>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}\n\n/** 嵌套路由配置(有 children,无 method 和 handler) */\nexport interface NestedRouteConfig<\n TPath extends string = string,\n TMiddleware extends readonly AnyMiddleware[] = readonly AnyMiddleware[]\n> {\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly middleware?: TMiddleware;\n readonly children: ReadonlyArray<RouteConfigResult>;\n}\n\n/** defineRoute 返回的类型 */\ntype RouteConfigResult =\n | LeafRouteConfig<HTTPMethod, string, RouteSchema, unknown, readonly AnyMiddleware[]>\n | NestedRouteConfig<string, readonly AnyMiddleware[]>;\n\n/** 处理后的扁平路由 */\nexport interface ProcessedRoute {\n method: HTTPMethod;\n path: string;\n name?: string;\n description?: string;\n schema?: RouteSchema;\n /** 是否为 SSE 端点 */\n sse?: boolean;\n handler: (req: Request) => Promise<Response>;\n middleware?: readonly AnyMiddleware[];\n docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n /** 允许任意扩展(兼容 Route 类型) */\n [key: string]: unknown;\n}\n\n/** Route 类型别名(便于用户使用) */\nexport type Route = ProcessedRoute;\n\n// ============= defineMiddleware =============\n\n/**\n * 定义带类型的中间件(函数式风格)\n *\n * 通过 next() 参数传递上下文,更符合函数式编程风格\n *\n * @example\n * ```typescript\n * type AuthContext = { user: { id: string; name: string } }\n *\n * const authMiddleware = defineMiddleware<AuthContext>((req, next) => {\n * const user = getUserFromToken(req)\n * return next({ user }) // 通过 next 传递上下文\n * })\n * ```\n */\nexport function defineMiddleware<TContext extends object = object>(\n handler: (\n req: Request,\n next: (ctx?: TContext) => Promise<Response>\n ) => Promise<Response>\n): TypedMiddleware<TContext> {\n // 包装成标准中间件签名\n const middleware = ((req: Request, originalNext: () => Promise<Response>) => {\n // 包装 next,接收上下文参数并存储到 req.__locals\n const nextWithContext = (ctx?: TContext): Promise<Response> => {\n if (ctx) {\n const target = req as unknown as { __locals?: object };\n target.__locals = { ...(target.__locals || {}), ...ctx };\n }\n return originalNext();\n };\n return handler(req, nextWithContext);\n }) as TypedMiddleware<TContext>;\n\n return middleware;\n}\n\n// ============= 响应处理 =============\n\n/** 自动转换返回值为 Response */\nfunction autoResponse(result: unknown): Response {\n if (result instanceof Response) return result;\n if (result === null || result === undefined) return new Response(null, { status: 204 });\n if (typeof result === \"string\") {\n return new Response(result, { headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n if (typeof result === \"number\" || typeof result === \"boolean\") {\n return new Response(String(result), { headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n if (typeof result === \"object\") {\n const obj = result as Record<string, unknown>;\n if (\"data\" in obj && (\"status\" in obj || \"headers\" in obj)) {\n const { data, status = 200, headers = {} } = obj;\n if (data === null || data === undefined) {\n return new Response(null, { status: status === 200 ? 204 : (status as number), headers: headers as HeadersInit });\n }\n return json(data, status as number, headers as Record<string, string>);\n }\n return json(result);\n }\n return new Response(null, { status: 204 });\n}\n\n/**\n * 构建 HandlerContext(公共逻辑,供普通 handler 和 SSE handler 复用)\n */\nasync function buildHandlerContext<TSchema extends RouteSchema>(\n req: Request,\n schema: TSchema | undefined\n): Promise<HandlerContext<TSchema>> {\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 let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n try {\n body = await parseBody(req);\n } catch {\n // 忽略解析错误\n }\n }\n\n const data = { body, query, params, headers, cookies };\n if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) {\n validateAllSchemas(schema, data);\n }\n\n // 获取中间件注入的上下文\n const extraCtx = (req as unknown as { __locals?: unknown }).__locals || {};\n\n return {\n req,\n body: body as HandlerContext<TSchema>[\"body\"],\n query: query as HandlerContext<TSchema>[\"query\"],\n params: params as HandlerContext<TSchema>[\"params\"],\n headers: headers as HandlerContext<TSchema>[\"headers\"],\n cookies: cookies as HandlerContext<TSchema>[\"cookies\"],\n ...extraCtx,\n } as HandlerContext<TSchema>;\n}\n\n/** 创建包装后的 handler(普通路由) */\nfunction wrapHandler<TSchema extends RouteSchema>(\n schema: TSchema | undefined,\n userHandler: (ctx: HandlerContext<TSchema>) => unknown | Promise<unknown>\n): (req: Request) => Promise<Response> {\n if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\n const ctx = await buildHandlerContext(req, schema);\n const result = await userHandler(ctx);\n return autoResponse(result);\n } catch (error) {\n // 如果是 VafastError,重新抛出让错误处理中间件处理\n if (error instanceof VafastError) {\n throw error;\n }\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return json({ code: 400, message: error.message }, 400);\n }\n return json({ code: 500, message: error instanceof Error ? error.message : \"未知错误\" }, 500);\n }\n };\n}\n\n/**\n * SSE Handler 函数类型\n * \n * SSE handler 与普通 handler 使用统一的上下文模型,接收完整的 HandlerContext。\n * 框架自动完成:body 解析、schema 验证、中间件上下文注入。\n * SSE handler 只需关注流式响应逻辑,返回 SSE Stream Response。\n */\ntype SSEHandlerFn<TSchema extends RouteSchema = RouteSchema> = \n (ctx: HandlerContext<TSchema>) => Promise<Response>;\n\n/**\n * 格式化 SSE 事件为字符串(内联,避免循环依赖)\n */\nfunction formatSSEEvent(event: SSEEventType): string {\n const lines: string[] = [];\n if (event.id !== undefined) lines.push(`id: ${event.id}`);\n if (event.event !== undefined) lines.push(`event: ${event.event}`);\n if (event.retry !== undefined) lines.push(`retry: ${event.retry}`);\n \n const dataStr = typeof event.data === 'string' ? event.data : JSON.stringify(event.data);\n for (const line of dataStr.split('\\n')) {\n lines.push(`data: ${line}`);\n }\n return lines.join('\\n') + '\\n\\n';\n}\n\n/**\n * 将 AsyncGenerator 包装为 SSE Handler\n * \n * 支持用户直接写 `async function* (ctx) { yield ... }` 而无需 createSSEHandler\n */\nfunction wrapGeneratorToSSEHandler<TSchema extends RouteSchema>(\n generator: (ctx: HandlerContext<TSchema>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>\n): SSEHandlerFn<TSchema> {\n return async (ctx: HandlerContext<TSchema>): Promise<Response> => {\n const stream = new ReadableStream({\n async start(controller) {\n const encoder = new TextEncoder();\n try {\n for await (const event of generator(ctx)) {\n controller.enqueue(encoder.encode(formatSSEEvent(event)));\n }\n } catch (error) {\n const errorEvent = formatSSEEvent({\n event: 'error',\n data: { error: error instanceof Error ? error.message : '未知错误' }\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',\n }\n });\n };\n}\n\n/**\n * 创建 SSE handler 的请求包装器\n * \n * SSE handler 与普通 handler 使用相同的上下文构建流程(buildHandlerContext),\n * 确保:\n * - body/query/params 解析一致\n * - schema 验证统一\n * - 中间件注入的上下文(如 userInfo)自动可用\n * - 错误处理统一\n * \n * 唯一区别:SSE handler 返回的是 SSE Stream Response,而非普通 JSON Response\n */\nfunction wrapSSEHandler<TSchema extends RouteSchema>(\n schema: TSchema | undefined,\n sseHandler: SSEHandlerFn<TSchema>\n): (req: Request) => Promise<Response> {\n if (schema && (schema.body || schema.query || schema.params || schema.headers || schema.cookies)) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\n // 与普通 handler 使用相同的上下文构建逻辑\n const ctx = await buildHandlerContext(req, schema);\n // SSE handler 返回 SSE Stream Response\n return await sseHandler(ctx);\n } catch (error) {\n // 如果是 VafastError,重新抛出让错误处理中间件处理\n if (error instanceof VafastError) {\n throw error;\n }\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return json({ code: 400, message: error.message }, 400);\n }\n return json({ code: 500, message: error instanceof Error ? error.message : \"未知错误\" }, 500);\n }\n };\n}\n\n// ============= 判断路由类型 =============\n\n/** 判断是否为叶子路由 */\nfunction isLeafRoute(route: RouteConfigResult): route is LeafRouteConfig {\n return \"method\" in route && \"handler\" in route;\n}\n\n/** 判断是否为嵌套路由 */\nfunction isNestedRoute(route: RouteConfigResult): route is NestedRouteConfig {\n return \"children\" in route;\n}\n\n// ============= defineRoute 函数(支持重载) =============\n\n/**\n * 定义叶子路由(有 method 和 handler),支持中间件类型推断和显式上下文类型\n *\n * @example\n * ```typescript\n * // 方式1:通过中间件自动推断上下文\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * middleware: [authMiddleware],\n * handler: ({ user }) => { ... } // user 来自 authMiddleware\n * })\n *\n * // 方式2:显式声明上下文类型(用于父级中间件注入的场景)\n * defineRoute({\n * method: 'GET',\n * path: '/profile',\n * context: {} as { userInfo: UserInfo },\n * handler: ({ userInfo }) => { ... } // userInfo 有类型\n * })\n * ```\n */\nexport function defineRoute<\n const TSchema extends RouteSchema,\n TReturn,\n const TMiddleware extends readonly AnyMiddleware[],\n TContext extends object = object,\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string\n>(config: {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n /** 是否为 SSE 端点,设置为 true 时 handler 应返回 AsyncGenerator */\n readonly sse?: boolean;\n /** 显式声明上下文类型(用于父级中间件注入的场景) */\n readonly context?: TContext;\n readonly handler: (\n ctx: HandlerContextWithExtra<TSchema, TContext & MergeMiddlewareContexts<TMiddleware>>\n ) => TReturn | Promise<TReturn> | AsyncGenerator<SSEEventType<unknown>, void, unknown>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}): LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware>;\n\n/**\n * 定义嵌套路由(有 children),支持中间件类型推断\n */\nexport function defineRoute<\n const TMiddleware extends readonly AnyMiddleware[],\n TPath extends string = string\n>(config: {\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly middleware?: TMiddleware;\n readonly children: ReadonlyArray<RouteConfigResult>;\n}): NestedRouteConfig<TPath, TMiddleware>;\n\n/**\n * defineRoute 实现\n */\nexport function defineRoute(config: {\n readonly method?: HTTPMethod;\n readonly path: string;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: RouteSchema;\n readonly sse?: boolean;\n readonly context?: object;\n readonly handler?: (ctx: HandlerContext<RouteSchema>) => unknown | Promise<unknown> | AsyncGenerator<unknown, void, unknown>;\n readonly middleware?: readonly AnyMiddleware[];\n readonly children?: ReadonlyArray<RouteConfigResult>;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n}): RouteConfigResult {\n return config as RouteConfigResult;\n}\n\n// ============= withContext 工厂函数 =============\n\n/**\n * 创建带预设上下文类型的路由定义器\n *\n * 用于父级中间件注入上下文的场景,定义一次,多处复用\n *\n * @example\n * ```typescript\n * // 1. 在 middleware/index.ts 中定义\n * export const defineAuthRoute = withContext<{ userInfo: UserInfo }>()\n *\n * // 2. 在路由文件中使用\n * defineAuthRoute({\n * method: 'GET',\n * path: '/profile',\n * handler: ({ userInfo }) => {\n * // userInfo 自动有类型!\n * return { id: userInfo.id }\n * }\n * })\n * ```\n */\n/**\n * 带扩展类型的路由定义器\n *\n * @typeParam TContext - Handler 上下文类型(如 { userInfo: UserInfo })\n * @typeParam TExtensions - 路由扩展字段类型(如 { webhook?: boolean })\n *\n * @example\n * ```typescript\n * // 定义扩展类型\n * interface WebhookExtension {\n * webhook?: boolean | { eventKey?: string }\n * }\n *\n * // 使用扩展\n * const defineRoute = withContext<MyContext, WebhookExtension>()\n * defineRoute({\n * method: 'POST',\n * path: '/create',\n * webhook: true, // TypeScript 严格检查\n * handler: ...\n * })\n * ```\n */\n/** withContext Handler 上下文类型 */\ntype WithContextHandlerCtx<TSchema extends RouteSchema, TContext extends object, TMiddleware extends readonly AnyMiddleware[]> =\n HandlerContextWithExtra<TSchema, TContext & MergeMiddlewareContexts<TMiddleware>>;\n\n/** withContext 支持的 Handler 类型(普通函数 + SSE Generator) */\ntype WithContextHandler<TSchema extends RouteSchema, TContext extends object, TMiddleware extends readonly AnyMiddleware[], TReturn> =\n | ((ctx: WithContextHandlerCtx<TSchema, TContext, TMiddleware>) => TReturn | Promise<TReturn>)\n | ((ctx: WithContextHandlerCtx<TSchema, TContext, TMiddleware>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>);\n\nexport function withContext<\n TContext extends object,\n TExtensions extends object = object\n>() {\n return <\n const TSchema extends RouteSchema,\n TReturn,\n const TMiddleware extends readonly AnyMiddleware[],\n TMethod extends HTTPMethod = HTTPMethod,\n TPath extends string = string\n >(config: {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n /** \n * 是否为 SSE 端点\n * 设置为 true 时,handler 应返回 AsyncGenerator\n */\n readonly sse?: boolean;\n /** Handler 支持两种写法:普通函数 或 SSE Generator(需配合 sse: true) */\n readonly handler: WithContextHandler<TSchema, TContext, TMiddleware, TReturn>;\n readonly middleware?: TMiddleware;\n readonly docs?: {\n tags?: string[];\n security?: unknown[];\n responses?: Record<string, unknown>;\n };\n } & TExtensions): LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware> => {\n return config as unknown as LeafRouteConfig<TMethod, TPath, TSchema, TReturn, TMiddleware>;\n };\n}\n\n// ============= 扁平化嵌套路由 =============\n\n/** 父级路由信息 */\ninterface ParentRouteInfo {\n /** 父级路由路径 */\n path: string;\n /** 父级路由名称 */\n name?: string;\n /** 父级路由描述 */\n description?: string;\n}\n\n/**\n * 递归扁平化路由,合并路径和中间件\n */\nfunction flattenRoutes(\n routes: ReadonlyArray<RouteConfigResult>,\n parentPath: string = \"\",\n parentMiddleware: readonly AnyMiddleware[] = [],\n parent?: ParentRouteInfo\n): ProcessedRoute[] {\n const result: ProcessedRoute[] = [];\n\n for (const route of routes) {\n const fullPath = parentPath + route.path;\n const mergedMiddleware = [...parentMiddleware, ...(route.middleware || [])];\n\n if (isLeafRoute(route)) {\n // SSE 检测:只通过显式 sse: true 声明\n const routeWithSSE = route as typeof route & { sse?: boolean };\n const isSSE = routeWithSSE.sse === true;\n \n // 基础属性\n const processed: ProcessedRoute = {\n method: route.method,\n path: fullPath,\n name: route.name,\n description: route.description,\n schema: route.schema,\n sse: isSSE || undefined, // SSE 标记\n handler: isSSE \n ? wrapSSEHandler(route.schema, wrapGeneratorToSSEHandler(route.handler as (ctx: HandlerContext<RouteSchema>) => AsyncGenerator<SSEEventType<unknown>, void, unknown>))\n : wrapHandler(route.schema, route.handler as (ctx: HandlerContext<RouteSchema>) => unknown),\n middleware: mergedMiddleware.length > 0 ? mergedMiddleware : undefined,\n docs: route.docs,\n };\n \n // 添加父级路由信息\n if (parent) {\n processed.parent = parent;\n }\n // 复制扩展属性(如 webhook, permission 等)\n const knownKeys = ['method', 'path', 'name', 'description', 'schema', 'handler', 'middleware', 'docs'];\n for (const key of Object.keys(route)) {\n if (!knownKeys.includes(key)) {\n processed[key] = (route as unknown as Record<string, unknown>)[key];\n }\n }\n result.push(processed);\n } else if (isNestedRoute(route)) {\n // 传递当前路由信息作为子路由的 parent\n const currentParent: ParentRouteInfo = {\n path: fullPath,\n name: route.name,\n description: route.description,\n };\n result.push(...flattenRoutes(route.children, fullPath, mergedMiddleware, currentParent));\n }\n }\n\n return result;\n}\n\n// ============= defineRoutes 函数 =============\n\n/** 带原始类型信息的路由数组 */\nexport type RoutesWithSource<T extends readonly RouteConfigResult[]> = ProcessedRoute[] & { __source: T };\n\n/**\n * 定义路由数组,支持嵌套路由\n *\n * 使用 `const T` 泛型自动保留字面量类型,无需手动添加 `as const`\n *\n * @example\n * ```typescript\n * const routes = defineRoutes([\n * defineRoute({ method: 'GET', path: '/users', handler: ... }),\n * defineRoute({ method: 'POST', path: '/users', handler: ... }),\n * ])\n *\n * // 类型推断自动工作,无需 as const\n * type Api = InferEden<typeof routes>\n * ```\n */\nexport function defineRoutes<const T extends readonly RouteConfigResult[]>(\n routes: T\n): RoutesWithSource<T> {\n const processed = flattenRoutes(routes);\n // 附加原始类型信息(仅用于类型推断,运行时不使用)\n return Object.assign(processed, { __source: routes }) as RoutesWithSource<T>;\n}\n\n// ============= 用于 API Client 的类型推断 =============\n\n/** 可推断的路由类型(供 vafast-api-client 使用) */\nexport type InferableRoute<\n TMethod extends string = string,\n TPath extends string = string,\n TReturn = unknown,\n TSchema extends RouteSchema = RouteSchema\n> = {\n readonly method: TMethod;\n readonly path: TPath;\n readonly name?: string;\n readonly description?: string;\n readonly schema?: TSchema;\n readonly handler: {\n __returnType: TReturn;\n __schema: TSchema;\n };\n readonly middleware?: ReadonlyArray<AnyMiddleware>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgOA,SAAgB,iBACd,SAI2B;CAE3B,MAAM,eAAe,KAAc,iBAA0C;EAE3E,MAAM,mBAAmB,QAAsC;AAC7D,OAAI,KAAK;IACP,MAAM,SAAS;AACf,WAAO,WAAW;KAAE,GAAI,OAAO,YAAY,EAAE;KAAG,GAAG;KAAK;;AAE1D,UAAO,cAAc;;AAEvB,SAAO,QAAQ,KAAK,gBAAgB;;AAGtC,QAAO;;;AAMT,SAAS,aAAa,QAA2B;AAC/C,KAAI,kBAAkB,SAAU,QAAO;AACvC,KAAI,WAAW,QAAQ,WAAW,OAAW,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;AACvF,KAAI,OAAO,WAAW,SACpB,QAAO,IAAI,SAAS,QAAQ,EAAE,SAAS,EAAE,gBAAgB,6BAA6B,EAAE,CAAC;AAE3F,KAAI,OAAO,WAAW,YAAY,OAAO,WAAW,UAClD,QAAO,IAAI,SAAS,OAAO,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,6BAA6B,EAAE,CAAC;AAEnG,KAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,MAAM;AACZ,MAAI,UAAU,QAAQ,YAAY,OAAO,aAAa,MAAM;GAC1D,MAAM,EAAE,MAAM,SAAS,KAAK,UAAU,EAAE,KAAK;AAC7C,OAAI,SAAS,QAAQ,SAAS,OAC5B,QAAO,IAAI,SAAS,MAAM;IAAE,QAAQ,WAAW,MAAM,MAAO;IAA4B;IAAwB,CAAC;AAEnH,UAAO,KAAK,MAAM,QAAkB,QAAkC;;AAExE,SAAO,KAAK,OAAO;;AAErB,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;;;;AAM5C,eAAe,oBACb,KACA,QACkC;CAClC,MAAM,QAAQ,WAAW,IAAI;CAC7B,MAAM,UAAU,aAAa,IAAI;CACjC,MAAM,UAAU,aAAa,IAAI;CACjC,MAAM,SAAW,IAA2C,UAAqC,EAAE;CAEnG,IAAI,OAAgB;AACpB,KAAI,IAAI,WAAW,SAAS,IAAI,WAAW,OACzC,KAAI;AACF,SAAO,MAAM,UAAU,IAAI;SACrB;CAKV,MAAM,OAAO;EAAE;EAAM;EAAO;EAAQ;EAAS;EAAS;AACtD,KAAI,WAAW,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,SACtF,oBAAmB,QAAQ,KAAK;CAIlC,MAAM,WAAY,IAA0C,YAAY,EAAE;AAE1E,QAAO;EACL;EACM;EACC;EACC;EACC;EACA;EACT,GAAG;EACJ;;;AAIH,SAAS,YACP,QACA,aACqC;AACrC,KAAI,WAAW,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,SACtF,mBAAkB,OAAO;AAG3B,QAAO,OAAO,QAAoC;AAChD,MAAI;AAGF,UAAO,aADQ,MAAM,YADT,MAAM,oBAAoB,KAAK,OAAO,CACb,CACV;WACpB,OAAO;AAEd,OAAI,iBAAiB,YACnB,OAAM;AAER,OAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,OAAO,CAC1D,QAAO,KAAK;IAAE,MAAM;IAAK,SAAS,MAAM;IAAS,EAAE,IAAI;AAEzD,UAAO,KAAK;IAAE,MAAM;IAAK,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IAAQ,EAAE,IAAI;;;;;;;AAkB/F,SAAS,eAAe,OAA6B;CACnD,MAAM,QAAkB,EAAE;AAC1B,KAAI,MAAM,OAAO,OAAW,OAAM,KAAK,OAAO,MAAM,KAAK;AACzD,KAAI,MAAM,UAAU,OAAW,OAAM,KAAK,UAAU,MAAM,QAAQ;AAClE,KAAI,MAAM,UAAU,OAAW,OAAM,KAAK,UAAU,MAAM,QAAQ;CAElE,MAAM,UAAU,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK;AACxF,MAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,CACpC,OAAM,KAAK,SAAS,OAAO;AAE7B,QAAO,MAAM,KAAK,KAAK,GAAG;;;;;;;AAQ5B,SAAS,0BACP,WACuB;AACvB,QAAO,OAAO,QAAoD;EAChE,MAAM,SAAS,IAAI,eAAe,EAChC,MAAM,MAAM,YAAY;GACtB,MAAM,UAAU,IAAI,aAAa;AACjC,OAAI;AACF,eAAW,MAAM,SAAS,UAAU,IAAI,CACtC,YAAW,QAAQ,QAAQ,OAAO,eAAe,MAAM,CAAC,CAAC;YAEpD,OAAO;IACd,MAAM,aAAa,eAAe;KAChC,OAAO;KACP,MAAM,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,QAAQ;KACjE,CAAC;AACF,eAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;aACtC;AACR,eAAW,OAAO;;KAGvB,CAAC;AAEF,SAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS;GACP,gBAAgB;GAChB,iBAAiB;GACjB,cAAc;GACd,qBAAqB;GACtB,EACF,CAAC;;;;;;;;;;;;;;;AAgBN,SAAS,eACP,QACA,YACqC;AACrC,KAAI,WAAW,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,SACtF,mBAAkB,OAAO;AAG3B,QAAO,OAAO,QAAoC;AAChD,MAAI;AAIF,UAAO,MAAM,WAFD,MAAM,oBAAoB,KAAK,OAAO,CAEtB;WACrB,OAAO;AAEd,OAAI,iBAAiB,YACnB,OAAM;AAER,OAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,OAAO,CAC1D,QAAO,KAAK;IAAE,MAAM;IAAK,SAAS,MAAM;IAAS,EAAE,IAAI;AAEzD,UAAO,KAAK;IAAE,MAAM;IAAK,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IAAQ,EAAE,IAAI;;;;;AAQ/F,SAAS,YAAY,OAAoD;AACvE,QAAO,YAAY,SAAS,aAAa;;;AAI3C,SAAS,cAAc,OAAsD;AAC3E,QAAO,cAAc;;;;;AAwEvB,SAAgB,YAAY,QAgBN;AACpB,QAAO;;AA0DT,SAAgB,cAGZ;AACF,SAME,WAmBkF;AAClF,SAAO;;;;;;AAmBX,SAAS,cACP,QACA,aAAqB,IACrB,mBAA6C,EAAE,EAC/C,QACkB;CAClB,MAAM,SAA2B,EAAE;AAEnC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,WAAW,aAAa,MAAM;EACpC,MAAM,mBAAmB,CAAC,GAAG,kBAAkB,GAAI,MAAM,cAAc,EAAE,CAAE;AAE3E,MAAI,YAAY,MAAM,EAAE;GAGtB,MAAM,QADe,MACM,QAAQ;GAGnC,MAAM,YAA4B;IAChC,QAAQ,MAAM;IACd,MAAM;IACN,MAAM,MAAM;IACZ,aAAa,MAAM;IACnB,QAAQ,MAAM;IACd,KAAK,SAAS;IACd,SAAS,QACL,eAAe,MAAM,QAAQ,0BAA0B,MAAM,QAAsG,CAAC,GACpK,YAAY,MAAM,QAAQ,MAAM,QAAyD;IAC7F,YAAY,iBAAiB,SAAS,IAAI,mBAAmB;IAC7D,MAAM,MAAM;IACb;AAGD,OAAI,OACF,WAAU,SAAS;GAGrB,MAAM,YAAY;IAAC;IAAU;IAAQ;IAAQ;IAAe;IAAU;IAAW;IAAc;IAAO;AACtG,QAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,KAAI,CAAC,UAAU,SAAS,IAAI,CAC1B,WAAU,OAAQ,MAA6C;AAGnE,UAAO,KAAK,UAAU;aACb,cAAc,MAAM,EAAE;GAE/B,MAAM,gBAAiC;IACrC,MAAM;IACN,MAAM,MAAM;IACZ,aAAa,MAAM;IACpB;AACD,UAAO,KAAK,GAAG,cAAc,MAAM,UAAU,UAAU,kBAAkB,cAAc,CAAC;;;AAI5F,QAAO;;;;;;;;;;;;;;;;;;AAwBT,SAAgB,aACd,QACqB;CACrB,MAAM,YAAY,cAAc,OAAO;AAEvC,QAAO,OAAO,OAAO,WAAW,EAAE,UAAU,QAAQ,CAAC"}
@@ -24,4 +24,4 @@ declare class DependencyManager {
24
24
  }
25
25
  //#endregion
26
26
  export { DependencyManager as t };
27
- //# sourceMappingURL=dependency-manager-DIN9X0Gj.d.mts.map
27
+ //# sourceMappingURL=dependency-manager-mqzLAocb.d.mts.map
@@ -39,4 +39,4 @@ declare const Patterns: {
39
39
  };
40
40
  //#endregion
41
41
  export { registerFormats as i, hasFormat as n, registerFormat as r, Patterns as t };
42
- //# sourceMappingURL=formats-DDDSFWP0.d.mts.map
42
+ //# sourceMappingURL=formats-Ca7ASaYH.d.mts.map
@@ -27,4 +27,4 @@
27
27
  declare function goAwait<T>(promise: Promise<T>): Promise<[Error | null, T | undefined]>;
28
28
  //#endregion
29
29
  export { goAwait as t };
30
- //# sourceMappingURL=go-await-DPtVBug4.d.mts.map
30
+ //# sourceMappingURL=go-await-Dz1CRSTT.d.mts.map
@@ -19,4 +19,4 @@ declare class HtmlRenderer {
19
19
  }
20
20
  //#endregion
21
21
  export { HtmlRenderer as t };
22
- //# sourceMappingURL=html-renderer-DhQxRuyi.d.mts.map
22
+ //# sourceMappingURL=html-renderer-Up52eIS6.d.mts.map