vafast 0.1.13 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/middleware/component-renderer.js +10 -14
  2. package/dist/middleware/component-router.js +4 -1
  3. package/dist/middleware.d.ts +1 -1
  4. package/dist/middleware.js +8 -3
  5. package/dist/monitoring/types.d.ts +1 -1
  6. package/dist/router/index.d.ts +5 -0
  7. package/dist/router/index.js +7 -0
  8. package/dist/router/radix-tree.d.ts +51 -0
  9. package/dist/router/radix-tree.js +186 -0
  10. package/dist/router.d.ts +38 -10
  11. package/dist/router.js +55 -43
  12. package/dist/server/base-server.d.ts +0 -4
  13. package/dist/server/base-server.js +2 -24
  14. package/dist/server/index.d.ts +4 -4
  15. package/dist/server/index.js +8 -6
  16. package/dist/server/server.d.ts +30 -2
  17. package/dist/server/server.js +84 -60
  18. package/dist/types/index.d.ts +4 -2
  19. package/dist/types/index.js +3 -2
  20. package/dist/types/route.d.ts +2 -2
  21. package/dist/types/schema.d.ts +75 -0
  22. package/dist/types/schema.js +10 -0
  23. package/dist/types/types.d.ts +6 -2
  24. package/dist/utils/create-handler.d.ts +74 -0
  25. package/dist/utils/create-handler.js +234 -0
  26. package/dist/utils/dependency-manager.js +8 -2
  27. package/dist/utils/go-await.js +1 -4
  28. package/dist/utils/handle.d.ts +1 -0
  29. package/dist/utils/handle.js +5 -0
  30. package/dist/utils/index.d.ts +12 -10
  31. package/dist/utils/index.js +21 -11
  32. package/dist/utils/path-matcher.js +2 -1
  33. package/dist/utils/response.d.ts +5 -0
  34. package/dist/utils/response.js +41 -0
  35. package/package.json +30 -27
  36. package/dist/index.js.map +0 -1
  37. package/dist/types.d.ts +0 -18
  38. package/dist/types.js +0 -1
  39. package/dist/utils/route-handler-factory.d.ts +0 -50
  40. package/dist/utils/route-handler-factory.js +0 -182
@@ -1,73 +1,97 @@
1
- import { matchPath, flattenNestedRoutes } from "../router";
1
+ /**
2
+ * Vafast 核心服务器
3
+ *
4
+ * 基于 Radix Tree 的高性能路由匹配
5
+ * 时间复杂度: O(k),k 为路径段数
6
+ */
7
+ import { flattenNestedRoutes } from "../router";
2
8
  import { composeMiddleware } from "../middleware";
3
9
  import { json } from "../utils/response";
4
10
  import { BaseServer } from "./base-server";
