vafast 0.3.1 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/token.d.ts +13 -11
- package/dist/auth/token.js +118 -111
- package/dist/auth/token.js.map +1 -0
- package/dist/defineRoute.d.ts +5 -2
- package/dist/defineRoute.js +7 -2
- package/dist/defineRoute.js.map +1 -0
- package/dist/index.d.ts +30 -14
- package/dist/index.js +2247 -15
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +8 -6
- package/dist/middleware/auth.js +198 -99
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/authMiddleware.d.ts +5 -2
- package/dist/middleware/authMiddleware.js +55 -11
- package/dist/middleware/authMiddleware.js.map +1 -0
- package/dist/middleware/component-renderer.d.ts +4 -2
- package/dist/middleware/component-renderer.js +87 -80
- package/dist/middleware/component-renderer.js.map +1 -0
- package/dist/middleware/component-router.d.ts +8 -3
- package/dist/middleware/component-router.js +33 -39
- package/dist/middleware/component-router.js.map +1 -0
- package/dist/middleware/cors.d.ts +6 -3
- package/dist/middleware/cors.js +42 -29
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +5 -3
- package/dist/middleware/rateLimit.js +45 -29
- package/dist/middleware/rateLimit.js.map +1 -0
- package/dist/middleware.d.ts +6 -3
- package/dist/middleware.js +97 -51
- package/dist/middleware.js.map +1 -0
- package/dist/monitoring/index.d.ts +11 -4
- package/dist/monitoring/index.js +1299 -17
- package/dist/monitoring/index.js.map +1 -0
- package/dist/monitoring/native-monitor.d.ts +12 -6
- package/dist/monitoring/native-monitor.js +1258 -161
- package/dist/monitoring/native-monitor.js.map +1 -0
- package/dist/monitoring/types.d.ts +8 -6
- package/dist/monitoring/types.js +1 -1
- package/dist/monitoring/types.js.map +1 -0
- package/dist/node-server/index.d.ts +4 -22
- package/dist/node-server/index.js +254 -21
- package/dist/node-server/index.js.map +1 -0
- package/dist/node-server/request.d.ts +6 -2
- package/dist/node-server/request.js +102 -134
- package/dist/node-server/request.js.map +1 -0
- package/dist/node-server/response.d.ts +7 -3
- package/dist/node-server/response.js +67 -89
- package/dist/node-server/response.js.map +1 -0
- package/dist/node-server/serve.d.ts +11 -7
- package/dist/node-server/serve.js +231 -82
- package/dist/node-server/serve.js.map +1 -0
- package/dist/router/index.d.ts +3 -5
- package/dist/router/index.js +228 -7
- package/dist/router/index.js.map +1 -0
- package/dist/router/radix-tree.d.ts +7 -4
- package/dist/router/radix-tree.js +186 -218
- package/dist/router/radix-tree.js.map +1 -0
- package/dist/router.d.ts +7 -3
- package/dist/router.js +37 -83
- package/dist/router.js.map +1 -0
- package/dist/serve.d.ts +2 -12
- package/dist/serve.js +237 -11
- package/dist/serve.js.map +1 -0
- package/dist/server/base-server.d.ts +5 -2
- package/dist/server/base-server.js +124 -135
- package/dist/server/base-server.js.map +1 -0
- package/dist/server/component-server.d.ts +9 -4
- package/dist/server/component-server.js +481 -139
- package/dist/server/component-server.js.map +1 -0
- package/dist/server/index.d.ts +8 -7
- package/dist/server/index.js +985 -11
- package/dist/server/index.js.map +1 -0
- package/dist/server/server-factory.d.ts +11 -5
- package/dist/server/server-factory.js +979 -67
- package/dist/server/server-factory.js.map +1 -0
- package/dist/server/server.d.ts +7 -3
- package/dist/server/server.js +553 -112
- package/dist/server/server.js.map +1 -0
- package/dist/types/component-route.d.ts +8 -4
- package/dist/types/component-route.js +1 -1
- package/dist/types/component-route.js.map +1 -0
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +21 -4
- package/dist/types/index.js.map +1 -0
- package/dist/types/route.d.ts +13 -10
- package/dist/types/route.js +10 -9
- package/dist/types/route.js.map +1 -0
- package/dist/types/schema.d.ts +11 -7
- package/dist/types/schema.js +1 -1
- package/dist/types/schema.js.map +1 -0
- package/dist/types/types.d.ts +11 -9
- package/dist/types/types.js +1 -1
- package/dist/types/types.js.map +1 -0
- package/dist/utils/base64url.d.ts +4 -2
- package/dist/utils/base64url.js +12 -9
- package/dist/utils/base64url.js.map +1 -0
- package/dist/utils/create-handler.d.ts +11 -7
- package/dist/utils/create-handler.js +393 -217
- package/dist/utils/create-handler.js.map +1 -0
- package/dist/utils/dependency-manager.d.ts +3 -1
- package/dist/utils/dependency-manager.js +67 -69
- package/dist/utils/dependency-manager.js.map +1 -0
- package/dist/utils/go-await.d.ts +3 -1
- package/dist/utils/go-await.js +8 -22
- package/dist/utils/go-await.js.map +1 -0
- package/dist/utils/handle.d.ts +6 -4
- package/dist/utils/handle.js +44 -25
- package/dist/utils/handle.js.map +1 -0
- package/dist/utils/html-renderer.d.ts +3 -1
- package/dist/utils/html-renderer.js +25 -24
- package/dist/utils/html-renderer.js.map +1 -0
- package/dist/utils/index.d.ts +13 -13
- package/dist/utils/index.js +832 -21
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/parsers.d.ts +15 -13
- package/dist/utils/parsers.js +138 -188
- package/dist/utils/parsers.js.map +1 -0
- package/dist/utils/path-matcher.d.ts +3 -1
- package/dist/utils/path-matcher.js +68 -78
- package/dist/utils/path-matcher.js.map +1 -0
- package/dist/utils/request-validator.d.ts +13 -10
- package/dist/utils/request-validator.js +234 -84
- package/dist/utils/request-validator.js.map +1 -0
- package/dist/utils/response.d.ts +9 -7
- package/dist/utils/response.js +93 -102
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/validators/schema-validator.d.ts +13 -9
- package/dist/utils/validators/schema-validator.js +228 -209
- package/dist/utils/validators/schema-validator.js.map +1 -0
- package/dist/utils/validators/schema-validators-ultra.d.ts +15 -12
- package/dist/utils/validators/schema-validators-ultra.js +233 -256
- package/dist/utils/validators/schema-validators-ultra.js.map +1 -0
- package/dist/utils/validators/validators.d.ts +15 -12
- package/dist/utils/validators/validators.js +81 -122
- package/dist/utils/validators/validators.js.map +1 -0
- package/package.json +5 -4
|
@@ -1,83 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (patternParts[i] !== pathParts[i] &&
|
|
17
|
-
!patternParts[i].startsWith(":")) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return true;
|
|
1
|
+
// src/utils/path-matcher.ts
|
|
2
|
+
var PathMatcher = class {
|
|
3
|
+
/**
|
|
4
|
+
* 路径匹配
|
|
5
|
+
*/
|
|
6
|
+
static matchPath(pattern, path) {
|
|
7
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
8
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
9
|
+
if (patternParts.length !== pathParts.length) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
13
|
+
if (patternParts[i] !== pathParts[i] && !patternParts[i].startsWith(":")) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 提取路径参数
|
|
21
|
+
*/
|
|
22
|
+
static extractParams(pattern, path) {
|
|
23
|
+
const params = {};
|
|
24
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
25
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
26
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
27
|
+
if (patternParts[i].startsWith(":")) {
|
|
28
|
+
const paramName = patternParts[i].slice(1);
|
|
29
|
+
params[paramName] = pathParts[i];
|
|
30
|
+
}
|
|
37
31
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// 更长的路径更具体,略微提升
|
|
54
|
-
return score * 10 + parts.length;
|
|
32
|
+
return params;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 计算路径特异性分数
|
|
36
|
+
* 用于路由排序:静态 > 动态(:param) > 通配符(*)
|
|
37
|
+
*/
|
|
38
|
+
static calculatePathScore(path) {
|
|
39
|
+
const parts = path.split("/").filter(Boolean);
|
|
40
|
+
let score = 0;
|
|
41
|
+
for (const p of parts) {
|
|
42
|
+
if (p === "*")
|
|
43
|
+
score += 1;
|
|
44
|
+
else if (p.startsWith(":"))
|
|
45
|
+
score += 2;
|
|
46
|
+
else score += 3;
|
|
55
47
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
!p1.startsWith("*") &&
|
|
70
|
-
!p2.startsWith(":") &&
|
|
71
|
-
!p2.startsWith("*") &&
|
|
72
|
-
p1 !== p2) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
// 如果一个是通配符,另一个是动态参数,可能冲突
|
|
76
|
-
if ((p1 === "*" && p2.startsWith(":")) ||
|
|
77
|
-
(p2 === "*" && p1.startsWith(":"))) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
48
|
+
return score * 10 + parts.length;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 判断两个路径是否可能冲突
|
|
52
|
+
*/
|
|
53
|
+
static pathsMayConflict(path1, path2) {
|
|
54
|
+
const parts1 = path1.split("/").filter(Boolean);
|
|
55
|
+
const parts2 = path2.split("/").filter(Boolean);
|
|
56
|
+
if (parts1.length !== parts2.length) return false;
|
|
57
|
+
for (let i = 0; i < parts1.length; i++) {
|
|
58
|
+
const p1 = parts1[i];
|
|
59
|
+
const p2 = parts2[i];
|
|
60
|
+
if (!p1.startsWith(":") && !p1.startsWith("*") && !p2.startsWith(":") && !p2.startsWith("*") && p1 !== p2) {
|
|
81
61
|
return false;
|
|
62
|
+
}
|
|
63
|
+
if (p1 === "*" && p2.startsWith(":") || p2 === "*" && p1.startsWith(":")) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
82
66
|
}
|
|
83
|
-
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export {
|
|
71
|
+
PathMatcher
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=path-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/path-matcher.ts"],"sourcesContent":["/**\n * 路径匹配工具类\n * 提供统一的路径匹配和参数提取功能\n */\nexport class PathMatcher {\n /**\n * 路径匹配\n */\n static matchPath(pattern: string, path: string): boolean {\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n if (patternParts.length !== pathParts.length) {\n return false;\n }\n\n for (let i = 0; i < patternParts.length; i++) {\n if (\n patternParts[i] !== pathParts[i] &&\n !patternParts[i].startsWith(\":\")\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * 提取路径参数\n */\n static extractParams(pattern: string, path: string): Record<string, string> {\n const params: Record<string, string> = {};\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const pathParts = path.split(\"/\").filter(Boolean);\n\n for (let i = 0; i < patternParts.length; i++) {\n if (patternParts[i].startsWith(\":\")) {\n const paramName = patternParts[i].slice(1);\n params[paramName] = pathParts[i];\n }\n }\n\n return params;\n }\n\n /**\n * 计算路径特异性分数\n * 用于路由排序:静态 > 动态(:param) > 通配符(*)\n */\n static calculatePathScore(path: string): number {\n const parts = path.split(\"/\").filter(Boolean);\n let score = 0;\n for (const p of parts) {\n if (p === \"*\")\n score += 1; // 最弱\n else if (p.startsWith(\":\"))\n score += 2; // 中等\n else score += 3; // 静态最强\n }\n // 更长的路径更具体,略微提升\n return score * 10 + parts.length;\n }\n\n /**\n * 判断两个路径是否可能冲突\n */\n static pathsMayConflict(path1: string, path2: string): boolean {\n const parts1 = path1.split(\"/\").filter(Boolean);\n const parts2 = path2.split(\"/\").filter(Boolean);\n\n if (parts1.length !== parts2.length) return false;\n\n for (let i = 0; i < parts1.length; i++) {\n const p1 = parts1[i];\n const p2 = parts2[i];\n\n // 如果两个部分都是静态的且不同,则不会冲突\n if (\n !p1.startsWith(\":\") &&\n !p1.startsWith(\"*\") &&\n !p2.startsWith(\":\") &&\n !p2.startsWith(\"*\") &&\n p1 !== p2\n ) {\n return false;\n }\n\n // 如果一个是通配符,另一个是动态参数,可能冲突\n if (\n (p1 === \"*\" && p2.startsWith(\":\")) ||\n (p2 === \"*\" && p1.startsWith(\":\"))\n ) {\n return true;\n }\n }\n\n return false;\n }\n}\n"],"mappings":";AAIO,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA,EAIvB,OAAO,UAAU,SAAiB,MAAuB;AACvD,UAAM,eAAe,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AACtD,UAAM,YAAY,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAEhD,QAAI,aAAa,WAAW,UAAU,QAAQ;AAC5C,aAAO;AAAA,IACT;AAEA,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UACE,aAAa,CAAC,MAAM,UAAU,CAAC,KAC/B,CAAC,aAAa,CAAC,EAAE,WAAW,GAAG,GAC/B;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,cAAc,SAAiB,MAAsC;AAC1E,UAAM,SAAiC,CAAC;AACxC,UAAM,eAAe,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AACtD,UAAM,YAAY,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAEhD,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UAAI,aAAa,CAAC,EAAE,WAAW,GAAG,GAAG;AACnC,cAAM,YAAY,aAAa,CAAC,EAAE,MAAM,CAAC;AACzC,eAAO,SAAS,IAAI,UAAU,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,MAAsB;AAC9C,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,QAAQ;AACZ,eAAW,KAAK,OAAO;AACrB,UAAI,MAAM;AACR,iBAAS;AAAA,eACF,EAAE,WAAW,GAAG;AACvB,iBAAS;AAAA,UACN,UAAS;AAAA,IAChB;AAEA,WAAO,QAAQ,KAAK,MAAM;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,iBAAiB,OAAe,OAAwB;AAC7D,UAAM,SAAS,MAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AAC9C,UAAM,SAAS,MAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AAE9C,QAAI,OAAO,WAAW,OAAO,OAAQ,QAAO;AAE5C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,KAAK,OAAO,CAAC;AACnB,YAAM,KAAK,OAAO,CAAC;AAGnB,UACE,CAAC,GAAG,WAAW,GAAG,KAClB,CAAC,GAAG,WAAW,GAAG,KAClB,CAAC,GAAG,WAAW,GAAG,KAClB,CAAC,GAAG,WAAW,GAAG,KAClB,OAAO,IACP;AACA,eAAO;AAAA,MACT;AAGA,UACG,OAAO,OAAO,GAAG,WAAW,GAAG,KAC/B,OAAO,OAAO,GAAG,WAAW,GAAG,GAChC;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { TSchema, Static } from '@sinclair/typebox';
|
|
2
|
+
import { SchemaConfig } from './validators/schema-validators-ultra.js';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* 请求解析和验证器
|
|
3
6
|
*
|
|
@@ -8,24 +11,22 @@
|
|
|
8
11
|
* @version 1.0.0
|
|
9
12
|
* @license MIT
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { type SchemaConfig } from "./validators/schema-validators-ultra";
|
|
14
|
-
export interface RequestData {
|
|
14
|
+
|
|
15
|
+
interface RequestData {
|
|
15
16
|
body: unknown;
|
|
16
17
|
query: unknown;
|
|
17
18
|
params: Record<string, string>;
|
|
18
19
|
headers: Record<string, string>;
|
|
19
20
|
cookies: Record<string, string>;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
interface ValidatedRequestData<T extends SchemaConfig> {
|
|
22
23
|
body: T["body"] extends TSchema ? Static<T["body"]> : unknown;
|
|
23
24
|
query: T["query"] extends TSchema ? Static<T["query"]> : unknown;
|
|
24
25
|
params: T["params"] extends TSchema ? Static<T["params"]> : Record<string, string>;
|
|
25
26
|
headers: T["headers"] extends TSchema ? Static<T["headers"]> : Record<string, string>;
|
|
26
27
|
cookies: T["cookies"] extends TSchema ? Static<T["cookies"]> : Record<string, string>;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
+
interface ValidationResult<T extends SchemaConfig> {
|
|
29
30
|
success: boolean;
|
|
30
31
|
data?: ValidatedRequestData<T>;
|
|
31
32
|
errors?: Array<{
|
|
@@ -39,14 +40,14 @@ export interface ValidationResult<T extends SchemaConfig> {
|
|
|
39
40
|
* @param params 路径参数(可选)
|
|
40
41
|
* @returns 解析后的请求数据
|
|
41
42
|
*/
|
|
42
|
-
|
|
43
|
+
declare function parseRequest(request: Request, params?: Record<string, string>): Promise<RequestData>;
|
|
43
44
|
/**
|
|
44
45
|
* 验证请求数据
|
|
45
46
|
* @param config Schema配置
|
|
46
47
|
* @param requestData 请求数据
|
|
47
48
|
* @returns 验证结果
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
+
declare function validateRequest<T extends SchemaConfig>(config: T, requestData: RequestData): ValidationResult<T>;
|
|
50
51
|
/**
|
|
51
52
|
* 完整的请求解析和验证流程
|
|
52
53
|
* @param request Request对象
|
|
@@ -54,10 +55,12 @@ export declare function validateRequest<T extends SchemaConfig>(config: T, reque
|
|
|
54
55
|
* @param params 路径参数(可选)
|
|
55
56
|
* @returns 验证结果
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
+
declare function parseAndValidateRequest<T extends SchemaConfig>(request: Request, config: T, params?: Record<string, string>): Promise<ValidationResult<T>>;
|
|
58
59
|
/**
|
|
59
60
|
* 创建类型安全的请求验证器工厂
|
|
60
61
|
* @param config Schema配置
|
|
61
62
|
* @returns 验证器函数
|
|
62
63
|
*/
|
|
63
|
-
|
|
64
|
+
declare function createRequestValidator<T extends SchemaConfig>(config: T): (request: Request, params?: Record<string, string>) => Promise<ValidationResult<T>>;
|
|
65
|
+
|
|
66
|
+
export { type RequestData, type ValidatedRequestData, type ValidationResult, createRequestValidator, parseAndValidateRequest, parseRequest, validateRequest };
|
|
@@ -1,3 +1,236 @@
|
|
|
1
|
+
// src/utils/validators/schema-validators-ultra.ts
|
|
2
|
+
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
3
|
+
var SCHEMA_FLAGS = {
|
|
4
|
+
BODY: 1 << 0,
|
|
5
|
+
// 1
|
|
6
|
+
QUERY: 1 << 1,
|
|
7
|
+
// 2
|
|
8
|
+
PARAMS: 1 << 2,
|
|
9
|
+
// 4
|
|
10
|
+
HEADERS: 1 << 3,
|
|
11
|
+
// 8
|
|
12
|
+
COOKIES: 1 << 4
|
|
13
|
+
// 16
|
|
14
|
+
};
|
|
15
|
+
var ultraSchemaCache = /* @__PURE__ */ new Map();
|
|
16
|
+
var errorPool = [];
|
|
17
|
+
var ERROR_POOL_SIZE = 200;
|
|
18
|
+
var errorMessagePool = /* @__PURE__ */ new Map();
|
|
19
|
+
var commonMessages = [
|
|
20
|
+
"\u8BF7\u6C42\u4F53\u9A8C\u8BC1\u5931\u8D25",
|
|
21
|
+
"Query\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25",
|
|
22
|
+
"\u8DEF\u5F84\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25",
|
|
23
|
+
"\u8BF7\u6C42\u5934\u9A8C\u8BC1\u5931\u8D25",
|
|
24
|
+
"Cookie\u9A8C\u8BC1\u5931\u8D25",
|
|
25
|
+
"\u7C7B\u578B\u9A8C\u8BC1\u5931\u8D25",
|
|
26
|
+
"Schema\u7F16\u8BD1\u5931\u8D25",
|
|
27
|
+
"\u672A\u77E5\u9519\u8BEF"
|
|
28
|
+
];
|
|
29
|
+
commonMessages.forEach((msg) => errorMessagePool.set(msg, msg));
|
|
30
|
+
for (let i = 0; i < ERROR_POOL_SIZE; i++) {
|
|
31
|
+
errorPool.push(new Error());
|
|
32
|
+
}
|
|
33
|
+
var errorPoolIndex = 0;
|
|
34
|
+
function getErrorFromPool(message) {
|
|
35
|
+
const error = errorPool[errorPoolIndex];
|
|
36
|
+
error.message = message;
|
|
37
|
+
errorPoolIndex = (errorPoolIndex + 1) % ERROR_POOL_SIZE;
|
|
38
|
+
return error;
|
|
39
|
+
}
|
|
40
|
+
function getPooledString(key) {
|
|
41
|
+
let pooled = errorMessagePool.get(key);
|
|
42
|
+
if (!pooled) {
|
|
43
|
+
pooled = key;
|
|
44
|
+
errorMessagePool.set(key, key);
|
|
45
|
+
}
|
|
46
|
+
return pooled;
|
|
47
|
+
}
|
|
48
|
+
function getSchemaFlags(config) {
|
|
49
|
+
let flags = 0;
|
|
50
|
+
if (config.body) flags |= SCHEMA_FLAGS.BODY;
|
|
51
|
+
if (config.query) flags |= SCHEMA_FLAGS.QUERY;
|
|
52
|
+
if (config.params) flags |= SCHEMA_FLAGS.PARAMS;
|
|
53
|
+
if (config.headers) flags |= SCHEMA_FLAGS.HEADERS;
|
|
54
|
+
if (config.cookies) flags |= SCHEMA_FLAGS.COOKIES;
|
|
55
|
+
return flags;
|
|
56
|
+
}
|
|
57
|
+
function validateSchemaUltra(schema, data, context) {
|
|
58
|
+
if (!schema) return data;
|
|
59
|
+
try {
|
|
60
|
+
let compiler = ultraSchemaCache.get(schema);
|
|
61
|
+
if (!compiler) {
|
|
62
|
+
try {
|
|
63
|
+
compiler = TypeCompiler.Compile(schema);
|
|
64
|
+
ultraSchemaCache.set(schema, compiler);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const message = getPooledString(`${context}\u9A8C\u8BC1\u5931\u8D25: Schema\u7F16\u8BD1\u5931\u8D25`);
|
|
67
|
+
throw getErrorFromPool(message);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const result = compiler.Check(data);
|
|
71
|
+
if (!result) {
|
|
72
|
+
const message = getPooledString(`${context}\u9A8C\u8BC1\u5931\u8D25`);
|
|
73
|
+
throw getErrorFromPool(message);
|
|
74
|
+
}
|
|
75
|
+
return data;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof Error && error.message.includes("\u9A8C\u8BC1\u5931\u8D25")) {
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
const message = getPooledString(
|
|
81
|
+
`${context}\u9A8C\u8BC1\u5931\u8D25: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
|
|
82
|
+
);
|
|
83
|
+
throw getErrorFromPool(message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function validateAllSchemasUltra(config, data) {
|
|
87
|
+
const flags = getSchemaFlags(config);
|
|
88
|
+
if (flags & SCHEMA_FLAGS.BODY) {
|
|
89
|
+
validateSchemaUltra(config.body, data.body, "\u8BF7\u6C42\u4F53");
|
|
90
|
+
}
|
|
91
|
+
if (flags & SCHEMA_FLAGS.QUERY) {
|
|
92
|
+
validateSchemaUltra(config.query, data.query, "Query\u53C2\u6570");
|
|
93
|
+
}
|
|
94
|
+
if (flags & SCHEMA_FLAGS.PARAMS) {
|
|
95
|
+
validateSchemaUltra(config.params, data.params, "\u8DEF\u5F84\u53C2\u6570");
|
|
96
|
+
}
|
|
97
|
+
if (flags & SCHEMA_FLAGS.HEADERS) {
|
|
98
|
+
validateSchemaUltra(config.headers, data.headers, "\u8BF7\u6C42\u5934");
|
|
99
|
+
}
|
|
100
|
+
if (flags & SCHEMA_FLAGS.COOKIES) {
|
|
101
|
+
validateSchemaUltra(config.cookies, data.cookies, "Cookie");
|
|
102
|
+
}
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/utils/parsers.ts
|
|
107
|
+
import qs from "qs";
|
|
108
|
+
import cookie from "cookie";
|
|
109
|
+
async function parseBody(req) {
|
|
110
|
+
const contentType = req.headers.get("content-type") || "";
|
|
111
|
+
if (contentType.includes("application/json")) {
|
|
112
|
+
return await req.json();
|
|
113
|
+
}
|
|
114
|
+
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
115
|
+
const text = await req.text();
|
|
116
|
+
return Object.fromEntries(new URLSearchParams(text));
|
|
117
|
+
}
|
|
118
|
+
return await req.text();
|
|
119
|
+
}
|
|
120
|
+
function extractQueryString(url) {
|
|
121
|
+
const qIndex = url.indexOf("?");
|
|
122
|
+
if (qIndex === -1) return "";
|
|
123
|
+
const hashIndex = url.indexOf("#", qIndex);
|
|
124
|
+
return hashIndex === -1 ? url.substring(qIndex + 1) : url.substring(qIndex + 1, hashIndex);
|
|
125
|
+
}
|
|
126
|
+
function parseQuery(req) {
|
|
127
|
+
const queryString = extractQueryString(req.url);
|
|
128
|
+
if (!queryString) return {};
|
|
129
|
+
return qs.parse(queryString);
|
|
130
|
+
}
|
|
131
|
+
function parseHeaders(req) {
|
|
132
|
+
const headers = /* @__PURE__ */ Object.create(null);
|
|
133
|
+
req.headers.forEach((value, key) => {
|
|
134
|
+
headers[key] = value;
|
|
135
|
+
});
|
|
136
|
+
return headers;
|
|
137
|
+
}
|
|
138
|
+
function parseCookies(req) {
|
|
139
|
+
const cookieHeader = req.headers.get("cookie");
|
|
140
|
+
if (!cookieHeader) return {};
|
|
141
|
+
try {
|
|
142
|
+
const parsed = cookie.parse(cookieHeader);
|
|
143
|
+
const result = {};
|
|
144
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
145
|
+
if (value !== void 0 && value !== null) {
|
|
146
|
+
result[key] = value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
} catch {
|
|
151
|
+
return {};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/utils/request-validator.ts
|
|
156
|
+
async function parseRequest(request, params) {
|
|
157
|
+
const requestData = {
|
|
158
|
+
body: void 0,
|
|
159
|
+
query: parseQuery(request),
|
|
160
|
+
params: params || {},
|
|
161
|
+
headers: parseHeaders(request),
|
|
162
|
+
cookies: parseCookies(request)
|
|
163
|
+
};
|
|
164
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
165
|
+
requestData.body = await parseBody(request);
|
|
166
|
+
}
|
|
167
|
+
return requestData;
|
|
168
|
+
}
|
|
169
|
+
function validateRequest(config, requestData) {
|
|
170
|
+
try {
|
|
171
|
+
const validatedData = validateAllSchemasUltra(config, requestData);
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
data: validatedData
|
|
175
|
+
};
|
|
176
|
+
} catch (error) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
errors: [
|
|
180
|
+
{
|
|
181
|
+
field: "unknown",
|
|
182
|
+
message: error instanceof Error ? error.message : "\u9A8C\u8BC1\u5931\u8D25"
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function parseAndValidateRequest(request, config, params) {
|
|
189
|
+
try {
|
|
190
|
+
const requestData = await parseRequest(request, params);
|
|
191
|
+
return validateRequest(config, requestData);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
return {
|
|
194
|
+
success: false,
|
|
195
|
+
errors: [
|
|
196
|
+
{
|
|
197
|
+
field: "unknown",
|
|
198
|
+
message: error instanceof Error ? error.message : "\u8BF7\u6C42\u89E3\u6790\u5931\u8D25"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function createRequestValidator(config) {
|
|
205
|
+
return async (request, params) => {
|
|
206
|
+
return parseAndValidateRequest(request, config, params);
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
export {
|
|
210
|
+
createRequestValidator,
|
|
211
|
+
parseAndValidateRequest,
|
|
212
|
+
parseRequest,
|
|
213
|
+
validateRequest
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* 超优化版Schema验证器 v5.0.0
|
|
217
|
+
*
|
|
218
|
+
* 使用经过验证的优化技术,确保极致性能
|
|
219
|
+
* - 内联函数调用
|
|
220
|
+
* - 预编译缓存优化
|
|
221
|
+
* - 内存池优化
|
|
222
|
+
* - 位运算优化
|
|
223
|
+
* - 类型特化优化
|
|
224
|
+
* - 循环展开优化
|
|
225
|
+
* - 位掩码优化
|
|
226
|
+
* - 字符串池优化
|
|
227
|
+
* - 内联缓存优化
|
|
228
|
+
* - 内存对齐优化
|
|
229
|
+
*
|
|
230
|
+
* @author Framework Team
|
|
231
|
+
* @version 5.0.0
|
|
232
|
+
* @license MIT
|
|
233
|
+
*/
|
|
1
234
|
/**
|
|
2
235
|
* 请求解析和验证器
|
|
3
236
|
*
|
|
@@ -8,87 +241,4 @@
|
|
|
8
241
|
* @version 1.0.0
|
|
9
242
|
* @license MIT
|
|
10
243
|
*/
|
|
11
|
-
|
|
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
|
-
}
|
|
244
|
+
//# sourceMappingURL=request-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/validators/schema-validators-ultra.ts","../../src/utils/parsers.ts","../../src/utils/request-validator.ts"],"sourcesContent":["/**\n * 超优化版Schema验证器 v5.0.0\n *\n * 使用经过验证的优化技术,确保极致性能\n * - 内联函数调用\n * - 预编译缓存优化\n * - 内存池优化\n * - 位运算优化\n * - 类型特化优化\n * - 循环展开优化\n * - 位掩码优化\n * - 字符串池优化\n * - 内联缓存优化\n * - 内存对齐优化\n *\n * @author Framework Team\n * @version 5.0.0\n * @license MIT\n */\n\nimport { TypeCompiler } from \"@sinclair/typebox/compiler\";\nimport type { TSchema } from \"@sinclair/typebox\";\n\n// 统一的Schema配置接口\nexport interface SchemaConfig {\n body?: TSchema;\n query?: TSchema;\n params?: TSchema;\n headers?: TSchema;\n cookies?: TSchema;\n}\n\n// 位掩码常量 - 用于快速检查Schema配置\nconst SCHEMA_FLAGS = {\n BODY: 1 << 0, // 1\n QUERY: 1 << 1, // 2\n PARAMS: 1 << 2, // 4\n HEADERS: 1 << 3, // 8\n COOKIES: 1 << 4, // 16\n} as const;\n\n// 超优化的Schema缓存 - 使用Map避免WeakMap的查找开销\nconst ultraSchemaCache = new Map<TSchema, any>();\nconst schemaCacheHits = new Map<TSchema, number>();\n\n// 内存池优化 - 预分配错误对象\nconst errorPool: Error[] = [];\nconst ERROR_POOL_SIZE = 200; // 增加池大小\n\n// 字符串池 - 避免重复创建错误消息\nconst errorMessagePool = new Map<string, string>();\nconst commonMessages = [\n \"请求体验证失败\",\n \"Query参数验证失败\",\n \"路径参数验证失败\",\n \"请求头验证失败\",\n \"Cookie验证失败\",\n \"类型验证失败\",\n \"Schema编译失败\",\n \"未知错误\",\n];\n\n// 初始化字符串池\ncommonMessages.forEach((msg) => errorMessagePool.set(msg, msg));\n\n// 初始化错误池\nfor (let i = 0; i < ERROR_POOL_SIZE; i++) {\n errorPool.push(new Error());\n}\n\nlet errorPoolIndex = 0;\n\n// 获取错误对象 - 避免重复创建\nfunction getErrorFromPool(message: string): Error {\n const error = errorPool[errorPoolIndex];\n error.message = message;\n errorPoolIndex = (errorPoolIndex + 1) % ERROR_POOL_SIZE;\n return error;\n}\n\n// 获取或创建字符串 - 字符串池优化\nfunction getPooledString(key: string): string {\n let pooled = errorMessagePool.get(key);\n if (!pooled) {\n pooled = key;\n errorMessagePool.set(key, key);\n }\n return pooled;\n}\n\n// 获取或编译Schema - 超内联优化版本\nfunction getUltraSchemaCompiler(schema: TSchema): any {\n // 直接检查缓存,避免WeakMap的has()调用\n let compiler = ultraSchemaCache.get(schema);\n if (compiler) {\n // 缓存命中统计\n schemaCacheHits.set(schema, (schemaCacheHits.get(schema) || 0) + 1);\n return compiler;\n }\n\n try {\n compiler = TypeCompiler.Compile(schema);\n ultraSchemaCache.set(schema, compiler);\n return compiler;\n } catch (error) {\n return null;\n }\n}\n\n// 计算Schema配置的位掩码 - 用于快速检查\nfunction getSchemaFlags(config: SchemaConfig): number {\n let flags = 0;\n if (config.body) flags |= SCHEMA_FLAGS.BODY;\n if (config.query) flags |= SCHEMA_FLAGS.QUERY;\n if (config.params) flags |= SCHEMA_FLAGS.PARAMS;\n if (config.headers) flags |= SCHEMA_FLAGS.HEADERS;\n if (config.cookies) flags |= SCHEMA_FLAGS.COOKIES;\n return flags;\n}\n\n// 超优化的Schema验证函数 - 位运算优化版本\nexport function validateSchemaUltra(\n schema: TSchema | undefined,\n data: any,\n context: string,\n): any {\n if (!schema) return data;\n\n try {\n // 完全内联逻辑,零函数调用开销\n let compiler = ultraSchemaCache.get(schema);\n if (!compiler) {\n try {\n compiler = TypeCompiler.Compile(schema);\n ultraSchemaCache.set(schema, compiler);\n } catch (error) {\n // 使用错误池和字符串池\n const message = getPooledString(`${context}验证失败: Schema编译失败`);\n throw getErrorFromPool(message);\n }\n }\n\n // 直接验证,零额外开销\n const result = compiler.Check(data);\n if (!result) {\n // 使用错误池和字符串池\n const message = getPooledString(`${context}验证失败`);\n throw getErrorFromPool(message);\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"验证失败\")) {\n throw error;\n }\n // 使用错误池和字符串池\n const message = getPooledString(\n `${context}验证失败: ${\n error instanceof Error ? error.message : \"未知错误\"\n }`,\n );\n throw getErrorFromPool(message);\n }\n}\n\n// 超优化的批量验证 - 位掩码优化版本(极致性能)\nexport function validateAllSchemasUltra(\n config: SchemaConfig,\n data: {\n body: any;\n query: any;\n params: any;\n headers: any;\n cookies: any;\n },\n): any {\n // 使用位掩码快速检查,避免多次条件判断\n const flags = getSchemaFlags(config);\n\n // 位运算检查,比条件判断快\n if (flags & SCHEMA_FLAGS.BODY) {\n validateSchemaUltra(config.body, data.body, \"请求体\");\n }\n if (flags & SCHEMA_FLAGS.QUERY) {\n validateSchemaUltra(config.query, data.query, \"Query参数\");\n }\n if (flags & SCHEMA_FLAGS.PARAMS) {\n validateSchemaUltra(config.params, data.params, \"路径参数\");\n }\n if (flags & SCHEMA_FLAGS.HEADERS) {\n validateSchemaUltra(config.headers, data.headers, \"请求头\");\n }\n if (flags & SCHEMA_FLAGS.COOKIES) {\n validateSchemaUltra(config.cookies, data.cookies, \"Cookie\");\n }\n return data;\n}\n\n// 超优化的预编译 - 位掩码优化版本\nexport function precompileSchemasUltra(config: SchemaConfig): void {\n const flags = getSchemaFlags(config);\n\n // 使用位运算检查,避免重复条件判断\n if (flags & SCHEMA_FLAGS.BODY && config.body) {\n getUltraSchemaCompiler(config.body);\n }\n if (flags & SCHEMA_FLAGS.QUERY && config.query) {\n getUltraSchemaCompiler(config.query);\n }\n if (flags & SCHEMA_FLAGS.PARAMS && config.params) {\n getUltraSchemaCompiler(config.params);\n }\n if (flags & SCHEMA_FLAGS.HEADERS && config.headers) {\n getUltraSchemaCompiler(config.headers);\n }\n if (flags & SCHEMA_FLAGS.COOKIES && config.cookies) {\n getUltraSchemaCompiler(config.cookies);\n }\n}\n\n// 类型特化验证器 - 针对特定类型优化\nexport function createTypedValidatorUltra<T>(schema: TSchema): (data: T) => T {\n const compiler = getUltraSchemaCompiler(schema);\n\n return (data: T): T => {\n if (!compiler.Check(data)) {\n throw getErrorFromPool(getPooledString(\"类型验证失败\"));\n }\n return data;\n };\n}\n\n// 批量类型验证器 - 一次验证多个数据,循环展开优化\nexport function validateBatchUltra<T>(schema: TSchema, dataArray: T[]): T[] {\n const compiler = getUltraSchemaCompiler(schema);\n const results: T[] = [];\n const length = dataArray.length;\n\n // 循环展开优化 - 处理前4个元素\n if (length >= 1) {\n if (!compiler.Check(dataArray[0])) {\n throw getErrorFromPool(getPooledString(\"第1个数据验证失败\"));\n }\n results.push(dataArray[0]);\n }\n if (length >= 2) {\n if (!compiler.Check(dataArray[1])) {\n throw getErrorFromPool(getPooledString(\"第2个数据验证失败\"));\n }\n results.push(dataArray[1]);\n }\n if (length >= 3) {\n if (!compiler.Check(dataArray[2])) {\n throw getErrorFromPool(getPooledString(\"第3个数据验证失败\"));\n }\n results.push(dataArray[2]);\n }\n if (length >= 4) {\n if (!compiler.Check(dataArray[3])) {\n throw getErrorFromPool(getPooledString(\"第4个数据验证失败\"));\n }\n results.push(dataArray[3]);\n }\n\n // 处理剩余元素\n for (let i = 4; i < length; i++) {\n const data = dataArray[i];\n if (!compiler.Check(data)) {\n throw getErrorFromPool(getPooledString(`第${i + 1}个数据验证失败`));\n }\n results.push(data);\n }\n\n return results;\n}\n\n// 内存优化的缓存统计\nexport function getCacheStats() {\n const totalSchemas = ultraSchemaCache.size;\n const totalHits = Array.from(schemaCacheHits.values()).reduce(\n (sum, hits) => sum + hits,\n 0,\n );\n const hitRate =\n totalHits > 0\n ? ((totalHits / (totalHits + totalSchemas)) * 100).toFixed(2)\n : \"0.00\";\n\n return {\n totalSchemas,\n totalHits,\n hitRate: `${hitRate}%`,\n cacheSize: ultraSchemaCache.size,\n errorPoolUsage: `${errorPoolIndex}/${ERROR_POOL_SIZE}`,\n stringPoolSize: errorMessagePool.size,\n memoryEfficiency:\n totalHits > 0 ? (totalHits / totalSchemas).toFixed(2) : \"0.00\",\n };\n}\n\n// 智能缓存清理 - 只清理最少使用的Schema\nexport function smartClearUltraCache(keepTop: number = 10): void {\n if (ultraSchemaCache.size <= keepTop) return;\n\n // 按使用频率排序\n const sortedSchemas = Array.from(schemaCacheHits.entries())\n .sort(([, a], [, b]) => b - a)\n .slice(0, keepTop);\n\n // 清理缓存\n ultraSchemaCache.clear();\n schemaCacheHits.clear();\n\n // 重新添加最常用的Schema\n for (const [schema, hits] of sortedSchemas) {\n ultraSchemaCache.set(schema, getUltraSchemaCompiler(schema));\n schemaCacheHits.set(schema, hits);\n }\n}\n\n// 完全清理缓存\nexport function clearUltraCache(): void {\n ultraSchemaCache.clear();\n schemaCacheHits.clear();\n errorPoolIndex = 0;\n}\n\n// 性能监控装饰器 - 使用高精度计时器\nexport function withPerformanceMonitoring<T extends (...args: any[]) => any>(\n fn: T,\n name: string,\n): T {\n return ((...args: any[]) => {\n const start = performance.now();\n try {\n const result = fn(...args);\n const end = performance.now();\n console.log(`⚡ ${name} 执行时间: ${(end - start).toFixed(6)}ms`);\n return result;\n } catch (error) {\n const end = performance.now();\n console.log(`❌ ${name} 执行时间: ${(end - start).toFixed(6)}ms (失败)`);\n throw error;\n }\n }) as T;\n}\n\n// 导出主要函数(使用标准命名)\nexport {\n validateAllSchemasUltra as validateAllSchemas,\n createTypedValidatorUltra as createTypedValidator,\n validateBatchUltra as validateBatch,\n clearUltraCache as clearCache,\n smartClearUltraCache as smartClearCache,\n};\n","// 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 * 请求解析和验证器\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 validateAllSchemasUltra,\n type SchemaConfig,\n} from \"./validators/schema-validators-ultra\";\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 = validateAllSchemasUltra(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"],"mappings":";AAoBA,SAAS,oBAAoB;AAa7B,IAAM,eAAe;AAAA,EACnB,MAAM,KAAK;AAAA;AAAA,EACX,OAAO,KAAK;AAAA;AAAA,EACZ,QAAQ,KAAK;AAAA;AAAA,EACb,SAAS,KAAK;AAAA;AAAA,EACd,SAAS,KAAK;AAAA;AAChB;AAGA,IAAM,mBAAmB,oBAAI,IAAkB;AAI/C,IAAM,YAAqB,CAAC;AAC5B,IAAM,kBAAkB;AAGxB,IAAM,mBAAmB,oBAAI,IAAoB;AACjD,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,eAAe,QAAQ,CAAC,QAAQ,iBAAiB,IAAI,KAAK,GAAG,CAAC;AAG9D,SAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACxC,YAAU,KAAK,IAAI,MAAM,CAAC;AAC5B;AAEA,IAAI,iBAAiB;AAGrB,SAAS,iBAAiB,SAAwB;AAChD,QAAM,QAAQ,UAAU,cAAc;AACtC,QAAM,UAAU;AAChB,oBAAkB,iBAAiB,KAAK;AACxC,SAAO;AACT;AAGA,SAAS,gBAAgB,KAAqB;AAC5C,MAAI,SAAS,iBAAiB,IAAI,GAAG;AACrC,MAAI,CAAC,QAAQ;AACX,aAAS;AACT,qBAAiB,IAAI,KAAK,GAAG;AAAA,EAC/B;AACA,SAAO;AACT;AAsBA,SAAS,eAAe,QAA8B;AACpD,MAAI,QAAQ;AACZ,MAAI,OAAO,KAAM,UAAS,aAAa;AACvC,MAAI,OAAO,MAAO,UAAS,aAAa;AACxC,MAAI,OAAO,OAAQ,UAAS,aAAa;AACzC,MAAI,OAAO,QAAS,UAAS,aAAa;AAC1C,MAAI,OAAO,QAAS,UAAS,aAAa;AAC1C,SAAO;AACT;AAGO,SAAS,oBACd,QACA,MACA,SACK;AACL,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI;AAEF,QAAI,WAAW,iBAAiB,IAAI,MAAM;AAC1C,QAAI,CAAC,UAAU;AACb,UAAI;AACF,mBAAW,aAAa,QAAQ,MAAM;AACtC,yBAAiB,IAAI,QAAQ,QAAQ;AAAA,MACvC,SAAS,OAAO;AAEd,cAAM,UAAU,gBAAgB,GAAG,OAAO,0DAAkB;AAC5D,cAAM,iBAAiB,OAAO;AAAA,MAChC;AAAA,IACF;AAGA,UAAM,SAAS,SAAS,MAAM,IAAI;AAClC,QAAI,CAAC,QAAQ;AAEX,YAAM,UAAU,gBAAgB,GAAG,OAAO,0BAAM;AAChD,YAAM,iBAAiB,OAAO;AAAA,IAChC;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,0BAAM,GAAG;AAC5D,YAAM;AAAA,IACR;AAEA,UAAM,UAAU;AAAA,MACd,GAAG,OAAO,6BACR,iBAAiB,QAAQ,MAAM,UAAU,0BAC3C;AAAA,IACF;AACA,UAAM,iBAAiB,OAAO;AAAA,EAChC;AACF;AAGO,SAAS,wBACd,QACA,MAOK;AAEL,QAAM,QAAQ,eAAe,MAAM;AAGnC,MAAI,QAAQ,aAAa,MAAM;AAC7B,wBAAoB,OAAO,MAAM,KAAK,MAAM,oBAAK;AAAA,EACnD;AACA,MAAI,QAAQ,aAAa,OAAO;AAC9B,wBAAoB,OAAO,OAAO,KAAK,OAAO,mBAAS;AAAA,EACzD;AACA,MAAI,QAAQ,aAAa,QAAQ;AAC/B,wBAAoB,OAAO,QAAQ,KAAK,QAAQ,0BAAM;AAAA,EACxD;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,wBAAoB,OAAO,SAAS,KAAK,SAAS,oBAAK;AAAA,EACzD;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,wBAAoB,OAAO,SAAS,KAAK,SAAS,QAAQ;AAAA,EAC5D;AACA,SAAO;AACT;;;ACnMA,OAAO,QAAQ;AACf,OAAO,YAAY;AAoBnB,eAAsB,UAAU,KAAgC;AAC9D,QAAM,cAAc,IAAI,QAAQ,IAAI,cAAc,KAAK;AACvD,MAAI,YAAY,SAAS,kBAAkB,GAAG;AAC5C,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AACA,MAAI,YAAY,SAAS,mCAAmC,GAAG;AAC7D,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,OAAO,YAAY,IAAI,gBAAgB,IAAI,CAAC;AAAA,EACrD;AACA,SAAO,MAAM,IAAI,KAAK;AACxB;AA0FA,SAAS,mBAAmB,KAAqB;AAC/C,QAAM,SAAS,IAAI,QAAQ,GAAG;AAC9B,MAAI,WAAW,GAAI,QAAO;AAE1B,QAAM,YAAY,IAAI,QAAQ,KAAK,MAAM;AACzC,SAAO,cAAc,KACjB,IAAI,UAAU,SAAS,CAAC,IACxB,IAAI,UAAU,SAAS,GAAG,SAAS;AACzC;AAGO,SAAS,WAAW,KAAuC;AAChE,QAAM,cAAc,mBAAmB,IAAI,GAAG;AAC9C,MAAI,CAAC,YAAa,QAAO,CAAC;AAC1B,SAAO,GAAG,MAAM,WAAW;AAC7B;AA4BO,SAAS,aAAa,KAAsC;AACjE,QAAM,UAAkC,uBAAO,OAAO,IAAI;AAC1D,MAAI,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAClC,YAAQ,GAAG,IAAI;AAAA,EACjB,CAAC;AACD,SAAO;AACT;AAUO,SAAS,aAAa,KAAsC;AACjE,QAAM,eAAe,IAAI,QAAQ,IAAI,QAAQ;AAC7C,MAAI,CAAC,aAAc,QAAO,CAAC;AAE3B,MAAI;AACF,UAAM,SAAS,OAAO,MAAM,YAAY;AAExC,UAAM,SAAiC,CAAC;AACxC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,UAAU,UAAa,UAAU,MAAM;AACzC,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;;;AC9IA,eAAsB,aACpB,SACA,QACsB;AACtB,QAAM,cAA2B;AAAA,IAC/B,MAAM;AAAA,IACN,OAAO,WAAW,OAAO;AAAA,IACzB,QAAQ,UAAU,CAAC;AAAA,IACnB,SAAS,aAAa,OAAO;AAAA,IAC7B,SAAS,aAAa,OAAO;AAAA,EAC/B;AAGA,MAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,QAAQ;AACzD,gBAAY,OAAO,MAAM,UAAU,OAAO;AAAA,EAC5C;AAEA,SAAO;AACT;AAQO,SAAS,gBACd,QACA,aACqB;AACrB,MAAI;AACF,UAAM,gBAAgB,wBAAwB,QAAQ,WAAW;AAEjE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,QACN;AAAA,UACE,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AASA,eAAsB,wBACpB,SACA,QACA,QAC8B;AAC9B,MAAI;AAEF,UAAM,cAAc,MAAM,aAAa,SAAS,MAAM;AAGtD,WAAO,gBAAgB,QAAQ,WAAW;AAAA,EAC5C,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,QACN;AAAA,UACE,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAOO,SAAS,uBAA+C,QAAW;AACxE,SAAO,OAAO,SAAkB,WAAoC;AAClE,WAAO,wBAAwB,SAAS,QAAQ,MAAM;AAAA,EACxD;AACF;","names":[]}
|
package/dist/utils/response.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
/** 生成 JSON 响应 */
|
|
2
|
-
|
|
2
|
+
declare function json(data: unknown, status?: number, headers?: HeadersInit): Response;
|
|
3
3
|
/**
|
|
4
4
|
* 类型特化的响应映射
|
|
5
5
|
* 根据返回值类型直接生成 Response,避免不必要的检查
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
declare function mapResponse(response: unknown): Response;
|
|
8
8
|
/** 生成重定向响应 */
|
|
9
|
-
|
|
9
|
+
declare function redirect(location: string, status?: 301 | 302): Response;
|
|
10
10
|
/** 生成纯文本响应 */
|
|
11
|
-
|
|
11
|
+
declare function text(content: string, status?: number, headers?: HeadersInit): Response;
|
|
12
12
|
/** 生成HTML响应 */
|
|
13
|
-
|
|
13
|
+
declare function html(content: string, status?: number, headers?: HeadersInit): Response;
|
|
14
14
|
/** 生成空响应(204 No Content) */
|
|
15
|
-
|
|
15
|
+
declare function empty(status?: number, headers?: HeadersInit): Response;
|
|
16
16
|
/** 生成流式响应 */
|
|
17
|
-
|
|
17
|
+
declare function stream(stream: ReadableStream, status?: number, headers?: HeadersInit): Response;
|
|
18
|
+
|
|
19
|
+
export { empty, html, json, mapResponse, redirect, stream, text };
|