vafast 0.1.10 → 0.1.12
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/dist/auth/token.d.ts +40 -0
- package/dist/auth/token.js +124 -0
- package/dist/defineRoute.d.ts +2 -0
- package/dist/defineRoute.js +3 -0
- package/dist/index.d.ts +14 -459
- package/dist/index.js +14 -1400
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +14 -0
- package/dist/middleware/auth.js +106 -0
- package/dist/middleware/authMiddleware.d.ts +2 -0
- package/dist/middleware/authMiddleware.js +13 -0
- package/dist/middleware/component-renderer.d.ts +6 -0
- package/dist/middleware/component-renderer.js +136 -0
- package/dist/middleware/component-router.d.ts +10 -0
- package/dist/middleware/component-router.js +39 -0
- package/dist/middleware/cors.d.ts +9 -0
- package/dist/middleware/cors.js +30 -0
- package/dist/middleware/rateLimit.d.ts +8 -0
- package/dist/middleware/rateLimit.js +33 -0
- package/dist/middleware.d.ts +18 -0
- package/dist/middleware.js +51 -0
- package/dist/monitoring/index.d.ts +29 -0
- package/dist/monitoring/index.js +24 -0
- package/dist/monitoring/native-monitor.d.ts +38 -0
- package/dist/monitoring/native-monitor.js +176 -0
- package/dist/monitoring/types.d.ts +146 -0
- package/dist/monitoring/types.js +8 -0
- package/dist/router.d.ts +17 -0
- package/dist/router.js +74 -0
- package/dist/server/base-server.d.ts +38 -0
- package/dist/server/base-server.js +167 -0
- package/dist/server/component-server.d.ts +32 -0
- package/dist/server/component-server.js +146 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +9 -0
- package/dist/server/server-factory.d.ts +42 -0
- package/dist/server/server-factory.js +70 -0
- package/dist/server/server.d.ts +7 -0
- package/dist/server/server.js +73 -0
- package/dist/types/component-route.d.ts +25 -0
- package/dist/types/component-route.js +1 -0
- package/dist/types/route.d.ts +37 -0
- package/dist/types/route.js +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +1 -0
- package/dist/utils/base64url.d.ts +2 -0
- package/dist/utils/base64url.js +11 -0
- package/dist/utils/dependency-manager.d.ts +23 -0
- package/dist/utils/dependency-manager.js +67 -0
- package/dist/utils/go-await.d.ts +26 -0
- package/dist/utils/go-await.js +33 -0
- package/dist/utils/handle.d.ts +10 -0
- package/dist/utils/handle.js +24 -0
- package/dist/utils/html-renderer.d.ts +18 -0
- package/dist/utils/html-renderer.js +64 -0
- package/dist/utils/parsers.d.ts +36 -0
- package/dist/utils/parsers.js +126 -0
- package/dist/utils/path-matcher.d.ts +23 -0
- package/dist/utils/path-matcher.js +82 -0
- package/dist/utils/request-validator.d.ts +63 -0
- package/dist/utils/request-validator.js +94 -0
- package/dist/utils/response.d.ts +12 -0
- package/dist/utils/response.js +69 -0
- package/dist/utils/route-handler-factory.d.ts +50 -0
- package/dist/utils/route-handler-factory.js +181 -0
- package/dist/utils/validators/schema-validator.d.ts +66 -0
- package/dist/utils/validators/schema-validator.js +222 -0
- package/dist/utils/validators/schema-validators-ultra.d.ts +51 -0
- package/dist/utils/validators/schema-validators-ultra.js +289 -0
- package/dist/utils/validators/validators.d.ts +30 -0
- package/dist/utils/validators/validators.js +54 -0
- package/package.json +3 -4
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 请求解析和验证器
|
|
3
|
+
*
|
|
4
|
+
* 解析handler的req参数,使用Ultra验证器进行验证,
|
|
5
|
+
* 并类型安全地返回解析出来的值
|
|
6
|
+
*
|
|
7
|
+
* @author Framework Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { validateAllSchemasUltra, } from "./validators/schema-validators-ultra";
|
|
12
|
+
import { parseBody, parseQuery, parseHeaders, parseCookies } from "./parsers";
|
|
13
|
+
/**
|
|
14
|
+
* 解析Request对象,提取所有相关数据
|
|
15
|
+
* @param request Request对象
|
|
16
|
+
* @param params 路径参数(可选)
|
|
17
|
+
* @returns 解析后的请求数据
|
|
18
|
+
*/
|
|
19
|
+
export async function parseRequest(request, params) {
|
|
20
|
+
const requestData = {
|
|
21
|
+
body: undefined,
|
|
22
|
+
query: parseQuery(request),
|
|
23
|
+
params: params || {},
|
|
24
|
+
headers: parseHeaders(request),
|
|
25
|
+
cookies: parseCookies(request),
|
|
26
|
+
};
|
|
27
|
+
// 对于非GET请求,尝试解析请求体
|
|
28
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
29
|
+
requestData.body = await parseBody(request);
|
|
30
|
+
}
|
|
31
|
+
return requestData;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 验证请求数据
|
|
35
|
+
* @param config Schema配置
|
|
36
|
+
* @param requestData 请求数据
|
|
37
|
+
* @returns 验证结果
|
|
38
|
+
*/
|
|
39
|
+
export function validateRequest(config, requestData) {
|
|
40
|
+
try {
|
|
41
|
+
const validatedData = validateAllSchemasUltra(config, requestData);
|
|
42
|
+
return {
|
|
43
|
+
success: true,
|
|
44
|
+
data: validatedData,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
errors: [
|
|
51
|
+
{
|
|
52
|
+
field: "unknown",
|
|
53
|
+
message: error instanceof Error ? error.message : "验证失败",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 完整的请求解析和验证流程
|
|
61
|
+
* @param request Request对象
|
|
62
|
+
* @param config Schema配置
|
|
63
|
+
* @param params 路径参数(可选)
|
|
64
|
+
* @returns 验证结果
|
|
65
|
+
*/
|
|
66
|
+
export async function parseAndValidateRequest(request, config, params) {
|
|
67
|
+
try {
|
|
68
|
+
// 1. 解析请求
|
|
69
|
+
const requestData = await parseRequest(request, params);
|
|
70
|
+
// 2. 验证数据
|
|
71
|
+
return validateRequest(config, requestData);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
errors: [
|
|
77
|
+
{
|
|
78
|
+
field: "unknown",
|
|
79
|
+
message: error instanceof Error ? error.message : "请求解析失败",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 创建类型安全的请求验证器工厂
|
|
87
|
+
* @param config Schema配置
|
|
88
|
+
* @returns 验证器函数
|
|
89
|
+
*/
|
|
90
|
+
export function createRequestValidator(config) {
|
|
91
|
+
return async (request, params) => {
|
|
92
|
+
return parseAndValidateRequest(request, config, params);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** 生成 JSON 响应 */
|
|
2
|
+
export declare function json(data: unknown, status?: number, headers?: HeadersInit): Response;
|
|
3
|
+
/** 生成重定向响应 */
|
|
4
|
+
export declare function redirect(location: string, status?: 301 | 302): Response;
|
|
5
|
+
/** 生成纯文本响应 */
|
|
6
|
+
export declare function text(content: string, status?: number, headers?: HeadersInit): Response;
|
|
7
|
+
/** 生成HTML响应 */
|
|
8
|
+
export declare function html(content: string, status?: number, headers?: HeadersInit): Response;
|
|
9
|
+
/** 生成空响应(204 No Content) */
|
|
10
|
+
export declare function empty(status?: number, headers?: HeadersInit): Response;
|
|
11
|
+
/** 生成流式响应 */
|
|
12
|
+
export declare function stream(stream: ReadableStream, status?: number, headers?: HeadersInit): Response;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// src/response.ts
|
|
2
|
+
/** 生成 JSON 响应 */
|
|
3
|
+
export function json(data, status = 200, headers = {}) {
|
|
4
|
+
// 优化:只在有自定义 headers 时才创建 Headers 对象
|
|
5
|
+
if (Object.keys(headers).length === 0) {
|
|
6
|
+
return new Response(JSON.stringify(data), {
|
|
7
|
+
status,
|
|
8
|
+
headers: { "Content-Type": "application/json" },
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
// 有自定义 headers 时才创建 Headers 对象
|
|
12
|
+
const h = new Headers({
|
|
13
|
+
"Content-Type": "application/json",
|
|
14
|
+
...headers,
|
|
15
|
+
});
|
|
16
|
+
return new Response(JSON.stringify(data), {
|
|
17
|
+
status,
|
|
18
|
+
headers: h,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/** 生成重定向响应 */
|
|
22
|
+
export function redirect(location, status = 302) {
|
|
23
|
+
return new Response(null, {
|
|
24
|
+
status,
|
|
25
|
+
headers: {
|
|
26
|
+
Location: location,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** 生成纯文本响应 */
|
|
31
|
+
export function text(content, status = 200, headers = {}) {
|
|
32
|
+
const h = new Headers({
|
|
33
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
34
|
+
...headers,
|
|
35
|
+
});
|
|
36
|
+
return new Response(content, {
|
|
37
|
+
status,
|
|
38
|
+
headers: h,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** 生成HTML响应 */
|
|
42
|
+
export function html(content, status = 200, headers = {}) {
|
|
43
|
+
const h = new Headers({
|
|
44
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
45
|
+
...headers,
|
|
46
|
+
});
|
|
47
|
+
return new Response(content, {
|
|
48
|
+
status,
|
|
49
|
+
headers: h,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** 生成空响应(204 No Content) */
|
|
53
|
+
export function empty(status = 204, headers = {}) {
|
|
54
|
+
return new Response(null, {
|
|
55
|
+
status,
|
|
56
|
+
headers,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** 生成流式响应 */
|
|
60
|
+
export function stream(stream, status = 200, headers = {}) {
|
|
61
|
+
const h = new Headers({
|
|
62
|
+
"Content-Type": "application/octet-stream",
|
|
63
|
+
...headers,
|
|
64
|
+
});
|
|
65
|
+
return new Response(stream, {
|
|
66
|
+
status,
|
|
67
|
+
headers: h,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 路由处理器工厂
|
|
3
|
+
*
|
|
4
|
+
* 负责创建和配置路由处理器,处理请求数据解析和验证
|
|
5
|
+
* 提供统一的错误处理和响应格式
|
|
6
|
+
*
|
|
7
|
+
* @author Framework Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { type SchemaConfig } from "./validators/schema-validators-ultra";
|
|
12
|
+
import type { Static } from "@sinclair/typebox";
|
|
13
|
+
export interface TypedConfig extends SchemaConfig {
|
|
14
|
+
docs?: any;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
maxBodySize?: string;
|
|
17
|
+
validationErrorHandler?: ValidationErrorHandler;
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
}
|
|
20
|
+
export type ValidationErrorHandler = (error: Error, field: string, value: any, schema: any) => Response | Promise<Response>;
|
|
21
|
+
export type TypedHandler<TBody = any, TQuery = any, TParams = any, THeaders = any, TCookies = any, TExtra extends object = {}> = (ctx: {
|
|
22
|
+
req: Request;
|
|
23
|
+
body: TBody;
|
|
24
|
+
query: TQuery;
|
|
25
|
+
params: TParams;
|
|
26
|
+
headers: THeaders;
|
|
27
|
+
cookies: TCookies;
|
|
28
|
+
} & TExtra) => Response | Promise<Response> | any | Promise<any>;
|
|
29
|
+
export declare function createRouteHandler<TConfig extends TypedConfig, TBody = TConfig extends {
|
|
30
|
+
body: any;
|
|
31
|
+
} ? Static<TConfig["body"]> : any, TQuery = TConfig extends {
|
|
32
|
+
query: any;
|
|
33
|
+
} ? Static<TConfig["query"]> : any, TParams = TConfig extends {
|
|
34
|
+
params: any;
|
|
35
|
+
} ? Static<TConfig["params"]> : any, THeaders = TConfig extends {
|
|
36
|
+
headers: any;
|
|
37
|
+
} ? Static<TConfig["headers"]> : any, TCookies = TConfig extends {
|
|
38
|
+
cookies: any;
|
|
39
|
+
} ? Static<TConfig["cookies"]> : any, TExtra extends object = {}>(handler: TypedHandler<TBody, TQuery, TParams, THeaders, TCookies, TExtra>, config?: TConfig): (req: Request) => Promise<Response>;
|
|
40
|
+
export declare function withExtra<TExtra extends object = {}>(): <TConfig extends TypedConfig>(config: TConfig, handler: TypedHandler<TConfig extends {
|
|
41
|
+
body: any;
|
|
42
|
+
} ? Static<TConfig["body"]> : any, TConfig extends {
|
|
43
|
+
query: any;
|
|
44
|
+
} ? Static<TConfig["query"]> : any, TConfig extends {
|
|
45
|
+
params: any;
|
|
46
|
+
} ? Static<TConfig["params"]> : any, TConfig extends {
|
|
47
|
+
headers: any;
|
|
48
|
+
} ? Static<TConfig["headers"]> : any, TConfig extends {
|
|
49
|
+
cookies: any;
|
|
50
|
+
} ? Static<TConfig["cookies"]> : any, TExtra>) => (req: Request) => Promise<Response>;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 路由处理器工厂
|
|
3
|
+
*
|
|
4
|
+
* 负责创建和配置路由处理器,处理请求数据解析和验证
|
|
5
|
+
* 提供统一的错误处理和响应格式
|
|
6
|
+
*
|
|
7
|
+
* @author Framework Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { parseQuery, parseHeaders, parseCookies, parseBody } from "./parsers";
|
|
12
|
+
import { goAwait } from "./go-await";
|
|
13
|
+
import { json } from "./response";
|
|
14
|
+
import { validateAllSchemasUltra, precompileSchemasUltra, } from "./validators/schema-validators-ultra";
|
|
15
|
+
// 默认验证错误处理器
|
|
16
|
+
const defaultValidationErrorHandler = (error, field, value, schema) => {
|
|
17
|
+
return json({
|
|
18
|
+
success: false,
|
|
19
|
+
error: "Validation Error",
|
|
20
|
+
message: error instanceof Error ? error.message : "验证失败",
|
|
21
|
+
field,
|
|
22
|
+
receivedValue: value,
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
}, 400);
|
|
25
|
+
};
|
|
26
|
+
// 预定义的常用响应头,避免重复创建
|
|
27
|
+
const TEXT_HEADERS = { "Content-Type": "text/plain; charset=utf-8" };
|
|
28
|
+
const JSON_HEADERS = { "Content-Type": "application/json" };
|
|
29
|
+
const EMPTY_RESPONSE_204 = new Response(null, { status: 204 });
|
|
30
|
+
// 超高性能的 Response 自动转换函数 - 生产环境推荐使用
|
|
31
|
+
function autoResponseUltra(result) {
|
|
32
|
+
// 快速路径:已经是 Response 对象
|
|
33
|
+
if (result instanceof Response) {
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
// 快速路径:null/undefined - 复用预创建的对象
|
|
37
|
+
if (result === null || result === undefined) {
|
|
38
|
+
return EMPTY_RESPONSE_204;
|
|
39
|
+
}
|
|
40
|
+
// 使用 switch 语句优化类型检查
|
|
41
|
+
switch (typeof result) {
|
|
42
|
+
case "string":
|
|
43
|
+
// 优化:复用预定义的头部对象
|
|
44
|
+
return new Response(result, { headers: TEXT_HEADERS });
|
|
45
|
+
case "number":
|
|
46
|
+
case "boolean":
|
|
47
|
+
// 优化:使用更高效的字符串转换,复用头部
|
|
48
|
+
return new Response(result.toString(), { headers: TEXT_HEADERS });
|
|
49
|
+
case "object":
|
|
50
|
+
// 检查是否是 { data, status, headers } 格式
|
|
51
|
+
if ("data" in result) {
|
|
52
|
+
const { data, status = 200, headers = {} } = result;
|
|
53
|
+
// 无内容
|
|
54
|
+
if (data === null || data === undefined) {
|
|
55
|
+
return new Response("", {
|
|
56
|
+
status: status === 200 ? 204 : status,
|
|
57
|
+
headers,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// 纯文本类型
|
|
61
|
+
if (typeof data === "string" ||
|
|
62
|
+
typeof data === "number" ||
|
|
63
|
+
typeof data === "boolean") {
|
|
64
|
+
// 优化:减少对象展开操作,直接构建最终对象
|
|
65
|
+
const finalHeaders = {
|
|
66
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
67
|
+
...headers,
|
|
68
|
+
};
|
|
69
|
+
return new Response(data.toString(), {
|
|
70
|
+
status,
|
|
71
|
+
headers: finalHeaders,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// JSON 类型 - 复用 json 函数
|
|
75
|
+
return json(data, status, headers);
|
|
76
|
+
}
|
|
77
|
+
// 普通对象/数组,复用 json 函数
|
|
78
|
+
return json(result);
|
|
79
|
+
default:
|
|
80
|
+
// 其他类型(如 symbol, function 等)
|
|
81
|
+
return EMPTY_RESPONSE_204;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 创建路由处理器的通用函数
|
|
85
|
+
export function createRouteHandler(handler, config = {}) {
|
|
86
|
+
// 检查哪些验证器是必需的
|
|
87
|
+
const hasBodySchema = config.body !== undefined;
|
|
88
|
+
const hasQuerySchema = config.query !== undefined;
|
|
89
|
+
const hasParamsSchema = config.params !== undefined;
|
|
90
|
+
const hasHeadersSchema = config.headers !== undefined;
|
|
91
|
+
const hasCookiesSchema = config.cookies !== undefined;
|
|
92
|
+
// 只在有验证器时预编译Schema
|
|
93
|
+
if (hasBodySchema ||
|
|
94
|
+
hasQuerySchema ||
|
|
95
|
+
hasParamsSchema ||
|
|
96
|
+
hasHeadersSchema ||
|
|
97
|
+
hasCookiesSchema) {
|
|
98
|
+
precompileSchemasUltra(config);
|
|
99
|
+
}
|
|
100
|
+
// 获取验证错误处理器
|
|
101
|
+
const errorHandler = config.validationErrorHandler || defaultValidationErrorHandler;
|
|
102
|
+
return async (req) => {
|
|
103
|
+
try {
|
|
104
|
+
let queryObj = {};
|
|
105
|
+
let headers = {};
|
|
106
|
+
let cookies = {};
|
|
107
|
+
let body = undefined;
|
|
108
|
+
let params = {};
|
|
109
|
+
// 默认总是解析所有数据,只有在有验证器时才进行验证
|
|
110
|
+
queryObj = parseQuery(req);
|
|
111
|
+
headers = parseHeaders(req);
|
|
112
|
+
cookies = parseCookies(req);
|
|
113
|
+
// 总是解析 body
|
|
114
|
+
const [, parsedBody] = await goAwait(parseBody(req));
|
|
115
|
+
body = parsedBody;
|
|
116
|
+
// 总是尝试获取路径参数
|
|
117
|
+
params = (req.pathParams ||
|
|
118
|
+
req.params ||
|
|
119
|
+
{});
|
|
120
|
+
// 只在有验证器时执行验证
|
|
121
|
+
if (hasBodySchema ||
|
|
122
|
+
hasQuerySchema ||
|
|
123
|
+
hasParamsSchema ||
|
|
124
|
+
hasHeadersSchema ||
|
|
125
|
+
hasCookiesSchema) {
|
|
126
|
+
const data = { body, query: queryObj, params, headers, cookies };
|
|
127
|
+
validateAllSchemasUltra(config, data);
|
|
128
|
+
}
|
|
129
|
+
// 合并中间件注入的本地上下文
|
|
130
|
+
const extras = (req.__locals ?? {});
|
|
131
|
+
// 调用处理器,传递上下文
|
|
132
|
+
const result = await handler({
|
|
133
|
+
req,
|
|
134
|
+
body,
|
|
135
|
+
query: queryObj,
|
|
136
|
+
params,
|
|
137
|
+
headers,
|
|
138
|
+
cookies,
|
|
139
|
+
...extras,
|
|
140
|
+
});
|
|
141
|
+
return autoResponseUltra(result);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// 使用用户自定义的验证错误处理器
|
|
145
|
+
if (error instanceof Error && error.message.includes("验证失败")) {
|
|
146
|
+
// 尝试提取字段信息
|
|
147
|
+
const field = extractFieldFromError(error);
|
|
148
|
+
const value = extractValueFromError(error);
|
|
149
|
+
const schema = extractSchemaFromError(error);
|
|
150
|
+
return await errorHandler(error, field, value, schema);
|
|
151
|
+
}
|
|
152
|
+
// 其他错误使用默认处理
|
|
153
|
+
return json({
|
|
154
|
+
success: false,
|
|
155
|
+
error: "Internal Error",
|
|
156
|
+
message: error instanceof Error ? error.message : "未知错误",
|
|
157
|
+
}, 500);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// 从错误中提取字段信息的辅助函数
|
|
162
|
+
function extractFieldFromError(error) {
|
|
163
|
+
// 尝试从错误消息中提取字段名
|
|
164
|
+
const fieldMatch = error.message.match(/字段\s*(\w+)/);
|
|
165
|
+
return fieldMatch ? fieldMatch[1] : "unknown";
|
|
166
|
+
}
|
|
167
|
+
// 从错误中提取值的辅助函数
|
|
168
|
+
function extractValueFromError(error) {
|
|
169
|
+
// 这里可以根据实际错误类型提取值
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
// 从错误中提取Schema的辅助函数
|
|
173
|
+
function extractSchemaFromError(error) {
|
|
174
|
+
// 这里可以根据实际错误类型提取Schema
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
export function withExtra() {
|
|
178
|
+
return function withExtraHandler(config, handler) {
|
|
179
|
+
return createRouteHandler(handler, config);
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema配置验证器
|
|
3
|
+
*
|
|
4
|
+
* 使用validateSchema函数对SchemaConfig结构的数据进行验证
|
|
5
|
+
* 提供统一的验证接口和错误处理
|
|
6
|
+
*
|
|
7
|
+
* @author Framework Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import type { TSchema } from "@sinclair/typebox";
|
|
12
|
+
import { type ValidationResult } from "./validators";
|
|
13
|
+
export interface SchemaConfig {
|
|
14
|
+
body?: TSchema;
|
|
15
|
+
query?: TSchema;
|
|
16
|
+
params?: TSchema;
|
|
17
|
+
headers?: TSchema;
|
|
18
|
+
cookies?: TSchema;
|
|
19
|
+
}
|
|
20
|
+
export interface RequestData {
|
|
21
|
+
body?: unknown;
|
|
22
|
+
query?: unknown;
|
|
23
|
+
params?: unknown;
|
|
24
|
+
headers?: unknown;
|
|
25
|
+
cookies?: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface SchemaValidationResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
data?: {
|
|
30
|
+
body?: unknown;
|
|
31
|
+
query?: unknown;
|
|
32
|
+
params?: unknown;
|
|
33
|
+
headers?: unknown;
|
|
34
|
+
cookies?: unknown;
|
|
35
|
+
};
|
|
36
|
+
errors?: Array<{
|
|
37
|
+
field: keyof SchemaConfig;
|
|
38
|
+
error: ValidationResult<unknown>;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 使用SchemaConfig验证完整的请求数据
|
|
43
|
+
* @param config Schema配置
|
|
44
|
+
* @param data 请求数据
|
|
45
|
+
* @returns 验证结果
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateSchemaConfig(config: SchemaConfig, data: RequestData): SchemaValidationResult;
|
|
48
|
+
/**
|
|
49
|
+
* 异步验证SchemaConfig(支持异步验证器)
|
|
50
|
+
* @param config Schema配置
|
|
51
|
+
* @param data 请求数据
|
|
52
|
+
* @returns Promise<验证结果>
|
|
53
|
+
*/
|
|
54
|
+
export declare function validateSchemaConfigAsync(config: SchemaConfig, data: RequestData): Promise<SchemaValidationResult>;
|
|
55
|
+
/**
|
|
56
|
+
* 创建验证器工厂函数
|
|
57
|
+
* @param config Schema配置
|
|
58
|
+
* @returns 验证器函数
|
|
59
|
+
*/
|
|
60
|
+
export declare function createSchemaValidator(config: SchemaConfig): (data: RequestData) => SchemaValidationResult;
|
|
61
|
+
/**
|
|
62
|
+
* 创建异步验证器工厂函数
|
|
63
|
+
* @param config Schema配置
|
|
64
|
+
* @returns 异步验证器函数
|
|
65
|
+
*/
|
|
66
|
+
export declare function createAsyncSchemaValidator(config: SchemaConfig): (data: RequestData) => Promise<SchemaValidationResult>;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema配置验证器
|
|
3
|
+
*
|
|
4
|
+
* 使用validateSchema函数对SchemaConfig结构的数据进行验证
|
|
5
|
+
* 提供统一的验证接口和错误处理
|
|
6
|
+
*
|
|
7
|
+
* @author Framework Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { validateSchema } from "./validators";
|
|
12
|
+
/**
|
|
13
|
+
* 验证单个Schema配置项
|
|
14
|
+
* @param schema Schema定义
|
|
15
|
+
* @param data 要验证的数据
|
|
16
|
+
* @param fieldName 字段名称(用于错误标识)
|
|
17
|
+
* @returns 验证结果
|
|
18
|
+
*/
|
|
19
|
+
function validateSingleSchema(schema, data, fieldName) {
|
|
20
|
+
return validateSchema(schema, data);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 使用SchemaConfig验证完整的请求数据
|
|
24
|
+
* @param config Schema配置
|
|
25
|
+
* @param data 请求数据
|
|
26
|
+
* @returns 验证结果
|
|
27
|
+
*/
|
|
28
|
+
export function validateSchemaConfig(config, data) {
|
|
29
|
+
const errors = [];
|
|
30
|
+
const validatedData = {};
|
|
31
|
+
// 验证body
|
|
32
|
+
if (config.body && data.body !== undefined) {
|
|
33
|
+
const result = validateSingleSchema(config.body, data.body, "body");
|
|
34
|
+
if (result.success) {
|
|
35
|
+
validatedData.body = result.data;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
errors.push({ field: "body", error: result });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (data.body !== undefined) {
|
|
42
|
+
validatedData.body = data.body;
|
|
43
|
+
}
|
|
44
|
+
// 验证query
|
|
45
|
+
if (config.query && data.query !== undefined) {
|
|
46
|
+
const result = validateSingleSchema(config.query, data.query, "query");
|
|
47
|
+
if (result.success) {
|
|
48
|
+
validatedData.query = result.data;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
errors.push({ field: "query", error: result });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (data.query !== undefined) {
|
|
55
|
+
validatedData.query = data.query;
|
|
56
|
+
}
|
|
57
|
+
// 验证params
|
|
58
|
+
if (config.params && data.params !== undefined) {
|
|
59
|
+
const result = validateSingleSchema(config.params, data.params, "params");
|
|
60
|
+
if (result.success) {
|
|
61
|
+
validatedData.params = result.data;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
errors.push({ field: "params", error: result });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (data.params !== undefined) {
|
|
68
|
+
validatedData.params = data.params;
|
|
69
|
+
}
|
|
70
|
+
// 验证headers
|
|
71
|
+
if (config.headers && data.headers !== undefined) {
|
|
72
|
+
const result = validateSingleSchema(config.headers, data.headers, "headers");
|
|
73
|
+
if (result.success) {
|
|
74
|
+
validatedData.headers = result.data;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
errors.push({ field: "headers", error: result });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (data.headers !== undefined) {
|
|
81
|
+
validatedData.headers = data.headers;
|
|
82
|
+
}
|
|
83
|
+
// 验证cookies
|
|
84
|
+
if (config.cookies && data.cookies !== undefined) {
|
|
85
|
+
const result = validateSingleSchema(config.cookies, data.cookies, "cookies");
|
|
86
|
+
if (result.success) {
|
|
87
|
+
validatedData.cookies = result.data;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
errors.push({ field: "cookies", error: result });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (data.cookies !== undefined) {
|
|
94
|
+
validatedData.cookies = data.cookies;
|
|
95
|
+
}
|
|
96
|
+
// 添加所有未配置但存在的数据字段
|
|
97
|
+
if (data.body !== undefined && !config.body) {
|
|
98
|
+
validatedData.body = data.body;
|
|
99
|
+
}
|
|
100
|
+
if (data.query !== undefined && !config.query) {
|
|
101
|
+
validatedData.query = data.query;
|
|
102
|
+
}
|
|
103
|
+
if (data.params !== undefined && !config.params) {
|
|
104
|
+
validatedData.params = data.params;
|
|
105
|
+
}
|
|
106
|
+
if (data.headers !== undefined && !config.headers) {
|
|
107
|
+
validatedData.headers = data.headers;
|
|
108
|
+
}
|
|
109
|
+
if (data.cookies !== undefined && !config.cookies) {
|
|
110
|
+
validatedData.cookies = data.cookies;
|
|
111
|
+
}
|
|
112
|
+
// 如果有错误,返回失败结果
|
|
113
|
+
if (errors.length > 0) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
errors,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// 验证成功,返回验证后的数据
|
|
120
|
+
return {
|
|
121
|
+
success: true,
|
|
122
|
+
data: validatedData,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 异步验证SchemaConfig(支持异步验证器)
|
|
127
|
+
* @param config Schema配置
|
|
128
|
+
* @param data 请求数据
|
|
129
|
+
* @returns Promise<验证结果>
|
|
130
|
+
*/
|
|
131
|
+
export async function validateSchemaConfigAsync(config, data) {
|
|
132
|
+
const errors = [];
|
|
133
|
+
const validatedData = {};
|
|
134
|
+
// 并行验证所有Schema以提高性能
|
|
135
|
+
const validationPromises = [];
|
|
136
|
+
// 收集所有需要验证的字段
|
|
137
|
+
if (config.body && data.body !== undefined) {
|
|
138
|
+
validationPromises.push(Promise.resolve({
|
|
139
|
+
field: "body",
|
|
140
|
+
result: validateSingleSchema(config.body, data.body, "body"),
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
if (config.query && data.query !== undefined) {
|
|
144
|
+
validationPromises.push(Promise.resolve({
|
|
145
|
+
field: "query",
|
|
146
|
+
result: validateSingleSchema(config.query, data.query, "query"),
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
if (config.params && data.params !== undefined) {
|
|
150
|
+
validationPromises.push(Promise.resolve({
|
|
151
|
+
field: "params",
|
|
152
|
+
result: validateSingleSchema(config.params, data.params, "params"),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
if (config.headers && data.headers !== undefined) {
|
|
156
|
+
validationPromises.push(Promise.resolve({
|
|
157
|
+
field: "headers",
|
|
158
|
+
result: validateSingleSchema(config.headers, data.headers, "headers"),
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
if (config.cookies && data.cookies !== undefined) {
|
|
162
|
+
validationPromises.push(Promise.resolve({
|
|
163
|
+
field: "cookies",
|
|
164
|
+
result: validateSingleSchema(config.cookies, data.cookies, "cookies"),
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
// 等待所有验证完成
|
|
168
|
+
const results = await Promise.all(validationPromises);
|
|
169
|
+
// 处理验证结果
|
|
170
|
+
for (const { field, result } of results) {
|
|
171
|
+
if (result.success) {
|
|
172
|
+
validatedData[field] = result.data;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
errors.push({ field, error: result });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// 添加未验证但存在的数据
|
|
179
|
+
if (data.body !== undefined && !config.body)
|
|
180
|
+
validatedData.body = data.body;
|
|
181
|
+
if (data.query !== undefined && !config.query)
|
|
182
|
+
validatedData.query = data.query;
|
|
183
|
+
if (data.params !== undefined && !config.params)
|
|
184
|
+
validatedData.params = data.params;
|
|
185
|
+
if (data.headers !== undefined && !config.headers)
|
|
186
|
+
validatedData.headers = data.headers;
|
|
187
|
+
if (data.cookies !== undefined && !config.cookies)
|
|
188
|
+
validatedData.cookies = data.cookies;
|
|
189
|
+
// 如果有错误,返回失败结果
|
|
190
|
+
if (errors.length > 0) {
|
|
191
|
+
return {
|
|
192
|
+
success: false,
|
|
193
|
+
errors,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// 验证成功,返回验证后的数据
|
|
197
|
+
return {
|
|
198
|
+
success: true,
|
|
199
|
+
data: validatedData,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* 创建验证器工厂函数
|
|
204
|
+
* @param config Schema配置
|
|
205
|
+
* @returns 验证器函数
|
|
206
|
+
*/
|
|
207
|
+
export function createSchemaValidator(config) {
|
|
208
|
+
return (data) => {
|
|
209
|
+
return validateSchemaConfig(config, data);
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 创建异步验证器工厂函数
|
|
214
|
+
* @param config Schema配置
|
|
215
|
+
* @returns 异步验证器函数
|
|
216
|
+
*/
|
|
217
|
+
export function createAsyncSchemaValidator(config) {
|
|
218
|
+
return (data) => {
|
|
219
|
+
return validateSchemaConfigAsync(config, data);
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
// 类型已经在上面定义并导出,无需重复导出
|