vafast 0.3.11 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +168 -1
- package/dist/index.js.map +1 -1
- package/dist/monitoring/index.js +151 -1
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/native-monitor.js +151 -1
- package/dist/monitoring/native-monitor.js.map +1 -1
- package/dist/router/index.js +2 -1
- package/dist/router/index.js.map +1 -1
- package/dist/router.js +2 -1
- package/dist/router.js.map +1 -1
- package/dist/server/index.js +144 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/server-factory.js +144 -1
- package/dist/server/server-factory.js.map +1 -1
- package/dist/server/server.d.ts +15 -1
- package/dist/server/server.js +144 -1
- package/dist/server/server.js.map +1 -1
- package/dist/types/types.d.ts +12 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +146 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/route-registry.d.ts +195 -0
- package/dist/utils/route-registry.js +152 -0
- package/dist/utils/route-registry.js.map +1 -0
- package/package.json +1 -1
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/parsers.ts","../../src/utils/go-await.ts","../../src/utils/response.ts","../../src/utils/validators/validators.ts","../../src/utils/create-handler.ts","../../src/utils/base64url.ts","../../src/utils/handle.ts","../../src/utils/request-validator.ts","../../src/utils/html-renderer.ts","../../src/utils/dependency-manager.ts","../../src/utils/formats.ts","../../src/utils/sse.ts"],"sourcesContent":["// src/parsers.ts\nimport qs from \"qs\";\nimport cookie from \"cookie\";\n\n// 文件信息接口\nexport interface FileInfo {\n name: string;\n type: string;\n size: number;\n data: ArrayBuffer;\n}\n\n// 表单数据接口\nexport interface FormData {\n fields: Record<string, string>;\n files: Record<string, FileInfo>;\n}\n\n/**\n * 简化的请求体解析函数\n * 优先简洁性,处理最常见的场景\n */\nexport async function parseBody(req: Request): Promise<unknown> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n return await req.json();\n }\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const text = await req.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n return await req.text(); // fallback\n}\n\n/**\n * 解析 multipart/form-data 格式\n * 支持文件上传和普通表单字段\n */\nasync function parseMultipartFormData(req: Request): Promise<FormData> {\n const formData = await req.formData();\n const result: FormData = {\n fields: {},\n files: {},\n };\n\n for (const [key, value] of formData.entries()) {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n \"type\" in value &&\n \"size\" in value\n ) {\n // 处理文件\n const file = value as any;\n const arrayBuffer = await file.arrayBuffer();\n result.files[key] = {\n name: file.name,\n type: file.type,\n size: file.size,\n data: arrayBuffer,\n };\n } else {\n // 处理普通字段\n result.fields[key] = value as string;\n }\n }\n\n return result;\n}\n\n/**\n * 解析请求体为特定类型\n * 提供类型安全的解析方法\n */\nexport async function parseBodyAs<T>(req: Request): Promise<T> {\n const body = await parseBody(req);\n return body as T;\n}\n\n/**\n * 解析请求体为表单数据\n * 专门用于处理 multipart/form-data\n */\nexport async function parseFormData(req: Request): Promise<FormData> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n return await parseMultipartFormData(req);\n}\n\n/**\n * 解析请求体为文件\n * 专门用于处理文件上传\n */\nexport async function parseFile(req: Request): Promise<FileInfo> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n const formData = await parseMultipartFormData(req);\n const fileKeys = Object.keys(formData.files);\n\n if (fileKeys.length === 0) {\n throw new Error(\"请求中没有文件\");\n }\n\n if (fileKeys.length > 1) {\n throw new Error(\"请求中包含多个文件,请使用 parseFormData\");\n }\n\n return formData.files[fileKeys[0]];\n}\n\n/**\n * 快速提取 query string(避免创建 URL 对象)\n */\nfunction extractQueryString(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return \"\";\n\n const hashIndex = url.indexOf(\"#\", qIndex);\n return hashIndex === -1\n ? url.substring(qIndex + 1)\n : url.substring(qIndex + 1, hashIndex);\n}\n\n/** 获取查询字符串,直接返回对象 */\nexport function parseQuery(req: Request): Record<string, unknown> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n return qs.parse(queryString);\n}\n\n/**\n * 快速解析简单查询字符串(不支持嵌套,但更快)\n * 适用于简单的 key=value&key2=value2 场景\n */\nexport function parseQueryFast(req: Request): Record<string, string> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) {\n result[decodeURIComponent(pair)] = \"\";\n } else {\n const key = decodeURIComponent(pair.substring(0, eqIndex));\n const value = decodeURIComponent(pair.substring(eqIndex + 1));\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/** 解析请求头,返回对象 */\nexport function parseHeaders(req: Request): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n req.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return headers;\n}\n\n/**\n * 获取单个请求头(避免解析全部)\n */\nexport function getHeader(req: Request, name: string): string | null {\n return req.headers.get(name);\n}\n\n/** 使用cookie库解析Cookie,保证可靠性 */\nexport function parseCookies(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n try {\n const parsed = cookie.parse(cookieHeader);\n // 过滤掉undefined和null值\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n return result;\n } catch {\n return {};\n }\n}\n\n/**\n * 快速解析 Cookie(简化版,不使用外部库)\n * 适用于简单的 cookie 场景\n */\nexport function parseCookiesFast(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex > 0) {\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n // 移除引号\n result[key] =\n value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return result;\n}\n\n/**\n * 获取单个 Cookie 值(避免解析全部)\n */\nexport function getCookie(req: Request, name: string): string | null {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return null;\n\n const prefix = `${name}=`;\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n if (trimmed.startsWith(prefix)) {\n const value = trimmed.substring(prefix.length).trim();\n return value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return null;\n}\n","/**\n * Go 风格的错误处理工具\n * 将 Promise 转换为 [Error | null, T | undefined] 格式\n *\n * @author Framework Team\n * @version 1.0.0\n * @license MIT\n */\n\n/**\n * Go 风格的错误处理工具\n * 将 Promise 转换为 [Error | null, T | undefined] 格式\n *\n * @param promise 要处理的 Promise\n * @returns [Error | null, T | undefined] 元组,第一个元素是错误,第二个是结果\n *\n * @example\n * ```typescript\n * const [error, result] = await goAwait(someAsyncFunction());\n * if (error) {\n * console.error(\"操作失败:\", error);\n * } else {\n * console.log(\"操作成功:\", result);\n * }\n * ```\n */\nexport function goAwait<T>(\n promise: Promise<T>,\n): Promise<[Error | null, T | undefined]> {\n return promise\n .then<[null, T]>((data) => [null, data])\n .catch<\n [Error, undefined]\n >((err) => [err instanceof Error ? err : new Error(String(err)), undefined]);\n}\n","// src/response.ts\n\n/** 生成 JSON 响应 */\nexport function json(\n data: unknown,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const body = JSON.stringify(data);\n\n // 优化:只在有自定义 headers 时才创建 Headers 对象\n if (Object.keys(headers).length === 0) {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // 有自定义 headers 时才创建 Headers 对象\n const h = new Headers({\n \"Content-Type\": \"application/json\",\n ...headers,\n });\n\n return new Response(body, {\n status,\n headers: h,\n });\n}\n\n// JSON 响应的预创建 headers(避免每次创建)\nconst JSON_HEADERS = { \"Content-Type\": \"application/json\" };\nconst TEXT_HEADERS = { \"Content-Type\": \"text/plain\" };\n\n/**\n * 类型特化的响应映射\n * 根据返回值类型直接生成 Response,避免不必要的检查\n */\nexport function mapResponse(response: unknown): Response {\n // 快速路径:已经是 Response\n if (response instanceof Response) return response;\n\n // 使用 constructor.name 进行类型判断(比 instanceof 更快)\n switch (response?.constructor?.name) {\n case \"String\":\n return new Response(response as string, { headers: TEXT_HEADERS });\n\n case \"Object\":\n case \"Array\":\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n\n case \"Number\":\n case \"Boolean\":\n return new Response(String(response), { headers: TEXT_HEADERS });\n\n case undefined:\n // null 或 undefined\n return new Response(null, { status: 204 });\n\n case \"ReadableStream\":\n return new Response(response as ReadableStream);\n\n case \"Blob\":\n return new Response(response as Blob);\n\n case \"ArrayBuffer\":\n return new Response(response as ArrayBuffer);\n\n case \"Uint8Array\":\n return new Response(response as unknown as BodyInit);\n\n default:\n // Promise 处理\n if (response instanceof Promise) {\n return response.then(mapResponse) as unknown as Response;\n }\n // 其他情况使用 JSON 序列化\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n }\n}\n\n/** 生成重定向响应 */\nexport function redirect(location: string, status: 301 | 302 = 302): Response {\n return new Response(null, {\n status,\n headers: {\n Location: location,\n },\n });\n}\n\n/** 生成纯文本响应 */\nexport function text(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成HTML响应 */\nexport function html(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成空响应(204 No Content) */\nexport function empty(status = 204, headers: HeadersInit = {}): Response {\n return new Response(null, {\n status,\n headers,\n });\n}\n\n/** 生成流式响应 */\nexport function stream(\n stream: ReadableStream,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"application/octet-stream\",\n ...headers,\n });\n\n return new Response(stream, {\n status,\n headers: h,\n });\n}\n","/**\n * 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","/**\n * 类型安全的路由处理器工厂\n *\n * 非柯里化设计,API 更简洁\n *\n * @author Framework Team\n * @version 3.0.0\n * @license MIT\n */\n\nimport type {\n RouteSchema,\n HandlerContext,\n HandlerContextWithExtra,\n} from \"../types/schema\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { goAwait } from \"./go-await\";\nimport { json } from \"./response\";\nimport {\n validateAllSchemas,\n precompileSchemas,\n} from \"./validators/validators\";\n\n/**\n * 自动响应转换\n * 将各种返回值类型转换为 Response 对象\n */\nfunction autoResponse(result: unknown): Response {\n // 已经是 Response\n if (result instanceof Response) {\n return result;\n }\n\n // null/undefined -> 204\n if (result === null || result === undefined) {\n return new Response(null, { status: 204 });\n }\n\n // 字符串 -> text/plain\n if (typeof result === \"string\") {\n return new Response(result, {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 数字/布尔 -> text/plain\n if (typeof result === \"number\" || typeof result === \"boolean\") {\n return new Response(String(result), {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 对象 -> 检查是否是 { data, status, headers } 格式\n if (typeof result === \"object\") {\n const obj = result as Record<string, unknown>;\n if (\"data\" in obj && (\"status\" in obj || \"headers\" in obj)) {\n const { data, status = 200, headers = {} } = obj;\n\n if (data === null || data === undefined) {\n return new Response(null, {\n status: status === 200 ? 204 : (status as number),\n headers: headers as HeadersInit,\n });\n }\n\n if (\n typeof data === \"string\" ||\n typeof data === \"number\" ||\n typeof data === \"boolean\"\n ) {\n return new Response(String(data), {\n status: status as number,\n headers: {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...(headers as Record<string, string>),\n },\n });\n }\n\n return json(data, status as number, headers as Record<string, string>);\n }\n\n // 普通对象 -> JSON\n return json(result);\n }\n\n // 其他类型 -> 204\n return new Response(null, { status: 204 });\n}\n\n/**\n * 处理验证错误\n */\nfunction handleValidationError(error: Error): Response {\n return json(\n {\n success: false,\n error: \"Validation Error\",\n message: error.message,\n timestamp: new Date().toISOString(),\n },\n 400,\n );\n}\n\n/**\n * 处理内部错误\n */\nfunction handleInternalError(error: unknown): Response {\n return json(\n {\n success: false,\n error: \"Internal Error\",\n message: error instanceof Error ? error.message : \"未知错误\",\n },\n 500,\n );\n}\n\n/** 空 schema 的上下文类型 */\ntype EmptySchemaContext = {\n req: Request;\n body: unknown;\n query: Record<string, string>;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n};\n\n/**\n * 判断是否为 handler 函数\n */\nfunction isHandler(value: unknown): value is (...args: unknown[]) => unknown {\n return typeof value === \"function\";\n}\n\n/**\n * 创建类型安全的路由处理器\n *\n * @example\n * ```typescript\n * // 无 schema - 直接传入 handler\n * createHandler(({ params }) => `User: ${params.id}`)\n *\n * // 有 schema - 传入 schema 和 handler\n * createHandler(\n * { body: Type.Object({ name: Type.String() }) },\n * ({ body }) => ({ hello: body.name })\n * )\n * ```\n */\n/**\n * 带类型推断的 Handler - 保留返回类型信息用于客户端类型推断\n */\nexport type InferableHandler<TReturn, TSchema extends RouteSchema = RouteSchema> = ((req: Request) => Promise<Response>) & {\n /** 返回类型标记(仅用于类型推断,运行时不存在) */\n __returnType: TReturn;\n /** Schema 类型标记 */\n __schema: TSchema;\n};\n\n\n// 重载 1: 无 schema\nexport function createHandler<R>(\n handler: (ctx: EmptySchemaContext) => R | Promise<R>,\n): InferableHandler<R>;\n\n// 重载 2: 有 schema\nexport function createHandler<const T extends RouteSchema, R>(\n schema: T,\n handler: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T>;\n\n// 实现\nexport function createHandler<const T extends RouteSchema, R>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (ctx: HandlerContext<T>) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n const handlerFn = async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n });\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n\n // 类型断言:这些属性只在编译时用于类型推断,运行时不存在\n return handlerFn as InferableHandler<R, T>;\n}\n\n/**\n * 创建带额外上下文的路由处理器\n *\n * 用于中间件注入额外数据的场景\n *\n * @example\n * ```typescript\n * // 定义中间件注入的类型\n * type AuthContext = { user: { id: string; role: string } };\n *\n * // 无 schema\n * createHandlerWithExtra<AuthContext>(({ user }) => {\n * return { userId: user.id };\n * })\n *\n * // 有 schema\n * createHandlerWithExtra<AuthContext>(\n * { body: Type.Object({ action: Type.String() }) },\n * ({ body, user }) => ({ success: true, userId: user.id })\n * )\n * ```\n */\n// 重载 1: 无 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n R = unknown,\n>(\n handler: (ctx: EmptySchemaContext & TExtra) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 重载 2: 有 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schema: T,\n handler: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 实现\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext & TExtra) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (\n ctx: HandlerContextWithExtra<T, TExtra>,\n ) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 获取中间件注入的额外数据\n const extras = ((req as unknown as Record<string, unknown>).__locals ??\n {}) as TExtra;\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n ...extras,\n } as HandlerContextWithExtra<T, TExtra>);\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n}\n\n/**\n * 简单的路由处理器 (无 schema 验证,只有 req)\n *\n * @example\n * ```typescript\n * simpleHandler(({ req }) => {\n * return { message: \"Hello World\" };\n * })\n * ```\n */\nexport function simpleHandler<R>(\n handler: (ctx: { req: Request }) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n return async (req: Request): Promise<Response> => {\n try {\n const result = await handler({ req });\n return autoResponse(result);\n } catch (error) {\n return handleInternalError(error);\n }\n };\n}\n","export function base64urlEncode(str: string): string {\n return btoa(str)\n .replace(/=/g, \"\") // ✅ 删除填充\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\");\n}\n\nexport function base64urlDecode(str: string): string {\n const pad = str.length % 4 === 0 ? \"\" : \"=\".repeat(4 - (str.length % 4));\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\") + pad;\n return atob(base64);\n}\n","import { parseCookies } from \"./parsers\";\n\n/** 获取单个 Cookie 值 */\nexport function getCookie(req: Request, key: string): string | null {\n const cookies = parseCookies(req);\n return cookies[key] || null;\n}\n\n/** 生成 Set-Cookie 头 */\nexport function setCookie(\n key: string,\n value: string,\n options: {\n path?: string;\n httpOnly?: boolean;\n maxAge?: number;\n secure?: boolean;\n } = {},\n): string {\n let cookie = `${key}=${encodeURIComponent(value)}`;\n\n if (options.path) cookie += `; Path=${options.path}`;\n if (options.httpOnly) cookie += `; HttpOnly`;\n if (options.secure) cookie += `; Secure`;\n if (options.maxAge) cookie += `; Max-Age=${options.maxAge}`;\n\n return cookie;\n}\n\n// 提供给中间件写入\"局部上下文\"的工具函数\nexport function setLocals<T extends object>(req: Request, extras: T) {\n const target = req as unknown as Record<string, unknown>;\n target.__locals = { ...((target.__locals as object) ?? {}), ...extras };\n}\n\n// 获取中间件注入的局部上下文\nexport function getLocals<T extends object>(req: Request): T {\n const target = req as unknown as Record<string, unknown>;\n return (target.__locals ?? {}) as T;\n}\n","/**\n * 请求解析和验证器\n *\n * 解析handler的req参数,使用Ultra验证器进行验证,\n * 并类型安全地返回解析出来的值\n *\n * @author Framework Team\n * @version 1.0.0\n * @license MIT\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { Static } from \"@sinclair/typebox\";\nimport {\n validateAllSchemas,\n type SchemaConfig,\n} from \"./validators/validators\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\n\n// 请求数据结构\nexport interface RequestData {\n body: unknown;\n query: unknown;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}\n\n// 验证后的请求数据类型\nexport interface ValidatedRequestData<T extends SchemaConfig> {\n body: T[\"body\"] extends TSchema ? Static<T[\"body\"]> : unknown;\n query: T[\"query\"] extends TSchema ? Static<T[\"query\"]> : unknown;\n params: T[\"params\"] extends TSchema\n ? Static<T[\"params\"]>\n : Record<string, string>;\n headers: T[\"headers\"] extends TSchema\n ? Static<T[\"headers\"]>\n : Record<string, string>;\n cookies: T[\"cookies\"] extends TSchema\n ? Static<T[\"cookies\"]>\n : Record<string, string>;\n}\n\n// 验证结果\nexport interface ValidationResult<T extends SchemaConfig> {\n success: boolean;\n data?: ValidatedRequestData<T>;\n errors?: Array<{ field: keyof SchemaConfig; message: string }>;\n}\n\n/**\n * 解析Request对象,提取所有相关数据\n * @param request Request对象\n * @param params 路径参数(可选)\n * @returns 解析后的请求数据\n */\nexport async function parseRequest(\n request: Request,\n params?: Record<string, string>,\n): Promise<RequestData> {\n const requestData: RequestData = {\n body: undefined,\n query: parseQuery(request),\n params: params || {},\n headers: parseHeaders(request),\n cookies: parseCookies(request),\n };\n\n // 对于非GET请求,尝试解析请求体\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n requestData.body = await parseBody(request);\n }\n\n return requestData;\n}\n\n/**\n * 验证请求数据\n * @param config Schema配置\n * @param requestData 请求数据\n * @returns 验证结果\n */\nexport function validateRequest<T extends SchemaConfig>(\n config: T,\n requestData: RequestData,\n): ValidationResult<T> {\n try {\n const validatedData = validateAllSchemas(config, requestData);\n\n return {\n success: true,\n data: validatedData as ValidatedRequestData<T>,\n };\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"验证失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 完整的请求解析和验证流程\n * @param request Request对象\n * @param config Schema配置\n * @param params 路径参数(可选)\n * @returns 验证结果\n */\nexport async function parseAndValidateRequest<T extends SchemaConfig>(\n request: Request,\n config: T,\n params?: Record<string, string>,\n): Promise<ValidationResult<T>> {\n try {\n // 1. 解析请求\n const requestData = await parseRequest(request, params);\n\n // 2. 验证数据\n return validateRequest(config, requestData);\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"请求解析失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 创建类型安全的请求验证器工厂\n * @param config Schema配置\n * @returns 验证器函数\n */\nexport function createRequestValidator<T extends SchemaConfig>(config: T) {\n return async (request: Request, params?: Record<string, string>) => {\n return parseAndValidateRequest(request, config, params);\n };\n}\n","/**\n * HTML渲染工具类\n * 提供统一的HTML模板生成功能\n */\nexport class HtmlRenderer {\n /**\n * 生成基础HTML模板\n */\n static generateBaseHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return `\n <!doctype html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>Vafast SSR App</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n <body>\n <div id=\"app\">${content}</div>\n <script>\n window.__ROUTE_INFO__ = {\n params: ${JSON.stringify(context.params || {})},\n query: ${JSON.stringify(context.query || {})},\n pathname: '${context.pathname}'\n };\n </script>\n <script type=\"module\" src=\"${clientScriptPath}\"></script>\n </body>\n </html>\n `;\n }\n\n /**\n * 生成Vue组件HTML\n */\n static generateVueHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return this.generateBaseHtml(content, context, clientScriptPath);\n }\n\n /**\n * 生成React组件HTML\n */\n static generateReactHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return `\n <!doctype html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>Vafast SSR App</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n <body>\n <div id=\"root\">${content}</div>\n <script>\n window.__ROUTE_INFO__ = {\n params: ${JSON.stringify(context.params || {})},\n query: ${JSON.stringify(context.query || {})},\n pathname: '${context.pathname}'\n };\n </script>\n <script type=\"module\" src=\"${clientScriptPath}\"></script>\n </body>\n </html>\n `;\n }\n}\n","/**\n * 依赖管理器\n * 负责按需加载和管理框架依赖\n */\nexport class DependencyManager {\n private dependencyCache = new Map<string, any>();\n\n /**\n * 按需获取框架依赖\n */\n async getFrameworkDeps(framework: \"vue\" | \"react\") {\n if (this.dependencyCache.has(framework)) {\n return this.dependencyCache.get(framework);\n }\n\n console.log(`📦 按需加载 ${framework} 依赖...`);\n\n try {\n let deps;\n switch (framework) {\n case \"vue\":\n deps = await Promise.all([\n import(\"vue\"),\n import(\"@vue/server-renderer\"),\n ]);\n break;\n case \"react\":\n deps = await Promise.all([\n import(\"react\"),\n import(\"react-dom/server\"),\n ]);\n break;\n default:\n throw new Error(`不支持的框架: ${framework}`);\n }\n\n this.dependencyCache.set(framework, deps);\n console.log(`✅ ${framework} 依赖加载完成`);\n return deps;\n } catch (error) {\n console.error(`❌ ${framework} 依赖加载失败:`, error);\n throw error;\n }\n }\n\n /**\n * 检测组件类型\n */\n detectComponentType(component: any): \"vue\" | \"react\" {\n // 简单的组件类型检测\n if (component.render && typeof component.render === \"function\") {\n return \"vue\";\n }\n if (component.$$typeof) {\n return \"react\";\n }\n // 默认使用 Vue\n return \"vue\";\n }\n\n /**\n * 清除缓存\n */\n clearCache(): void {\n this.dependencyCache.clear();\n console.log(\"🧹 依赖缓存已清除\");\n }\n\n /**\n * 获取缓存状态\n */\n getCacheStatus(): Record<string, boolean> {\n const status: Record<string, boolean> = {};\n for (const [framework] of this.dependencyCache) {\n status[framework] = true;\n }\n return status;\n }\n}\n","/**\n * TypeBox Format 验证器\n *\n * 内置常用的 format 验证,对标 Zod 的内置验证\n * 框架启动时自动注册\n *\n * @version 1.0.0\n */\n\nimport { FormatRegistry } from \"@sinclair/typebox\";\n\n// ============== 正则表达式 ==============\n\n// 邮箱 (RFC 5322 简化版)\nconst EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n// UUID v4\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n// UUID 任意版本\nconst UUID_ANY_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// CUID\nconst CUID_REGEX = /^c[^\\s-]{8,}$/i;\n\n// CUID2\nconst CUID2_REGEX = /^[0-9a-z]+$/;\n\n// ULID\nconst ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/i;\n\n// NanoID (默认 21 字符)\nconst NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/;\n\n// URL\nconst URL_REGEX = /^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$/;\n\n// IPv4\nconst IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n// IPv6 (简化版)\nconst IPV6_REGEX = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$/;\n\n// CIDR (IPv4)\nconst CIDR_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(?:3[0-2]|[12]?[0-9])$/;\n\n// 日期 (YYYY-MM-DD)\nconst DATE_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/;\n\n// 时间 (HH:mm:ss 或 HH:mm:ss.SSS)\nconst TIME_REGEX = /^(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?$/;\n\n// ISO 日期时间\nconst DATE_TIME_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?(?:Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])?$/;\n\n// ISO 8601 Duration (P1Y2M3DT4H5M6S)\nconst DURATION_REGEX = /^P(?:\\d+Y)?(?:\\d+M)?(?:\\d+W)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?$/;\n\n// Hostname (RFC 1123)\nconst HOSTNAME_REGEX = /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)*(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;\n\n// 手机号 (中国大陆)\nconst PHONE_CN_REGEX = /^1[3-9]\\d{9}$/;\n\n// 手机号 (国际格式 E.164)\nconst PHONE_E164_REGEX = /^\\+[1-9]\\d{6,14}$/;\n\n// MongoDB ObjectId\nconst OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/;\n\n// 十六进制颜色\nconst HEX_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n\n// RGB/RGBA 颜色\nconst RGB_COLOR_REGEX = /^rgba?\\(\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\\s*,\\s*(?:0|1|0?\\.\\d+))?\\s*\\)$/;\n\n// Base64\nconst BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n// Base64 URL Safe\nconst BASE64URL_REGEX = /^[A-Za-z0-9_-]+$/;\n\n// JWT (3 部分 base64url)\nconst JWT_REGEX = /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\n\n// Emoji (简化检测)\nconst EMOJI_REGEX = /^[\\p{Emoji}]+$/u;\n\n// Slug (URL 友好字符串)\nconst SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n// Semver (语义化版本)\nconst SEMVER_REGEX = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n// 信用卡号 (Luhn 算法验证)\nfunction isValidCreditCard(value: string): boolean {\n const digits = value.replace(/\\D/g, \"\");\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let isEven = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let digit = parseInt(digits[i], 10);\n if (isEven) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n isEven = !isEven;\n }\n return sum % 10 === 0;\n}\n\n// ============== Format 注册 ==============\n\nlet isRegistered = false;\n\n/**\n * 注册所有内置 format 验证器\n * 框架自动调用,也可手动调用\n */\nexport function registerFormats(): void {\n if (isRegistered) return;\n isRegistered = true;\n\n // === 字符串标识符 ===\n FormatRegistry.Set(\"email\", (v) => EMAIL_REGEX.test(v));\n FormatRegistry.Set(\"uuid\", (v) => UUID_REGEX.test(v));\n FormatRegistry.Set(\"uuid-any\", (v) => UUID_ANY_REGEX.test(v));\n FormatRegistry.Set(\"cuid\", (v) => CUID_REGEX.test(v));\n FormatRegistry.Set(\"cuid2\", (v) => CUID2_REGEX.test(v) && v.length >= 1);\n FormatRegistry.Set(\"ulid\", (v) => ULID_REGEX.test(v));\n FormatRegistry.Set(\"nanoid\", (v) => NANOID_REGEX.test(v));\n FormatRegistry.Set(\"objectid\", (v) => OBJECTID_REGEX.test(v));\n FormatRegistry.Set(\"slug\", (v) => SLUG_REGEX.test(v));\n\n // === 网络相关 ===\n FormatRegistry.Set(\"url\", (v) => URL_REGEX.test(v));\n FormatRegistry.Set(\"uri\", (v) => URL_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"ipv4\", (v) => IPV4_REGEX.test(v));\n FormatRegistry.Set(\"ipv6\", (v) => IPV6_REGEX.test(v));\n FormatRegistry.Set(\"ip\", (v) => IPV4_REGEX.test(v) || IPV6_REGEX.test(v));\n FormatRegistry.Set(\"cidr\", (v) => CIDR_REGEX.test(v));\n FormatRegistry.Set(\"hostname\", (v) => HOSTNAME_REGEX.test(v));\n\n // === 日期时间 ===\n FormatRegistry.Set(\"date\", (v) => DATE_REGEX.test(v));\n FormatRegistry.Set(\"time\", (v) => TIME_REGEX.test(v));\n FormatRegistry.Set(\"date-time\", (v) => DATE_TIME_REGEX.test(v));\n FormatRegistry.Set(\"datetime\", (v) => DATE_TIME_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"duration\", (v) => DURATION_REGEX.test(v));\n\n // === 手机号 ===\n FormatRegistry.Set(\"phone\", (v) => PHONE_CN_REGEX.test(v)); // 中国大陆\n FormatRegistry.Set(\"phone-cn\", (v) => PHONE_CN_REGEX.test(v));\n FormatRegistry.Set(\"phone-e164\", (v) => PHONE_E164_REGEX.test(v)); // 国际\n\n // === 编码格式 ===\n FormatRegistry.Set(\"base64\", (v) => BASE64_REGEX.test(v));\n FormatRegistry.Set(\"base64url\", (v) => BASE64URL_REGEX.test(v));\n FormatRegistry.Set(\"jwt\", (v) => JWT_REGEX.test(v));\n\n // === 颜色 ===\n FormatRegistry.Set(\"hex-color\", (v) => HEX_COLOR_REGEX.test(v));\n FormatRegistry.Set(\"rgb-color\", (v) => RGB_COLOR_REGEX.test(v));\n FormatRegistry.Set(\n \"color\",\n (v) => HEX_COLOR_REGEX.test(v) || RGB_COLOR_REGEX.test(v),\n );\n\n // === 其他 ===\n FormatRegistry.Set(\"emoji\", (v) => EMOJI_REGEX.test(v));\n FormatRegistry.Set(\"semver\", (v) => SEMVER_REGEX.test(v));\n FormatRegistry.Set(\"credit-card\", isValidCreditCard);\n}\n\n/**\n * 自定义注册 format\n */\nexport function registerFormat(\n name: string,\n validator: (value: string) => boolean,\n): void {\n FormatRegistry.Set(name, validator);\n}\n\n/**\n * 检查 format 是否已注册\n */\nexport function hasFormat(name: string): boolean {\n return FormatRegistry.Has(name);\n}\n\n// 导出正则(供外部使用)\nexport const Patterns = {\n EMAIL: EMAIL_REGEX,\n UUID: UUID_REGEX,\n URL: URL_REGEX,\n IPV4: IPV4_REGEX,\n IPV6: IPV6_REGEX,\n DATE: DATE_REGEX,\n TIME: TIME_REGEX,\n DATE_TIME: DATE_TIME_REGEX,\n PHONE_CN: PHONE_CN_REGEX,\n PHONE_E164: PHONE_E164_REGEX,\n OBJECTID: OBJECTID_REGEX,\n HEX_COLOR: HEX_COLOR_REGEX,\n SLUG: SLUG_REGEX,\n SEMVER: SEMVER_REGEX,\n JWT: JWT_REGEX,\n} as const;\n\n","/**\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":"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","names":["text","stream","stream"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/parsers.ts","../../src/utils/go-await.ts","../../src/utils/response.ts","../../src/utils/validators/validators.ts","../../src/utils/create-handler.ts","../../src/utils/base64url.ts","../../src/utils/handle.ts","../../src/utils/request-validator.ts","../../src/utils/html-renderer.ts","../../src/utils/dependency-manager.ts","../../src/utils/formats.ts","../../src/utils/sse.ts","../../src/utils/route-registry.ts"],"sourcesContent":["// src/parsers.ts\nimport qs from \"qs\";\nimport cookie from \"cookie\";\n\n// 文件信息接口\nexport interface FileInfo {\n name: string;\n type: string;\n size: number;\n data: ArrayBuffer;\n}\n\n// 表单数据接口\nexport interface FormData {\n fields: Record<string, string>;\n files: Record<string, FileInfo>;\n}\n\n/**\n * 简化的请求体解析函数\n * 优先简洁性,处理最常见的场景\n */\nexport async function parseBody(req: Request): Promise<unknown> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n return await req.json();\n }\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const text = await req.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n return await req.text(); // fallback\n}\n\n/**\n * 解析 multipart/form-data 格式\n * 支持文件上传和普通表单字段\n */\nasync function parseMultipartFormData(req: Request): Promise<FormData> {\n const formData = await req.formData();\n const result: FormData = {\n fields: {},\n files: {},\n };\n\n for (const [key, value] of formData.entries()) {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n \"type\" in value &&\n \"size\" in value\n ) {\n // 处理文件\n const file = value as any;\n const arrayBuffer = await file.arrayBuffer();\n result.files[key] = {\n name: file.name,\n type: file.type,\n size: file.size,\n data: arrayBuffer,\n };\n } else {\n // 处理普通字段\n result.fields[key] = value as string;\n }\n }\n\n return result;\n}\n\n/**\n * 解析请求体为特定类型\n * 提供类型安全的解析方法\n */\nexport async function parseBodyAs<T>(req: Request): Promise<T> {\n const body = await parseBody(req);\n return body as T;\n}\n\n/**\n * 解析请求体为表单数据\n * 专门用于处理 multipart/form-data\n */\nexport async function parseFormData(req: Request): Promise<FormData> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n return await parseMultipartFormData(req);\n}\n\n/**\n * 解析请求体为文件\n * 专门用于处理文件上传\n */\nexport async function parseFile(req: Request): Promise<FileInfo> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (!contentType.includes(\"multipart/form-data\")) {\n throw new Error(\"请求不是 multipart/form-data 格式\");\n }\n\n const formData = await parseMultipartFormData(req);\n const fileKeys = Object.keys(formData.files);\n\n if (fileKeys.length === 0) {\n throw new Error(\"请求中没有文件\");\n }\n\n if (fileKeys.length > 1) {\n throw new Error(\"请求中包含多个文件,请使用 parseFormData\");\n }\n\n return formData.files[fileKeys[0]];\n}\n\n/**\n * 快速提取 query string(避免创建 URL 对象)\n */\nfunction extractQueryString(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return \"\";\n\n const hashIndex = url.indexOf(\"#\", qIndex);\n return hashIndex === -1\n ? url.substring(qIndex + 1)\n : url.substring(qIndex + 1, hashIndex);\n}\n\n/** 获取查询字符串,直接返回对象 */\nexport function parseQuery(req: Request): Record<string, unknown> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n return qs.parse(queryString);\n}\n\n/**\n * 快速解析简单查询字符串(不支持嵌套,但更快)\n * 适用于简单的 key=value&key2=value2 场景\n */\nexport function parseQueryFast(req: Request): Record<string, string> {\n const queryString = extractQueryString(req.url);\n if (!queryString) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) {\n result[decodeURIComponent(pair)] = \"\";\n } else {\n const key = decodeURIComponent(pair.substring(0, eqIndex));\n const value = decodeURIComponent(pair.substring(eqIndex + 1));\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/** 解析请求头,返回对象 */\nexport function parseHeaders(req: Request): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n req.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return headers;\n}\n\n/**\n * 获取单个请求头(避免解析全部)\n */\nexport function getHeader(req: Request, name: string): string | null {\n return req.headers.get(name);\n}\n\n/** 使用cookie库解析Cookie,保证可靠性 */\nexport function parseCookies(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n try {\n const parsed = cookie.parse(cookieHeader);\n // 过滤掉undefined和null值\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n return result;\n } catch {\n return {};\n }\n}\n\n/**\n * 快速解析 Cookie(简化版,不使用外部库)\n * 适用于简单的 cookie 场景\n */\nexport function parseCookiesFast(req: Request): Record<string, string> {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return {};\n\n const result: Record<string, string> = Object.create(null);\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex > 0) {\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n // 移除引号\n result[key] =\n value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return result;\n}\n\n/**\n * 获取单个 Cookie 值(避免解析全部)\n */\nexport function getCookie(req: Request, name: string): string | null {\n const cookieHeader = req.headers.get(\"cookie\");\n if (!cookieHeader) return null;\n\n const prefix = `${name}=`;\n const pairs = cookieHeader.split(\";\");\n\n for (const pair of pairs) {\n const trimmed = pair.trim();\n if (trimmed.startsWith(prefix)) {\n const value = trimmed.substring(prefix.length).trim();\n return value.startsWith('\"') && value.endsWith('\"')\n ? value.slice(1, -1)\n : value;\n }\n }\n\n return null;\n}\n","/**\n * Go 风格的错误处理工具\n * 将 Promise 转换为 [Error | null, T | undefined] 格式\n *\n * @author Framework Team\n * @version 1.0.0\n * @license MIT\n */\n\n/**\n * Go 风格的错误处理工具\n * 将 Promise 转换为 [Error | null, T | undefined] 格式\n *\n * @param promise 要处理的 Promise\n * @returns [Error | null, T | undefined] 元组,第一个元素是错误,第二个是结果\n *\n * @example\n * ```typescript\n * const [error, result] = await goAwait(someAsyncFunction());\n * if (error) {\n * console.error(\"操作失败:\", error);\n * } else {\n * console.log(\"操作成功:\", result);\n * }\n * ```\n */\nexport function goAwait<T>(\n promise: Promise<T>,\n): Promise<[Error | null, T | undefined]> {\n return promise\n .then<[null, T]>((data) => [null, data])\n .catch<\n [Error, undefined]\n >((err) => [err instanceof Error ? err : new Error(String(err)), undefined]);\n}\n","// src/response.ts\n\n/** 生成 JSON 响应 */\nexport function json(\n data: unknown,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const body = JSON.stringify(data);\n\n // 优化:只在有自定义 headers 时才创建 Headers 对象\n if (Object.keys(headers).length === 0) {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // 有自定义 headers 时才创建 Headers 对象\n const h = new Headers({\n \"Content-Type\": \"application/json\",\n ...headers,\n });\n\n return new Response(body, {\n status,\n headers: h,\n });\n}\n\n// JSON 响应的预创建 headers(避免每次创建)\nconst JSON_HEADERS = { \"Content-Type\": \"application/json\" };\nconst TEXT_HEADERS = { \"Content-Type\": \"text/plain\" };\n\n/**\n * 类型特化的响应映射\n * 根据返回值类型直接生成 Response,避免不必要的检查\n */\nexport function mapResponse(response: unknown): Response {\n // 快速路径:已经是 Response\n if (response instanceof Response) return response;\n\n // 使用 constructor.name 进行类型判断(比 instanceof 更快)\n switch (response?.constructor?.name) {\n case \"String\":\n return new Response(response as string, { headers: TEXT_HEADERS });\n\n case \"Object\":\n case \"Array\":\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n\n case \"Number\":\n case \"Boolean\":\n return new Response(String(response), { headers: TEXT_HEADERS });\n\n case undefined:\n // null 或 undefined\n return new Response(null, { status: 204 });\n\n case \"ReadableStream\":\n return new Response(response as ReadableStream);\n\n case \"Blob\":\n return new Response(response as Blob);\n\n case \"ArrayBuffer\":\n return new Response(response as ArrayBuffer);\n\n case \"Uint8Array\":\n return new Response(response as unknown as BodyInit);\n\n default:\n // Promise 处理\n if (response instanceof Promise) {\n return response.then(mapResponse) as unknown as Response;\n }\n // 其他情况使用 JSON 序列化\n return new Response(JSON.stringify(response), { headers: JSON_HEADERS });\n }\n}\n\n/** 生成重定向响应 */\nexport function redirect(location: string, status: 301 | 302 = 302): Response {\n return new Response(null, {\n status,\n headers: {\n Location: location,\n },\n });\n}\n\n/** 生成纯文本响应 */\nexport function text(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成HTML响应 */\nexport function html(\n content: string,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n ...headers,\n });\n\n return new Response(content, {\n status,\n headers: h,\n });\n}\n\n/** 生成空响应(204 No Content) */\nexport function empty(status = 204, headers: HeadersInit = {}): Response {\n return new Response(null, {\n status,\n headers,\n });\n}\n\n/** 生成流式响应 */\nexport function stream(\n stream: ReadableStream,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n const h = new Headers({\n \"Content-Type\": \"application/octet-stream\",\n ...headers,\n });\n\n return new Response(stream, {\n status,\n headers: h,\n });\n}\n","/**\n * 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","/**\n * 类型安全的路由处理器工厂\n *\n * 非柯里化设计,API 更简洁\n *\n * @author Framework Team\n * @version 3.0.0\n * @license MIT\n */\n\nimport type {\n RouteSchema,\n HandlerContext,\n HandlerContextWithExtra,\n} from \"../types/schema\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { goAwait } from \"./go-await\";\nimport { json } from \"./response\";\nimport {\n validateAllSchemas,\n precompileSchemas,\n} from \"./validators/validators\";\n\n/**\n * 自动响应转换\n * 将各种返回值类型转换为 Response 对象\n */\nfunction autoResponse(result: unknown): Response {\n // 已经是 Response\n if (result instanceof Response) {\n return result;\n }\n\n // null/undefined -> 204\n if (result === null || result === undefined) {\n return new Response(null, { status: 204 });\n }\n\n // 字符串 -> text/plain\n if (typeof result === \"string\") {\n return new Response(result, {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 数字/布尔 -> text/plain\n if (typeof result === \"number\" || typeof result === \"boolean\") {\n return new Response(String(result), {\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n }\n\n // 对象 -> 检查是否是 { data, status, headers } 格式\n if (typeof result === \"object\") {\n const obj = result as Record<string, unknown>;\n if (\"data\" in obj && (\"status\" in obj || \"headers\" in obj)) {\n const { data, status = 200, headers = {} } = obj;\n\n if (data === null || data === undefined) {\n return new Response(null, {\n status: status === 200 ? 204 : (status as number),\n headers: headers as HeadersInit,\n });\n }\n\n if (\n typeof data === \"string\" ||\n typeof data === \"number\" ||\n typeof data === \"boolean\"\n ) {\n return new Response(String(data), {\n status: status as number,\n headers: {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n ...(headers as Record<string, string>),\n },\n });\n }\n\n return json(data, status as number, headers as Record<string, string>);\n }\n\n // 普通对象 -> JSON\n return json(result);\n }\n\n // 其他类型 -> 204\n return new Response(null, { status: 204 });\n}\n\n/**\n * 处理验证错误\n */\nfunction handleValidationError(error: Error): Response {\n return json(\n {\n success: false,\n error: \"Validation Error\",\n message: error.message,\n timestamp: new Date().toISOString(),\n },\n 400,\n );\n}\n\n/**\n * 处理内部错误\n */\nfunction handleInternalError(error: unknown): Response {\n return json(\n {\n success: false,\n error: \"Internal Error\",\n message: error instanceof Error ? error.message : \"未知错误\",\n },\n 500,\n );\n}\n\n/** 空 schema 的上下文类型 */\ntype EmptySchemaContext = {\n req: Request;\n body: unknown;\n query: Record<string, string>;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n};\n\n/**\n * 判断是否为 handler 函数\n */\nfunction isHandler(value: unknown): value is (...args: unknown[]) => unknown {\n return typeof value === \"function\";\n}\n\n/**\n * 创建类型安全的路由处理器\n *\n * @example\n * ```typescript\n * // 无 schema - 直接传入 handler\n * createHandler(({ params }) => `User: ${params.id}`)\n *\n * // 有 schema - 传入 schema 和 handler\n * createHandler(\n * { body: Type.Object({ name: Type.String() }) },\n * ({ body }) => ({ hello: body.name })\n * )\n * ```\n */\n/**\n * 带类型推断的 Handler - 保留返回类型信息用于客户端类型推断\n */\nexport type InferableHandler<TReturn, TSchema extends RouteSchema = RouteSchema> = ((req: Request) => Promise<Response>) & {\n /** 返回类型标记(仅用于类型推断,运行时不存在) */\n __returnType: TReturn;\n /** Schema 类型标记 */\n __schema: TSchema;\n};\n\n\n// 重载 1: 无 schema\nexport function createHandler<R>(\n handler: (ctx: EmptySchemaContext) => R | Promise<R>,\n): InferableHandler<R>;\n\n// 重载 2: 有 schema\nexport function createHandler<const T extends RouteSchema, R>(\n schema: T,\n handler: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T>;\n\n// 实现\nexport function createHandler<const T extends RouteSchema, R>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContext<T>) => R | Promise<R>,\n): InferableHandler<R, T> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (ctx: HandlerContext<T>) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n const handlerFn = async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n });\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n\n // 类型断言:这些属性只在编译时用于类型推断,运行时不存在\n return handlerFn as InferableHandler<R, T>;\n}\n\n/**\n * 创建带额外上下文的路由处理器\n *\n * 用于中间件注入额外数据的场景\n *\n * @example\n * ```typescript\n * // 定义中间件注入的类型\n * type AuthContext = { user: { id: string; role: string } };\n *\n * // 无 schema\n * createHandlerWithExtra<AuthContext>(({ user }) => {\n * return { userId: user.id };\n * })\n *\n * // 有 schema\n * createHandlerWithExtra<AuthContext>(\n * { body: Type.Object({ action: Type.String() }) },\n * ({ body, user }) => ({ success: true, userId: user.id })\n * )\n * ```\n */\n// 重载 1: 无 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n R = unknown,\n>(\n handler: (ctx: EmptySchemaContext & TExtra) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 重载 2: 有 schema\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schema: T,\n handler: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response>;\n\n// 实现\nexport function createHandlerWithExtra<\n TExtra extends Record<string, unknown> = Record<string, never>,\n const T extends RouteSchema = RouteSchema,\n R = unknown,\n>(\n schemaOrHandler: T | ((ctx: EmptySchemaContext & TExtra) => R | Promise<R>),\n maybeHandler?: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n // 判断调用方式\n const hasSchema = !isHandler(schemaOrHandler);\n const schema = hasSchema ? (schemaOrHandler as T) : ({} as T);\n const handler = hasSchema\n ? maybeHandler!\n : (schemaOrHandler as (\n ctx: HandlerContextWithExtra<T, TExtra>,\n ) => R | Promise<R>);\n\n // 预编译 schema\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n precompileSchemas(schema);\n }\n\n return async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params =\n ((req as unknown as Record<string, unknown>).params as Record<\n string,\n string\n >) || {};\n\n // 解析请求体\n let body: unknown = undefined;\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n const [, parsedBody] = await goAwait(parseBody(req));\n body = parsedBody;\n }\n\n // 验证 schema\n const data = { body, query, params, headers, cookies };\n if (\n schema.body ||\n schema.query ||\n schema.params ||\n schema.headers ||\n schema.cookies\n ) {\n validateAllSchemas(schema, data);\n }\n\n // 获取中间件注入的额外数据\n const extras = ((req as unknown as Record<string, unknown>).__locals ??\n {}) as TExtra;\n\n // 调用 handler\n const result = await handler({\n req,\n body: body as HandlerContext<T>[\"body\"],\n query: query as HandlerContext<T>[\"query\"],\n params: params as HandlerContext<T>[\"params\"],\n headers: headers as HandlerContext<T>[\"headers\"],\n cookies: cookies as HandlerContext<T>[\"cookies\"],\n ...extras,\n } as HandlerContextWithExtra<T, TExtra>);\n\n return autoResponse(result);\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n return handleValidationError(error);\n }\n return handleInternalError(error);\n }\n };\n}\n\n/**\n * 简单的路由处理器 (无 schema 验证,只有 req)\n *\n * @example\n * ```typescript\n * simpleHandler(({ req }) => {\n * return { message: \"Hello World\" };\n * })\n * ```\n */\nexport function simpleHandler<R>(\n handler: (ctx: { req: Request }) => R | Promise<R>,\n): (req: Request) => Promise<Response> {\n return async (req: Request): Promise<Response> => {\n try {\n const result = await handler({ req });\n return autoResponse(result);\n } catch (error) {\n return handleInternalError(error);\n }\n };\n}\n","export function base64urlEncode(str: string): string {\n return btoa(str)\n .replace(/=/g, \"\") // ✅ 删除填充\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\");\n}\n\nexport function base64urlDecode(str: string): string {\n const pad = str.length % 4 === 0 ? \"\" : \"=\".repeat(4 - (str.length % 4));\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\") + pad;\n return atob(base64);\n}\n","import { parseCookies } from \"./parsers\";\n\n/** 获取单个 Cookie 值 */\nexport function getCookie(req: Request, key: string): string | null {\n const cookies = parseCookies(req);\n return cookies[key] || null;\n}\n\n/** 生成 Set-Cookie 头 */\nexport function setCookie(\n key: string,\n value: string,\n options: {\n path?: string;\n httpOnly?: boolean;\n maxAge?: number;\n secure?: boolean;\n } = {},\n): string {\n let cookie = `${key}=${encodeURIComponent(value)}`;\n\n if (options.path) cookie += `; Path=${options.path}`;\n if (options.httpOnly) cookie += `; HttpOnly`;\n if (options.secure) cookie += `; Secure`;\n if (options.maxAge) cookie += `; Max-Age=${options.maxAge}`;\n\n return cookie;\n}\n\n// 提供给中间件写入\"局部上下文\"的工具函数\nexport function setLocals<T extends object>(req: Request, extras: T) {\n const target = req as unknown as Record<string, unknown>;\n target.__locals = { ...((target.__locals as object) ?? {}), ...extras };\n}\n\n// 获取中间件注入的局部上下文\nexport function getLocals<T extends object>(req: Request): T {\n const target = req as unknown as Record<string, unknown>;\n return (target.__locals ?? {}) as T;\n}\n","/**\n * 请求解析和验证器\n *\n * 解析handler的req参数,使用Ultra验证器进行验证,\n * 并类型安全地返回解析出来的值\n *\n * @author Framework Team\n * @version 1.0.0\n * @license MIT\n */\n\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { Static } from \"@sinclair/typebox\";\nimport {\n validateAllSchemas,\n type SchemaConfig,\n} from \"./validators/validators\";\nimport { parseBody, parseQuery, parseHeaders, parseCookies } from \"./parsers\";\n\n// 请求数据结构\nexport interface RequestData {\n body: unknown;\n query: unknown;\n params: Record<string, string>;\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}\n\n// 验证后的请求数据类型\nexport interface ValidatedRequestData<T extends SchemaConfig> {\n body: T[\"body\"] extends TSchema ? Static<T[\"body\"]> : unknown;\n query: T[\"query\"] extends TSchema ? Static<T[\"query\"]> : unknown;\n params: T[\"params\"] extends TSchema\n ? Static<T[\"params\"]>\n : Record<string, string>;\n headers: T[\"headers\"] extends TSchema\n ? Static<T[\"headers\"]>\n : Record<string, string>;\n cookies: T[\"cookies\"] extends TSchema\n ? Static<T[\"cookies\"]>\n : Record<string, string>;\n}\n\n// 验证结果\nexport interface ValidationResult<T extends SchemaConfig> {\n success: boolean;\n data?: ValidatedRequestData<T>;\n errors?: Array<{ field: keyof SchemaConfig; message: string }>;\n}\n\n/**\n * 解析Request对象,提取所有相关数据\n * @param request Request对象\n * @param params 路径参数(可选)\n * @returns 解析后的请求数据\n */\nexport async function parseRequest(\n request: Request,\n params?: Record<string, string>,\n): Promise<RequestData> {\n const requestData: RequestData = {\n body: undefined,\n query: parseQuery(request),\n params: params || {},\n headers: parseHeaders(request),\n cookies: parseCookies(request),\n };\n\n // 对于非GET请求,尝试解析请求体\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n requestData.body = await parseBody(request);\n }\n\n return requestData;\n}\n\n/**\n * 验证请求数据\n * @param config Schema配置\n * @param requestData 请求数据\n * @returns 验证结果\n */\nexport function validateRequest<T extends SchemaConfig>(\n config: T,\n requestData: RequestData,\n): ValidationResult<T> {\n try {\n const validatedData = validateAllSchemas(config, requestData);\n\n return {\n success: true,\n data: validatedData as ValidatedRequestData<T>,\n };\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"验证失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 完整的请求解析和验证流程\n * @param request Request对象\n * @param config Schema配置\n * @param params 路径参数(可选)\n * @returns 验证结果\n */\nexport async function parseAndValidateRequest<T extends SchemaConfig>(\n request: Request,\n config: T,\n params?: Record<string, string>,\n): Promise<ValidationResult<T>> {\n try {\n // 1. 解析请求\n const requestData = await parseRequest(request, params);\n\n // 2. 验证数据\n return validateRequest(config, requestData);\n } catch (error) {\n return {\n success: false,\n errors: [\n {\n field: \"unknown\" as keyof SchemaConfig,\n message: error instanceof Error ? error.message : \"请求解析失败\",\n },\n ],\n };\n }\n}\n\n/**\n * 创建类型安全的请求验证器工厂\n * @param config Schema配置\n * @returns 验证器函数\n */\nexport function createRequestValidator<T extends SchemaConfig>(config: T) {\n return async (request: Request, params?: Record<string, string>) => {\n return parseAndValidateRequest(request, config, params);\n };\n}\n","/**\n * HTML渲染工具类\n * 提供统一的HTML模板生成功能\n */\nexport class HtmlRenderer {\n /**\n * 生成基础HTML模板\n */\n static generateBaseHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return `\n <!doctype html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>Vafast SSR App</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n <body>\n <div id=\"app\">${content}</div>\n <script>\n window.__ROUTE_INFO__ = {\n params: ${JSON.stringify(context.params || {})},\n query: ${JSON.stringify(context.query || {})},\n pathname: '${context.pathname}'\n };\n </script>\n <script type=\"module\" src=\"${clientScriptPath}\"></script>\n </body>\n </html>\n `;\n }\n\n /**\n * 生成Vue组件HTML\n */\n static generateVueHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return this.generateBaseHtml(content, context, clientScriptPath);\n }\n\n /**\n * 生成React组件HTML\n */\n static generateReactHtml(\n content: string,\n context: any,\n clientScriptPath: string = \"/client.js\",\n ): string {\n return `\n <!doctype html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>Vafast SSR App</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n <body>\n <div id=\"root\">${content}</div>\n <script>\n window.__ROUTE_INFO__ = {\n params: ${JSON.stringify(context.params || {})},\n query: ${JSON.stringify(context.query || {})},\n pathname: '${context.pathname}'\n };\n </script>\n <script type=\"module\" src=\"${clientScriptPath}\"></script>\n </body>\n </html>\n `;\n }\n}\n","/**\n * 依赖管理器\n * 负责按需加载和管理框架依赖\n */\nexport class DependencyManager {\n private dependencyCache = new Map<string, any>();\n\n /**\n * 按需获取框架依赖\n */\n async getFrameworkDeps(framework: \"vue\" | \"react\") {\n if (this.dependencyCache.has(framework)) {\n return this.dependencyCache.get(framework);\n }\n\n console.log(`📦 按需加载 ${framework} 依赖...`);\n\n try {\n let deps;\n switch (framework) {\n case \"vue\":\n deps = await Promise.all([\n import(\"vue\"),\n import(\"@vue/server-renderer\"),\n ]);\n break;\n case \"react\":\n deps = await Promise.all([\n import(\"react\"),\n import(\"react-dom/server\"),\n ]);\n break;\n default:\n throw new Error(`不支持的框架: ${framework}`);\n }\n\n this.dependencyCache.set(framework, deps);\n console.log(`✅ ${framework} 依赖加载完成`);\n return deps;\n } catch (error) {\n console.error(`❌ ${framework} 依赖加载失败:`, error);\n throw error;\n }\n }\n\n /**\n * 检测组件类型\n */\n detectComponentType(component: any): \"vue\" | \"react\" {\n // 简单的组件类型检测\n if (component.render && typeof component.render === \"function\") {\n return \"vue\";\n }\n if (component.$$typeof) {\n return \"react\";\n }\n // 默认使用 Vue\n return \"vue\";\n }\n\n /**\n * 清除缓存\n */\n clearCache(): void {\n this.dependencyCache.clear();\n console.log(\"🧹 依赖缓存已清除\");\n }\n\n /**\n * 获取缓存状态\n */\n getCacheStatus(): Record<string, boolean> {\n const status: Record<string, boolean> = {};\n for (const [framework] of this.dependencyCache) {\n status[framework] = true;\n }\n return status;\n }\n}\n","/**\n * TypeBox Format 验证器\n *\n * 内置常用的 format 验证,对标 Zod 的内置验证\n * 框架启动时自动注册\n *\n * @version 1.0.0\n */\n\nimport { FormatRegistry } from \"@sinclair/typebox\";\n\n// ============== 正则表达式 ==============\n\n// 邮箱 (RFC 5322 简化版)\nconst EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n// UUID v4\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n// UUID 任意版本\nconst UUID_ANY_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// CUID\nconst CUID_REGEX = /^c[^\\s-]{8,}$/i;\n\n// CUID2\nconst CUID2_REGEX = /^[0-9a-z]+$/;\n\n// ULID\nconst ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/i;\n\n// NanoID (默认 21 字符)\nconst NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/;\n\n// URL\nconst URL_REGEX = /^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$/;\n\n// IPv4\nconst IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n// IPv6 (简化版)\nconst IPV6_REGEX = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$/;\n\n// CIDR (IPv4)\nconst CIDR_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(?:3[0-2]|[12]?[0-9])$/;\n\n// 日期 (YYYY-MM-DD)\nconst DATE_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/;\n\n// 时间 (HH:mm:ss 或 HH:mm:ss.SSS)\nconst TIME_REGEX = /^(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?$/;\n\n// ISO 日期时间\nconst DATE_TIME_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?(?:Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])?$/;\n\n// ISO 8601 Duration (P1Y2M3DT4H5M6S)\nconst DURATION_REGEX = /^P(?:\\d+Y)?(?:\\d+M)?(?:\\d+W)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?$/;\n\n// Hostname (RFC 1123)\nconst HOSTNAME_REGEX = /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)*(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;\n\n// 手机号 (中国大陆)\nconst PHONE_CN_REGEX = /^1[3-9]\\d{9}$/;\n\n// 手机号 (国际格式 E.164)\nconst PHONE_E164_REGEX = /^\\+[1-9]\\d{6,14}$/;\n\n// MongoDB ObjectId\nconst OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/;\n\n// 十六进制颜色\nconst HEX_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n\n// RGB/RGBA 颜色\nconst RGB_COLOR_REGEX = /^rgba?\\(\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\\s*,\\s*(?:0|1|0?\\.\\d+))?\\s*\\)$/;\n\n// Base64\nconst BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n// Base64 URL Safe\nconst BASE64URL_REGEX = /^[A-Za-z0-9_-]+$/;\n\n// JWT (3 部分 base64url)\nconst JWT_REGEX = /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\n\n// Emoji (简化检测)\nconst EMOJI_REGEX = /^[\\p{Emoji}]+$/u;\n\n// Slug (URL 友好字符串)\nconst SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n// Semver (语义化版本)\nconst SEMVER_REGEX = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n// 信用卡号 (Luhn 算法验证)\nfunction isValidCreditCard(value: string): boolean {\n const digits = value.replace(/\\D/g, \"\");\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let isEven = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let digit = parseInt(digits[i], 10);\n if (isEven) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n isEven = !isEven;\n }\n return sum % 10 === 0;\n}\n\n// ============== Format 注册 ==============\n\nlet isRegistered = false;\n\n/**\n * 注册所有内置 format 验证器\n * 框架自动调用,也可手动调用\n */\nexport function registerFormats(): void {\n if (isRegistered) return;\n isRegistered = true;\n\n // === 字符串标识符 ===\n FormatRegistry.Set(\"email\", (v) => EMAIL_REGEX.test(v));\n FormatRegistry.Set(\"uuid\", (v) => UUID_REGEX.test(v));\n FormatRegistry.Set(\"uuid-any\", (v) => UUID_ANY_REGEX.test(v));\n FormatRegistry.Set(\"cuid\", (v) => CUID_REGEX.test(v));\n FormatRegistry.Set(\"cuid2\", (v) => CUID2_REGEX.test(v) && v.length >= 1);\n FormatRegistry.Set(\"ulid\", (v) => ULID_REGEX.test(v));\n FormatRegistry.Set(\"nanoid\", (v) => NANOID_REGEX.test(v));\n FormatRegistry.Set(\"objectid\", (v) => OBJECTID_REGEX.test(v));\n FormatRegistry.Set(\"slug\", (v) => SLUG_REGEX.test(v));\n\n // === 网络相关 ===\n FormatRegistry.Set(\"url\", (v) => URL_REGEX.test(v));\n FormatRegistry.Set(\"uri\", (v) => URL_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"ipv4\", (v) => IPV4_REGEX.test(v));\n FormatRegistry.Set(\"ipv6\", (v) => IPV6_REGEX.test(v));\n FormatRegistry.Set(\"ip\", (v) => IPV4_REGEX.test(v) || IPV6_REGEX.test(v));\n FormatRegistry.Set(\"cidr\", (v) => CIDR_REGEX.test(v));\n FormatRegistry.Set(\"hostname\", (v) => HOSTNAME_REGEX.test(v));\n\n // === 日期时间 ===\n FormatRegistry.Set(\"date\", (v) => DATE_REGEX.test(v));\n FormatRegistry.Set(\"time\", (v) => TIME_REGEX.test(v));\n FormatRegistry.Set(\"date-time\", (v) => DATE_TIME_REGEX.test(v));\n FormatRegistry.Set(\"datetime\", (v) => DATE_TIME_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"duration\", (v) => DURATION_REGEX.test(v));\n\n // === 手机号 ===\n FormatRegistry.Set(\"phone\", (v) => PHONE_CN_REGEX.test(v)); // 中国大陆\n FormatRegistry.Set(\"phone-cn\", (v) => PHONE_CN_REGEX.test(v));\n FormatRegistry.Set(\"phone-e164\", (v) => PHONE_E164_REGEX.test(v)); // 国际\n\n // === 编码格式 ===\n FormatRegistry.Set(\"base64\", (v) => BASE64_REGEX.test(v));\n FormatRegistry.Set(\"base64url\", (v) => BASE64URL_REGEX.test(v));\n FormatRegistry.Set(\"jwt\", (v) => JWT_REGEX.test(v));\n\n // === 颜色 ===\n FormatRegistry.Set(\"hex-color\", (v) => HEX_COLOR_REGEX.test(v));\n FormatRegistry.Set(\"rgb-color\", (v) => RGB_COLOR_REGEX.test(v));\n FormatRegistry.Set(\n \"color\",\n (v) => HEX_COLOR_REGEX.test(v) || RGB_COLOR_REGEX.test(v),\n );\n\n // === 其他 ===\n FormatRegistry.Set(\"emoji\", (v) => EMOJI_REGEX.test(v));\n FormatRegistry.Set(\"semver\", (v) => SEMVER_REGEX.test(v));\n FormatRegistry.Set(\"credit-card\", isValidCreditCard);\n}\n\n/**\n * 自定义注册 format\n */\nexport function registerFormat(\n name: string,\n validator: (value: string) => boolean,\n): void {\n FormatRegistry.Set(name, validator);\n}\n\n/**\n * 检查 format 是否已注册\n */\nexport function hasFormat(name: string): boolean {\n return FormatRegistry.Has(name);\n}\n\n// 导出正则(供外部使用)\nexport const Patterns = {\n EMAIL: EMAIL_REGEX,\n UUID: UUID_REGEX,\n URL: URL_REGEX,\n IPV4: IPV4_REGEX,\n IPV6: IPV6_REGEX,\n DATE: DATE_REGEX,\n TIME: TIME_REGEX,\n DATE_TIME: DATE_TIME_REGEX,\n PHONE_CN: PHONE_CN_REGEX,\n PHONE_E164: PHONE_E164_REGEX,\n OBJECTID: OBJECTID_REGEX,\n HEX_COLOR: HEX_COLOR_REGEX,\n SLUG: SLUG_REGEX,\n SEMVER: SEMVER_REGEX,\n JWT: JWT_REGEX,\n} as const;\n\n","/**\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","/**\n * 路由注册表\n *\n * 提供路由元信息的收集和查询能力\n * 可用于:API 文档生成、Webhook 事件注册、权限检查、审计日志等\n *\n * @example\n * ```typescript\n * // 创建注册表\n * const registry = createRouteRegistry(server.getRoutes())\n *\n * // 查询路由\n * const route = registry.get('POST', '/auth/signIn')\n *\n * // 筛选有 webhook 配置的路由\n * const webhookRoutes = registry.filter('webhook')\n *\n * // 按分类获取\n * const authRoutes = registry.getByCategory('auth')\n * ```\n */\n\nimport type { FlattenedRoute, Method } from '../types'\n\n/**\n * 路由元信息(不含 handler 和 middleware)\n */\nexport interface RouteMeta {\n method: Method\n path: string\n fullPath: string\n name?: string\n description?: string\n /** 扩展字段 */\n [key: string]: unknown\n}\n\n/**\n * 路由注册表\n *\n * 泛型 T 用于定义扩展字段的类型\n */\nexport class RouteRegistry<T extends Record<string, unknown> = Record<string, unknown>> {\n /** 所有路由元信息 */\n private routes: RouteMeta[] = []\n\n /** 路由映射表:METHOD:fullPath -> RouteMeta */\n private routeMap = new Map<string, RouteMeta>()\n\n /** 分类映射表:category -> RouteMeta[] */\n private categoryMap = new Map<string, RouteMeta[]>()\n\n constructor(routes: FlattenedRoute[]) {\n this.buildRegistry(routes)\n }\n\n /**\n * 构建注册表\n */\n private buildRegistry(routes: FlattenedRoute[]): void {\n for (const route of routes) {\n // 提取元信息(排除 handler 和 middleware)\n const meta: RouteMeta = {\n method: route.method,\n path: route.path,\n fullPath: route.fullPath,\n name: route.name,\n description: route.description,\n }\n\n // 复制扩展字段\n for (const key of Object.keys(route)) {\n if (!['method', 'path', 'fullPath', 'name', 'description', 'handler', 'middleware', 'middlewareChain'].includes(key)) {\n meta[key] = route[key as keyof FlattenedRoute]\n }\n }\n\n this.routes.push(meta)\n this.routeMap.set(`${route.method}:${route.fullPath}`, meta)\n\n // 按分类索引\n const category = this.extractCategory(route.fullPath)\n if (!this.categoryMap.has(category)) {\n this.categoryMap.set(category, [])\n }\n this.categoryMap.get(category)!.push(meta)\n }\n }\n\n /**\n * 提取分类(第一段路径)\n */\n private extractCategory(path: string): string {\n const segments = path.split('/').filter(Boolean)\n return segments[0] || 'root'\n }\n\n // ============================================\n // 查询接口\n // ============================================\n\n /**\n * 获取所有路由元信息\n */\n getAll(): RouteMeta[] {\n return [...this.routes]\n }\n\n /**\n * 按 method + path 查询路由\n */\n get(method: string, path: string): (RouteMeta & T) | undefined {\n return this.routeMap.get(`${method}:${path}`) as (RouteMeta & T) | undefined\n }\n\n /**\n * 检查路由是否存在\n */\n has(method: string, path: string): boolean {\n return this.routeMap.has(`${method}:${path}`)\n }\n\n /**\n * 按分类获取路由\n */\n getByCategory(category: string): RouteMeta[] {\n return this.categoryMap.get(category) || []\n }\n\n /**\n * 获取所有分类\n */\n getCategories(): string[] {\n return Array.from(this.categoryMap.keys()).sort()\n }\n\n /**\n * 筛选有特定字段的路由\n *\n * @example\n * ```typescript\n * // 获取所有配置了 webhook 的路由\n * const webhookRoutes = registry.filter('webhook')\n * ```\n */\n filter<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[] {\n return this.routes.filter((r) => field in r && r[field] !== undefined) as (RouteMeta & Record<K, unknown>)[]\n }\n\n /**\n * 按条件筛选路由\n *\n * @example\n * ```typescript\n * // 获取所有 POST 请求\n * const postRoutes = registry.filterBy(r => r.method === 'POST')\n * ```\n */\n filterBy(predicate: (route: RouteMeta) => boolean): RouteMeta[] {\n return this.routes.filter(predicate)\n }\n\n /**\n * 获取路由数量\n */\n get size(): number {\n return this.routes.length\n }\n\n /**\n * 遍历所有路由\n */\n forEach(callback: (route: RouteMeta, index: number) => void): void {\n this.routes.forEach(callback)\n }\n\n /**\n * 映射所有路由\n */\n map<R>(callback: (route: RouteMeta, index: number) => R): R[] {\n return this.routes.map(callback)\n }\n}\n\n/**\n * 创建路由注册表\n *\n * @example\n * ```typescript\n * // 定义扩展字段类型\n * interface MyRouteMeta {\n * webhook?: { eventKey: string }\n * permission?: string\n * }\n *\n * // 创建带类型的注册表\n * const registry = createRouteRegistry<MyRouteMeta>(server.getRoutes())\n *\n * // 类型安全的查询\n * const route = registry.get('POST', '/auth/signIn')\n * if (route?.webhook) {\n * console.log(route.webhook.eventKey)\n * }\n * ```\n */\nexport function createRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(\n routes: FlattenedRoute[]\n): RouteRegistry<T> {\n return new RouteRegistry<T>(routes)\n}\n\n// ============================================\n// 全局 Registry(单例模式)\n// ============================================\n\n/** 全局 registry 实例 */\nlet globalRegistry: RouteRegistry | null = null\n\n/**\n * 设置全局 registry(框架内部使用)\n * @internal\n */\nexport function setGlobalRegistry(registry: RouteRegistry): void {\n globalRegistry = registry\n}\n\n/**\n * 获取全局路由注册表\n *\n * @example\n * ```typescript\n * // 在任意文件中\n * import { getRouteRegistry } from 'vafast'\n *\n * const registry = getRouteRegistry()\n * const webhookRoutes = registry.filter('webhook')\n * ```\n *\n * @throws 如果 Server 尚未创建\n */\nexport function getRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(): RouteRegistry<T> {\n if (!globalRegistry) {\n throw new Error('RouteRegistry not initialized. Make sure Server is created first.')\n }\n return globalRegistry as RouteRegistry<T>\n}\n\n/**\n * 按 method + path 获取单个路由\n *\n * 便捷函数,无需先获取 registry\n *\n * @example\n * ```typescript\n * // 在中间件或接口中\n * import { getRoute } from 'vafast'\n *\n * const route = getRoute('POST', '/auth/signIn')\n * if (route?.webhook) {\n * console.log('This route has webhook:', route.webhook)\n * }\n * ```\n */\nexport function getRoute<T extends Record<string, unknown> = Record<string, unknown>>(\n method: string,\n path: string\n): (RouteMeta & T) | undefined {\n return getRouteRegistry<T>().get(method, path)\n}\n\n/**\n * 获取所有路由\n *\n * @example\n * ```typescript\n * import { getAllRoutes } from 'vafast'\n *\n * const routes = getAllRoutes()\n * console.log(`Total ${routes.length} routes`)\n * ```\n */\nexport function getAllRoutes(): RouteMeta[] {\n return getRouteRegistry().getAll()\n}\n\n/**\n * 筛选有特定字段的路由\n *\n * @example\n * ```typescript\n * import { filterRoutes } from 'vafast'\n *\n * // 获取所有配置了 webhook 的路由\n * const webhookRoutes = filterRoutes('webhook')\n * ```\n */\nexport function filterRoutes<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[] {\n return getRouteRegistry().filter(field)\n}\n\n"],"mappings":"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","names":["text","stream","stream"]}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { FlattenedRoute, Method } from '../types/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 路由注册表
|
|
5
|
+
*
|
|
6
|
+
* 提供路由元信息的收集和查询能力
|
|
7
|
+
* 可用于:API 文档生成、Webhook 事件注册、权限检查、审计日志等
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // 创建注册表
|
|
12
|
+
* const registry = createRouteRegistry(server.getRoutes())
|
|
13
|
+
*
|
|
14
|
+
* // 查询路由
|
|
15
|
+
* const route = registry.get('POST', '/auth/signIn')
|
|
16
|
+
*
|
|
17
|
+
* // 筛选有 webhook 配置的路由
|
|
18
|
+
* const webhookRoutes = registry.filter('webhook')
|
|
19
|
+
*
|
|
20
|
+
* // 按分类获取
|
|
21
|
+
* const authRoutes = registry.getByCategory('auth')
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 路由元信息(不含 handler 和 middleware)
|
|
27
|
+
*/
|
|
28
|
+
interface RouteMeta {
|
|
29
|
+
method: Method;
|
|
30
|
+
path: string;
|
|
31
|
+
fullPath: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
/** 扩展字段 */
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 路由注册表
|
|
39
|
+
*
|
|
40
|
+
* 泛型 T 用于定义扩展字段的类型
|
|
41
|
+
*/
|
|
42
|
+
declare class RouteRegistry<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
43
|
+
/** 所有路由元信息 */
|
|
44
|
+
private routes;
|
|
45
|
+
/** 路由映射表:METHOD:fullPath -> RouteMeta */
|
|
46
|
+
private routeMap;
|
|
47
|
+
/** 分类映射表:category -> RouteMeta[] */
|
|
48
|
+
private categoryMap;
|
|
49
|
+
constructor(routes: FlattenedRoute[]);
|
|
50
|
+
/**
|
|
51
|
+
* 构建注册表
|
|
52
|
+
*/
|
|
53
|
+
private buildRegistry;
|
|
54
|
+
/**
|
|
55
|
+
* 提取分类(第一段路径)
|
|
56
|
+
*/
|
|
57
|
+
private extractCategory;
|
|
58
|
+
/**
|
|
59
|
+
* 获取所有路由元信息
|
|
60
|
+
*/
|
|
61
|
+
getAll(): RouteMeta[];
|
|
62
|
+
/**
|
|
63
|
+
* 按 method + path 查询路由
|
|
64
|
+
*/
|
|
65
|
+
get(method: string, path: string): (RouteMeta & T) | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* 检查路由是否存在
|
|
68
|
+
*/
|
|
69
|
+
has(method: string, path: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* 按分类获取路由
|
|
72
|
+
*/
|
|
73
|
+
getByCategory(category: string): RouteMeta[];
|
|
74
|
+
/**
|
|
75
|
+
* 获取所有分类
|
|
76
|
+
*/
|
|
77
|
+
getCategories(): string[];
|
|
78
|
+
/**
|
|
79
|
+
* 筛选有特定字段的路由
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // 获取所有配置了 webhook 的路由
|
|
84
|
+
* const webhookRoutes = registry.filter('webhook')
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
filter<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[];
|
|
88
|
+
/**
|
|
89
|
+
* 按条件筛选路由
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // 获取所有 POST 请求
|
|
94
|
+
* const postRoutes = registry.filterBy(r => r.method === 'POST')
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
filterBy(predicate: (route: RouteMeta) => boolean): RouteMeta[];
|
|
98
|
+
/**
|
|
99
|
+
* 获取路由数量
|
|
100
|
+
*/
|
|
101
|
+
get size(): number;
|
|
102
|
+
/**
|
|
103
|
+
* 遍历所有路由
|
|
104
|
+
*/
|
|
105
|
+
forEach(callback: (route: RouteMeta, index: number) => void): void;
|
|
106
|
+
/**
|
|
107
|
+
* 映射所有路由
|
|
108
|
+
*/
|
|
109
|
+
map<R>(callback: (route: RouteMeta, index: number) => R): R[];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 创建路由注册表
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // 定义扩展字段类型
|
|
117
|
+
* interface MyRouteMeta {
|
|
118
|
+
* webhook?: { eventKey: string }
|
|
119
|
+
* permission?: string
|
|
120
|
+
* }
|
|
121
|
+
*
|
|
122
|
+
* // 创建带类型的注册表
|
|
123
|
+
* const registry = createRouteRegistry<MyRouteMeta>(server.getRoutes())
|
|
124
|
+
*
|
|
125
|
+
* // 类型安全的查询
|
|
126
|
+
* const route = registry.get('POST', '/auth/signIn')
|
|
127
|
+
* if (route?.webhook) {
|
|
128
|
+
* console.log(route.webhook.eventKey)
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
declare function createRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(routes: FlattenedRoute[]): RouteRegistry<T>;
|
|
133
|
+
/**
|
|
134
|
+
* 设置全局 registry(框架内部使用)
|
|
135
|
+
* @internal
|
|
136
|
+
*/
|
|
137
|
+
declare function setGlobalRegistry(registry: RouteRegistry): void;
|
|
138
|
+
/**
|
|
139
|
+
* 获取全局路由注册表
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* // 在任意文件中
|
|
144
|
+
* import { getRouteRegistry } from 'vafast'
|
|
145
|
+
*
|
|
146
|
+
* const registry = getRouteRegistry()
|
|
147
|
+
* const webhookRoutes = registry.filter('webhook')
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @throws 如果 Server 尚未创建
|
|
151
|
+
*/
|
|
152
|
+
declare function getRouteRegistry<T extends Record<string, unknown> = Record<string, unknown>>(): RouteRegistry<T>;
|
|
153
|
+
/**
|
|
154
|
+
* 按 method + path 获取单个路由
|
|
155
|
+
*
|
|
156
|
+
* 便捷函数,无需先获取 registry
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* // 在中间件或接口中
|
|
161
|
+
* import { getRoute } from 'vafast'
|
|
162
|
+
*
|
|
163
|
+
* const route = getRoute('POST', '/auth/signIn')
|
|
164
|
+
* if (route?.webhook) {
|
|
165
|
+
* console.log('This route has webhook:', route.webhook)
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
declare function getRoute<T extends Record<string, unknown> = Record<string, unknown>>(method: string, path: string): (RouteMeta & T) | undefined;
|
|
170
|
+
/**
|
|
171
|
+
* 获取所有路由
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* import { getAllRoutes } from 'vafast'
|
|
176
|
+
*
|
|
177
|
+
* const routes = getAllRoutes()
|
|
178
|
+
* console.log(`Total ${routes.length} routes`)
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function getAllRoutes(): RouteMeta[];
|
|
182
|
+
/**
|
|
183
|
+
* 筛选有特定字段的路由
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* import { filterRoutes } from 'vafast'
|
|
188
|
+
*
|
|
189
|
+
* // 获取所有配置了 webhook 的路由
|
|
190
|
+
* const webhookRoutes = filterRoutes('webhook')
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
declare function filterRoutes<K extends string>(field: K): (RouteMeta & Record<K, unknown>)[];
|
|
194
|
+
|
|
195
|
+
export { type RouteMeta, RouteRegistry, createRouteRegistry, filterRoutes, getAllRoutes, getRoute, getRouteRegistry, setGlobalRegistry };
|