5
- import { PathMatcher } from "../utils/path-matcher";
11
+ import { RadixRouter } from "../router/radix-tree";
12
+ /**
13
+ * Vafast 服务器
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const server = new Server([
18
+ * { method: "GET", path: "/", handler: () => new Response("Hello") },
19
+ * ]);
20
+ * export default { fetch: server.fetch };
21
+ * ```
22
+ */
6
23
  export class Server extends BaseServer {
24
+ router;
7
25
  routes;
8
- constructor(routes) {
26
+ constructor(routes = []) {
9
27
  super();
10
- // 扁平化嵌套路由,计算完整的中间件链
11
- this.routes = flattenNestedRoutes(routes);
12
- // 在构造时按路由"特异性"排序:静态 > 动态(:param) > 通配符(*)
13
- this.routes = this.routes.sort((a, b) => PathMatcher.calculatePathScore(b.fullPath) -
14
- PathMatcher.calculatePathScore(a.fullPath));
15
- // 检测路由冲突
16
- this.detectRouteConflicts(this.routes);
17
- // 打印扁平化后的路由信息
18
- this.logFlattenedRoutes(this.routes);
28
+ this.router = new RadixRouter();
29
+ this.routes = [];
30
+ if (routes.length > 0) {
31
+ this.registerRoutes(routes);
32
+ }
33
+ }
34
+ registerRoutes(routes) {
35
+ const flattened = flattenNestedRoutes(routes);
36
+ this.routes.push(...flattened);
37
+ for (const route of flattened) {
38
+ this.router.register(route.method, route.fullPath, route.handler, route.middlewareChain || []);
39
+ }
40
+ this.detectRouteConflicts(flattened);
41
+ this.logFlattenedRoutes(flattened);
19
42
  }
43
+ /** 快速提取 pathname */
44
+ extractPathname(url) {
45
+ let start = url.indexOf("://");
46
+ start = start === -1 ? 0 : start + 3;
47
+ const pathStart = url.indexOf("/", start);
48
+ if (pathStart === -1)
49
+ return "/";
50
+ let end = url.indexOf("?", pathStart);
51
+ if (end === -1)
52
+ end = url.indexOf("#", pathStart);
53
+ if (end === -1)
54
+ end = url.length;
55
+ return url.substring(pathStart, end) || "/";
56
+ }
57
+ /** 处理请求 */
20
58
  fetch = async (req) => {
21
- const { pathname } = new URL(req.url);
59
+ const pathname = this.extractPathname(req.url);
22
60
  const method = req.method;
23
- // 自动处理 OPTIONS 请求
24
- if (method === "OPTIONS") {
25
- return this.handleOptions(pathname, this.routes);
61
+ const match = this.router.match(method, pathname);
62
+ if (match) {
63
+ req.params = match.params;
64
+ // 组合全局中间件 + 路由中间件(mapResponse 在 composeMiddleware 内部处理)
65
+ const allMiddleware = [...this.globalMiddleware, ...match.middleware];
66
+ const handler = composeMiddleware(allMiddleware, match.handler);
67
+ return handler(req);
26
68
  }
27
- let matched;
28
- let params = {};
29
- let availableMethods = [];
30
- for (const route of this.routes) {
31
- const result = matchPath(route.fullPath, pathname);
32
- if (result.matched) {
33
- if (route.method === method) {
34
- matched = route;
35
- params = result.params;
36
- break;
37
- }
38
- else {
39
- // 路径匹配但方法不匹配,收集可用方法
40
- availableMethods.push(route.method);
41
- }
42
- }
69
+ // 405 Method Not Allowed
70
+ const allowedMethods = this.router.getAllowedMethods(pathname);
71
+ if (allowedMethods.length > 0) {
72
+ return json({
73
+ success: false,
74
+ error: "Method Not Allowed",
75
+ message: `Method ${method} not allowed for this endpoint`,
76
+ allowedMethods,
77
+ }, 405, { Allow: allowedMethods.join(", ") });
43
78
  }
44
- const handler = async (req) => {
45
- if (matched) {
46
- // 将路径参数设置到 req 对象上,以便 TypedRoute 处理器能够访问
47
- req.params = params;
48
- return await matched.handler(req);
49
- }
50
- else if (availableMethods.length > 0) {
51
- // 路径存在但方法不匹配,返回 405 Method Not Allowed
52
- return json({
53
- success: false,
54
- error: "Method Not Allowed",
55
- message: `Method ${method} not allowed for this endpoint`,
56
- allowedMethods: availableMethods,
57
- }, 405, {
58
- Allow: availableMethods.join(", "),
59
- });
60
- }
61
- else {
62
- // 路径不存在,返回 404 Not Found
63
- return json({ success: false, error: "Not Found" }, 404);
64
- }
65
- };
66
- const middlewareChain = matched?.middlewareChain
67
- ? [...this.globalMiddleware, ...matched.middlewareChain]
68
- : this.globalMiddleware;
69
- // 使用 composeMiddleware 来确保错误处理中间件被应用
70
- const composedHandler = composeMiddleware(middlewareChain, handler);
71
- return await composedHandler(req);
79
+ // 404 Not Found
80
+ return json({ success: false, error: "Not Found" }, 404);
72
81
  };
82
+ addRoute(route) {
83
+ const flattenedRoute = {
84
+ ...route,
85
+ fullPath: route.path,
86
+ middlewareChain: route.middleware || [],
87
+ };
88
+ this.routes.push(flattenedRoute);
89
+ this.router.register(route.method, route.path, route.handler, route.middleware || []);
90
+ }
91
+ addRoutes(routes) {
92
+ this.registerRoutes(routes);
93
+ }
94
+ getRoutes() {
95
+ return this.router.getRoutes();
96
+ }
73
97
  }
@@ -1,3 +1,5 @@
1
- export * from "./route";
1
+ export type { Method, Handler, Route, NestedRoute, Middleware, FlattenedRoute, ResponseBody, } from "./types";
2
+ export type { BaseRouteConfig, ExtendedRouteConfig, NestedRouteConfig, TypedRoute, CompatibleRoute, } from "./route";
3
+ export { createTypedRoute, isTypedRoute } from "./route";
2
4
  export * from "./component-route";
3
- export type { Method, Handler, Route, NestedRoute } from "./types";
5
+ export * from "./schema";
@@ -1,3 +1,4 @@
1
- // 导出所有类型定义
2
- export * from "./route";
1
+ export { createTypedRoute, isTypedRoute } from "./route";
2
+ // 组件路由和 Schema 类型
3
3
  export * from "./component-route";
4
+ export * from "./schema";
@@ -1,11 +1,11 @@
1
- import { Route } from "./types";
1
+ import { Route, ResponseBody } from "./types";
2
2
  export interface Middleware {
3
3
  (req: Request, next: () => Promise<Response>): Promise<Response>;
4
4
  }
5
5
  export interface BaseRouteConfig {
6
6
  method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
7
7
  path: string;
8
- handler: (req: Request) => Response | Promise<Response>;
8
+ handler: (req: Request) => ResponseBody | Promise<ResponseBody>;
9
9
  }
10
10
  export interface ExtendedRouteConfig extends BaseRouteConfig {
11
11
  middleware?: Middleware[];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Schema 类型定义
3
+ *
4
+ * 使用 TSchema 约束替代 any,提供完整的类型安全
5
+ *
6
+ * @author Framework Team
7
+ * @version 1.0.0
8
+ * @license MIT
9
+ */
10
+ import type { TSchema, Static } from "@sinclair/typebox";
11
+ /**
12
+ * 路由 Schema 配置
13
+ * 所有 schema 字段使用 TSchema 约束
14
+ */
15
+ export interface RouteSchema {
16
+ body?: TSchema;
17
+ query?: TSchema;
18
+ params?: TSchema;
19
+ headers?: TSchema;
20
+ cookies?: TSchema;
21
+ }
22
+ /**
23
+ * 从 Schema 配置推导出具体类型
24
+ */
25
+ export type InferSchema<T extends RouteSchema> = {
26
+ body: T["body"] extends TSchema ? Static<T["body"]> : unknown;
27
+ query: T["query"] extends TSchema ? Static<T["query"]> : Record<string, string>;
28
+ params: T["params"] extends TSchema ? Static<T["params"]> : Record<string, string>;
29
+ headers: T["headers"] extends TSchema ? Static<T["headers"]> : Record<string, string>;
30
+ cookies: T["cookies"] extends TSchema ? Static<T["cookies"]> : Record<string, string>;
31
+ };
32
+ /**
33
+ * Handler 上下文类型
34
+ */
35
+ export interface HandlerContext<T extends RouteSchema = RouteSchema> {
36
+ /** 原始请求对象 */
37
+ req: Request;
38
+ /** 请求体 (经过 schema 验证) */
39
+ body: InferSchema<T>["body"];
40
+ /** 查询参数 (经过 schema 验证) */
41
+ query: InferSchema<T>["query"];
42
+ /** 路径参数 (经过 schema 验证) */
43
+ params: InferSchema<T>["params"];
44
+ /** 请求头 (经过 schema 验证) */
45
+ headers: InferSchema<T>["headers"];
46
+ /** Cookie (经过 schema 验证) */
47
+ cookies: InferSchema<T>["cookies"];
48
+ }
49
+ /**
50
+ * 带额外上下文的 Handler 上下文类型
51
+ * 用于中间件注入额外数据
52
+ */
53
+ export type HandlerContextWithExtra<T extends RouteSchema = RouteSchema, TExtra extends Record<string, unknown> = Record<string, never>> = HandlerContext<T> & TExtra;
54
+ /**
55
+ * Handler 函数类型
56
+ */
57
+ export type TypedHandler<T extends RouteSchema = RouteSchema, TExtra extends Record<string, unknown> = Record<string, never>, TReturn = unknown> = (ctx: HandlerContextWithExtra<T, TExtra>) => TReturn | Promise<TReturn>;
58
+ /**
59
+ * 扩展的路由配置 (包含 schema)
60
+ */
61
+ export interface TypedRouteConfig<T extends RouteSchema = RouteSchema> {
62
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
63
+ path: string;
64
+ schema?: T;
65
+ handler: (req: Request) => Response | Promise<Response>;
66
+ middleware?: Array<(req: Request, next: () => Promise<Response>) => Promise<Response>>;
67
+ docs?: {
68
+ description?: string;
69
+ tags?: string[];
70
+ security?: unknown[];
71
+ responses?: Record<string, unknown>;
72
+ };
73
+ timeout?: number;
74
+ maxBodySize?: string;
75
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Schema 类型定义
3
+ *
4
+ * 使用 TSchema 约束替代 any,提供完整的类型安全
5
+ *
6
+ * @author Framework Team
7
+ * @version 1.0.0
8
+ * @license MIT
9
+ */
10
+ export {};
@@ -1,6 +1,10 @@
1
1
  export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
2
- export type Handler = (req: Request, params?: Record<string, string>, user?: Record<string, any>) => Response | Promise<Response>;
3
- export type Middleware = (req: Request, next: () => Promise<Response>) => Promise<Response>;
2
+ /** 支持的响应类型 - mapResponse 自动转换 */
3
+ export type ResponseBody = Response | string | number | boolean | object | null | undefined | ReadableStream | Blob | ArrayBuffer;
4
+ /** Handler 返回值(支持同步/异步,任意类型) */
5
+ export type Handler = (req: Request, params?: Record<string, string>, user?: Record<string, any>) => ResponseBody | Promise<ResponseBody>;
6
+ /** 中间件(返回值必须是 Response 或 Promise<Response>) */
7
+ export type Middleware = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>;
4
8
  export interface Route {
5
9
  method: Method;
6
10
  path: string;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 类型安全的路由处理器工厂
3
+ *
4
+ * 非柯里化设计,API 更简洁
5
+ *
6
+ * @author Framework Team
7
+ * @version 3.0.0
8
+ * @license MIT
9
+ */
10
+ import type { RouteSchema, HandlerContext, HandlerContextWithExtra } from "../types/schema";
11
+ /** 空 schema 的上下文类型 */
12
+ type EmptySchemaContext = {
13
+ req: Request;
14
+ body: unknown;
15
+ query: Record<string, string>;
16
+ params: Record<string, string>;
17
+ headers: Record<string, string>;
18
+ cookies: Record<string, string>;
19
+ };
20
+ /**
21
+ * 创建类型安全的路由处理器
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // 无 schema - 直接传入 handler
26
+ * createHandler(({ params }) => `User: ${params.id}`)
27
+ *
28
+ * // 有 schema - 传入 schema 和 handler
29
+ * createHandler(
30
+ * { body: Type.Object({ name: Type.String() }) },
31
+ * ({ body }) => ({ hello: body.name })
32
+ * )
33
+ * ```
34
+ */
35
+ export declare function createHandler<R>(handler: (ctx: EmptySchemaContext) => R | Promise<R>): (req: Request) => Promise<Response>;
36
+ export declare function createHandler<const T extends RouteSchema, R>(schema: T, handler: (ctx: HandlerContext<T>) => R | Promise<R>): (req: Request) => Promise<Response>;
37
+ /**
38
+ * 创建带额外上下文的路由处理器
39
+ *
40
+ * 用于中间件注入额外数据的场景
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // 定义中间件注入的类型
45
+ * type AuthContext = { user: { id: string; role: string } };
46
+ *
47
+ * // 无 schema
48
+ * createHandlerWithExtra<AuthContext>(({ user }) => {
49
+ * return { userId: user.id };
50
+ * })
51
+ *
52
+ * // 有 schema
53
+ * createHandlerWithExtra<AuthContext>(
54
+ * { body: Type.Object({ action: Type.String() }) },
55
+ * ({ body, user }) => ({ success: true, userId: user.id })
56
+ * )
57
+ * ```
58
+ */
59
+ export declare function createHandlerWithExtra<TExtra extends Record<string, unknown> = Record<string, never>, R = unknown>(handler: (ctx: EmptySchemaContext & TExtra) => R | Promise<R>): (req: Request) => Promise<Response>;
60
+ export declare function createHandlerWithExtra<TExtra extends Record<string, unknown> = Record<string, never>, const T extends RouteSchema = RouteSchema, R = unknown>(schema: T, handler: (ctx: HandlerContextWithExtra<T, TExtra>) => R | Promise<R>): (req: Request) => Promise<Response>;
61
+ /**
62
+ * 简单的路由处理器 (无 schema 验证,只有 req)
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * simpleHandler(({ req }) => {
67
+ * return { message: "Hello World" };
68
+ * })
69
+ * ```
70
+ */
71
+ export declare function simpleHandler<R>(handler: (ctx: {
72
+ req: Request;
73
+ }) => R | Promise<R>): (req: Request) => Promise<Response>;
74
+ export {};
@@ -0,0 +1,234 @@
1
+ /**
2
+ * 类型安全的路由处理器工厂
3
+ *
4
+ * 非柯里化设计,API 更简洁
5
+ *
6
+ * @author Framework Team
7
+ * @version 3.0.0
8
+ * @license MIT
9
+ */
10
+ import { parseBody, parseQuery, parseHeaders, parseCookies } from "./parsers";
11
+ import { goAwait } from "./go-await";
12
+ import { json } from "./response";
13
+ import { validateAllSchemasUltra, precompileSchemasUltra, } from "./validators/schema-validators-ultra";
14
+ /**
15
+ * 自动响应转换
16
+ * 将各种返回值类型转换为 Response 对象
17
+ */
18
+ function autoResponse(result) {
19
+ // 已经是 Response
20
+ if (result instanceof Response) {
21
+ return result;
22
+ }
23
+ // null/undefined -> 204
24
+ if (result === null || result === undefined) {
25
+ return new Response(null, { status: 204 });
26
+ }
27
+ // 字符串 -> text/plain
28
+ if (typeof result === "string") {
29
+ return new Response(result, {
30
+ headers: { "Content-Type": "text/plain; charset=utf-8" },
31
+ });
32
+ }
33
+ // 数字/布尔 -> text/plain
34
+ if (typeof result === "number" || typeof result === "boolean") {
35
+ return new Response(String(result), {
36
+ headers: { "Content-Type": "text/plain; charset=utf-8" },
37
+ });
38
+ }
39
+ // 对象 -> 检查是否是 { data, status, headers } 格式
40
+ if (typeof result === "object") {
41
+ const obj = result;
42
+ if ("data" in obj && ("status" in obj || "headers" in obj)) {
43
+ const { data, status = 200, headers = {} } = obj;
44
+ if (data === null || data === undefined) {
45
+ return new Response(null, {
46
+ status: status === 200 ? 204 : status,
47
+ headers: headers,
48
+ });
49
+ }
50
+ if (typeof data === "string" ||
51
+ typeof data === "number" ||
52
+ typeof data === "boolean") {
53
+ return new Response(String(data), {
54
+ status: status,
55
+ headers: {
56
+ "Content-Type": "text/plain; charset=utf-8",
57
+ ...headers,
58
+ },
59
+ });
60
+ }
61
+ return json(data, status, headers);
62
+ }
63
+ // 普通对象 -> JSON
64
+ return json(result);
65
+ }
66
+ // 其他类型 -> 204
67
+ return new Response(null, { status: 204 });
68
+ }
69
+ /**
70
+ * 处理验证错误
71
+ */
72
+ function handleValidationError(error) {
73
+ return json({
74
+ success: false,
75
+ error: "Validation Error",
76
+ message: error.message,
77
+ timestamp: new Date().toISOString(),
78
+ }, 400);
79
+ }
80
+ /**
81
+ * 处理内部错误
82
+ */
83
+ function handleInternalError(error) {
84
+ return json({
85
+ success: false,
86
+ error: "Internal Error",
87
+ message: error instanceof Error ? error.message : "未知错误",
88
+ }, 500);
89
+ }
90
+ /**
91
+ * 判断是否为 handler 函数
92
+ */
93
+ function isHandler(value) {
94
+ return typeof value === "function";
95
+ }
96
+ // 实现
97
+ export function createHandler(schemaOrHandler, maybeHandler) {
98
+ // 判断调用方式
99
+ const hasSchema = !isHandler(schemaOrHandler);
100
+ const schema = hasSchema ? schemaOrHandler : {};
101
+ const handler = hasSchema
102
+ ? maybeHandler
103
+ : schemaOrHandler;
104
+ // 预编译 schema
105
+ if (schema.body ||
106
+ schema.query ||
107
+ schema.params ||
108
+ schema.headers ||
109
+ schema.cookies) {
110
+ precompileSchemasUltra(schema);
111
+ }
112
+ return async (req) => {
113
+ try {
114
+ // 解析请求数据
115
+ const query = parseQuery(req);
116
+ const headers = parseHeaders(req);
117
+ const cookies = parseCookies(req);
118
+ const params = req.params || {};
119
+ // 解析请求体
120
+ let body = undefined;
121
+ if (req.method !== "GET" && req.method !== "HEAD") {
122
+ const [, parsedBody] = await goAwait(parseBody(req));
123
+ body = parsedBody;
124
+ }
125
+ // 验证 schema
126
+ const data = { body, query, params, headers, cookies };
127
+ if (schema.body ||
128
+ schema.query ||
129
+ schema.params ||
130
+ schema.headers ||
131
+ schema.cookies) {
132
+ validateAllSchemasUltra(schema, data);
133
+ }
134
+ // 调用 handler
135
+ const result = await handler({
136
+ req,
137
+ body: body,
138
+ query: query,
139
+ params: params,
140
+ headers: headers,
141
+ cookies: cookies,
142
+ });
143
+ return autoResponse(result);
144
+ }
145
+ catch (error) {
146
+ if (error instanceof Error && error.message.includes("验证失败")) {
147
+ return handleValidationError(error);
148
+ }
149
+ return handleInternalError(error);
150
+ }
151
+ };
152
+ }
153
+ // 实现
154
+ export function createHandlerWithExtra(schemaOrHandler, maybeHandler) {
155
+ // 判断调用方式
156
+ const hasSchema = !isHandler(schemaOrHandler);
157
+ const schema = hasSchema ? schemaOrHandler : {};
158
+ const handler = hasSchema
159
+ ? maybeHandler
160
+ : schemaOrHandler;
161
+ // 预编译 schema
162
+ if (schema.body ||
163
+ schema.query ||
164
+ schema.params ||
165
+ schema.headers ||
166
+ schema.cookies) {
167
+ precompileSchemasUltra(schema);
168
+ }
169
+ return async (req) => {
170
+ try {
171
+ // 解析请求数据
172
+ const query = parseQuery(req);
173
+ const headers = parseHeaders(req);
174
+ const cookies = parseCookies(req);
175
+ const params = req.params || {};
176
+ // 解析请求体
177
+ let body = undefined;
178
+ if (req.method !== "GET" && req.method !== "HEAD") {
179
+ const [, parsedBody] = await goAwait(parseBody(req));
180
+ body = parsedBody;
181
+ }
182
+ // 验证 schema
183
+ const data = { body, query, params, headers, cookies };
184
+ if (schema.body ||
185
+ schema.query ||
186
+ schema.params ||
187
+ schema.headers ||
188
+ schema.cookies) {
189
+ validateAllSchemasUltra(schema, data);
190
+ }
191
+ // 获取中间件注入的额外数据
192
+ const extras = (req.__locals ??
193
+ {});
194
+ // 调用 handler
195
+ const result = await handler({
196
+ req,
197
+ body: body,
198
+ query: query,
199
+ params: params,
200
+ headers: headers,
201
+ cookies: cookies,
202
+ ...extras,
203
+ });
204
+ return autoResponse(result);
205
+ }
206
+ catch (error) {
207
+ if (error instanceof Error && error.message.includes("验证失败")) {
208
+ return handleValidationError(error);
209
+ }
210
+ return handleInternalError(error);
211
+ }
212
+ };
213
+ }
214
+ /**
215
+ * 简单的路由处理器 (无 schema 验证,只有 req)
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * simpleHandler(({ req }) => {
220
+ * return { message: "Hello World" };
221
+ * })
222
+ * ```
223
+ */
224
+ export function simpleHandler(handler) {
225
+ return async (req) => {
226
+ try {
227
+ const result = await handler({ req });
228
+ return autoResponse(result);
229
+ }
230
+ catch (error) {
231
+ return handleInternalError(error);
232
+ }
233
+ };
234
+ }
@@ -16,10 +16,16 @@ export class DependencyManager {
16
16
  let deps;
17
17
  switch (framework) {
18
18
  case "vue":
19
- deps = await Promise.all([import("vue"), import("@vue/server-renderer")]);
19
+ deps = await Promise.all([
20
+ import("vue"),
21
+ import("@vue/server-renderer"),
22
+ ]);
20
23
  break;
21
24
  case "react":
22
- deps = await Promise.all([import("react"), import("react-dom/server")]);
25
+ deps = await Promise.all([
26
+ import("react"),
27
+ import("react-dom/server"),
28
+ ]);
23
29
  break;
24
30
  default:
25
31
  throw new Error(`不支持的框架: ${framework}`);
@@ -26,8 +26,5 @@
26
26
  export function goAwait(promise) {
27
27
  return promise
28
28
  .then((data) => [null, data])
29
- .catch((err) => [
30
- err instanceof Error ? err : new Error(String(err)),
31
- undefined,
32
- ]);
29
+ .catch((err) => [err instanceof Error ? err : new Error(String(err)), undefined]);
33
30
  }
@@ -8,3 +8,4 @@ export declare function setCookie(key: string, value: string, options?: {
8
8
  secure?: boolean;
9
9
  }): string;
10
10
  export declare function setLocals<T extends object>(req: Request, extras: T): void;
11
+ export declare function getLocals<T extends object>(req: Request): T;
@@ -22,3 +22,8 @@ export function setLocals(req, extras) {
22
22
  const target = req;
23
23
  target.__locals = { ...(target.__locals ?? {}), ...extras };
24
24
  }
25
+ // 获取中间件注入的局部上下文
26
+ export function getLocals(req) {
27
+ const target = req;
28
+ return (target.__locals ?? {});
29
+ }
@@ -1,10 +1,12 @@
1
- export * from "./handle";
2
- export * from "./parsers";
3
- export * from "./response";
4
- export * from "./base64url";
5
- export * from "./go-await";
6
- export * from "./route-handler-factory";
7
- export * from "./path-matcher";
8
- export * from "./html-renderer";
9
- export * from "./dependency-manager";
10
- export * from "./request-validator";
1
+ /**
2
+ * 工具函数模块导出
3
+ */
4
+ export { createHandler, createHandlerWithExtra, simpleHandler, } from "./create-handler";
5
+ export { parseBody, parseQuery, parseHeaders, parseCookies } from "./parsers";
6
+ export { json, text, html, redirect, empty, stream } from "./response";
7
+ export { goAwait } from "./go-await";
8
+ export { base64urlEncode, base64urlDecode } from "./base64url";
9
+ export { setLocals, getLocals } from "./handle";
10
+ export { parseRequest, validateRequest, parseAndValidateRequest, createRequestValidator, } from "./request-validator";
11
+ export { HtmlRenderer } from "./html-renderer";
12
+ export { DependencyManager } from "./dependency-manager";