vafast 0.4.2 → 0.4.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/README.md +6 -10
- package/dist/base-server-CSkyjEaY.mjs +113 -0
- package/dist/base-server-CSkyjEaY.mjs.map +1 -0
- package/dist/base-server-DvGS6ATg.d.mts +40 -0
- package/dist/base64url-0N9uQPjZ.d.mts +6 -0
- package/dist/base64url-CwQnvZyp.mjs +13 -0
- package/dist/base64url-CwQnvZyp.mjs.map +1 -0
- package/dist/chunk-DW4-Jl94.mjs +37 -0
- package/dist/component-route-CYxLOnci.mjs +1 -0
- package/dist/component-route-CZawYn61.d.mts +31 -0
- package/dist/component-router-CErbGh2A.mjs +33 -0
- package/dist/component-router-CErbGh2A.mjs.map +1 -0
- package/dist/component-server-CGzU4bss.d.mts +38 -0
- package/dist/component-server-DAbIyIPI.mjs +124 -0
- package/dist/component-server-DAbIyIPI.mjs.map +1 -0
- package/dist/create-handler-B_pfxh3m.mjs +166 -0
- package/dist/create-handler-B_pfxh3m.mjs.map +1 -0
- package/dist/{utils/create-handler.d.ts → create-handler-Bo-hvWp-.d.mts} +24 -24
- package/dist/{defineRoute.d.ts → defineRoute.d.mts} +20 -17
- package/dist/defineRoute.mjs +93 -0
- package/dist/defineRoute.mjs.map +1 -0
- package/dist/dependency-manager-C6vFWP2L.d.mts +27 -0
- package/dist/dependency-manager-Czg7Po2j.mjs +61 -0
- package/dist/dependency-manager-Czg7Po2j.mjs.map +1 -0
- package/dist/formats-CYLwo9GJ.d.mts +42 -0
- package/dist/go-await-BGAGJfrB.mjs +33 -0
- package/dist/go-await-BGAGJfrB.mjs.map +1 -0
- package/dist/{utils/go-await.d.ts → go-await-DRItVwwh.d.mts} +4 -2
- package/dist/handle-Csjtywdc.mjs +30 -0
- package/dist/handle-Csjtywdc.mjs.map +1 -0
- package/dist/{utils/handle.d.ts → handle-D0TFoOiX.d.mts} +8 -6
- package/dist/html-renderer-CMGKJoIy.d.mts +22 -0
- package/dist/{utils/html-renderer.js → html-renderer-CczE8mwC.mjs} +34 -29
- package/dist/html-renderer-CczE8mwC.mjs.map +1 -0
- package/dist/index-Ci52vt55.d.mts +48 -0
- package/dist/index-CzItj62a.d.mts +1 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.mjs +37 -0
- package/dist/index.mjs.map +1 -0
- package/dist/middleware/{component-renderer.d.ts → component-renderer.d.mts} +3 -1
- package/dist/middleware/component-renderer.mjs +119 -0
- package/dist/middleware/component-renderer.mjs.map +1 -0
- package/dist/middleware/{component-router.d.ts → component-router.d.mts} +5 -4
- package/dist/middleware/component-router.mjs +4 -0
- package/dist/middleware-Byp3Hjae.mjs +59 -0
- package/dist/middleware-Byp3Hjae.mjs.map +1 -0
- package/dist/middleware.d.mts +25 -0
- package/dist/middleware.mjs +4 -0
- package/dist/monitoring/index.d.mts +33 -0
- package/dist/monitoring/index.mjs +27 -0
- package/dist/monitoring/index.mjs.map +1 -0
- package/dist/monitoring/native-monitor.d.mts +48 -0
- package/dist/monitoring/native-monitor.mjs +154 -0
- package/dist/monitoring/native-monitor.mjs.map +1 -0
- package/dist/monitoring/types.d.mts +150 -0
- package/dist/monitoring/types.mjs +1 -0
- package/dist/node-server/index.d.mts +4 -0
- package/dist/node-server/index.mjs +5 -0
- package/dist/node-server/{request.d.ts → request.d.mts} +4 -6
- package/dist/node-server/request.mjs +3 -0
- package/dist/node-server/{response.d.ts → response.d.mts} +4 -6
- package/dist/node-server/response.mjs +3 -0
- package/dist/node-server/serve.d.mts +2 -0
- package/dist/node-server/serve.mjs +4 -0
- package/dist/{utils/parsers.d.ts → parsers-7lvt3Oss.d.mts} +10 -8
- package/dist/parsers-CI_TZ7pO.mjs +168 -0
- package/dist/parsers-CI_TZ7pO.mjs.map +1 -0
- package/dist/path-matcher-73cJd5Y7.mjs +62 -0
- package/dist/path-matcher-73cJd5Y7.mjs.map +1 -0
- package/dist/radix-tree-D0XYaJKb.mjs +157 -0
- package/dist/radix-tree-D0XYaJKb.mjs.map +1 -0
- package/dist/request-CKC3Ox6M.mjs +133 -0
- package/dist/request-CKC3Ox6M.mjs.map +1 -0
- package/dist/request-validator-42lY21gn.d.mts +67 -0
- package/dist/request-validator-_J5HloRq.mjs +77 -0
- package/dist/request-validator-_J5HloRq.mjs.map +1 -0
- package/dist/{utils/response.d.ts → response-A-sZZiJ7.d.mts} +4 -2
- package/dist/response-Cf5FgtmE.mjs +72 -0
- package/dist/response-Cf5FgtmE.mjs.map +1 -0
- package/dist/response-DXg4i_yh.mjs +97 -0
- package/dist/response-DXg4i_yh.mjs.map +1 -0
- package/dist/route-9pAVP1GC.mjs +11 -0
- package/dist/route-9pAVP1GC.mjs.map +1 -0
- package/dist/route-BJ-40LNI.d.mts +44 -0
- package/dist/route-registry--tx1PNui.d.mts +176 -0
- package/dist/route-registry-mcTG0M-t.mjs +225 -0
- package/dist/route-registry-mcTG0M-t.mjs.map +1 -0
- package/dist/router/index.d.mts +5 -0
- package/dist/router/index.mjs +10 -0
- package/dist/router/index.mjs.map +1 -0
- package/dist/router/radix-tree.d.mts +60 -0
- package/dist/router/radix-tree.mjs +4 -0
- package/dist/router-B9HUUCkR.mjs +71 -0
- package/dist/router-B9HUUCkR.mjs.map +1 -0
- package/dist/{router.d.ts → router.d.mts} +6 -7
- package/dist/router.mjs +4 -0
- package/dist/schema-CPQudJpE.d.mts +81 -0
- package/dist/schema-CtVBNfnQ.mjs +1 -0
- package/dist/serve-B5WmhK6m.d.mts +69 -0
- package/dist/serve-Be6NvuQk.mjs +107 -0
- package/dist/serve-Be6NvuQk.mjs.map +1 -0
- package/dist/serve.d.mts +2 -0
- package/dist/serve.mjs +4 -0
- package/dist/server/base-server.d.mts +4 -0
- package/dist/server/base-server.mjs +4 -0
- package/dist/server/component-server.d.mts +5 -0
- package/dist/server/component-server.mjs +5 -0
- package/dist/server/index.d.mts +7 -0
- package/dist/server/index.mjs +8 -0
- package/dist/server/server-factory.d.mts +7 -0
- package/dist/server/server-factory.mjs +6 -0
- package/dist/server/server.d.mts +5 -0
- package/dist/server/server.mjs +4 -0
- package/dist/server-BmPKs8oM.mjs +137 -0
- package/dist/server-BmPKs8oM.mjs.map +1 -0
- package/dist/server-Cbd3Ia51.mjs +88 -0
- package/dist/server-Cbd3Ia51.mjs.map +1 -0
- package/dist/server-D9gjszHe.d.mts +60 -0
- package/dist/sse-BMM6KTfy.d.mts +65 -0
- package/dist/sse-BT5yyLgX.mjs +87 -0
- package/dist/sse-BT5yyLgX.mjs.map +1 -0
- package/dist/types/component-route.d.mts +2 -0
- package/dist/types/component-route.mjs +1 -0
- package/dist/types/index.d.mts +6 -0
- package/dist/types/index.mjs +3 -0
- package/dist/types/route.d.mts +2 -0
- package/dist/types/route.mjs +3 -0
- package/dist/types/schema.d.mts +2 -0
- package/dist/types/schema.mjs +1 -0
- package/dist/types/types.d.mts +2 -0
- package/dist/types/types.mjs +1 -0
- package/dist/{types/types.d.ts → types-DuTa8AVN.d.mts} +27 -25
- package/dist/utils/base64url.d.mts +2 -0
- package/dist/utils/base64url.mjs +3 -0
- package/dist/utils/create-handler.d.mts +3 -0
- package/dist/utils/create-handler.mjs +5 -0
- package/dist/utils/dependency-manager.d.mts +2 -0
- package/dist/utils/dependency-manager.mjs +4 -0
- package/dist/utils/formats.d.mts +2 -0
- package/dist/utils/formats.mjs +129 -0
- package/dist/utils/formats.mjs.map +1 -0
- package/dist/utils/go-await.d.mts +2 -0
- package/dist/utils/go-await.mjs +3 -0
- package/dist/utils/handle.d.mts +2 -0
- package/dist/utils/handle.mjs +4 -0
- package/dist/utils/html-renderer.d.mts +2 -0
- package/dist/utils/html-renderer.mjs +4 -0
- package/dist/utils/index.d.mts +16 -0
- package/dist/utils/index.mjs +23 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/parsers.d.mts +2 -0
- package/dist/utils/parsers.mjs +3 -0
- package/dist/utils/path-matcher.d.mts +27 -0
- package/dist/utils/path-matcher.mjs +4 -0
- package/dist/utils/request-validator.d.mts +3 -0
- package/dist/utils/request-validator.mjs +5 -0
- package/dist/utils/response.d.mts +2 -0
- package/dist/utils/response.mjs +4 -0
- package/dist/utils/route-registry.d.mts +4 -0
- package/dist/utils/route-registry.mjs +4 -0
- package/dist/utils/sse.d.mts +3 -0
- package/dist/utils/sse.mjs +5 -0
- package/dist/utils/validators/validators.d.mts +2 -0
- package/dist/utils/validators/validators.mjs +3 -0
- package/dist/validators-BBrGePBr.mjs +112 -0
- package/dist/validators-BBrGePBr.mjs.map +1 -0
- package/dist/validators-CPmnj_y9.d.mts +67 -0
- package/package.json +16 -18
- package/dist/auth/token.d.ts +0 -42
- package/dist/auth/token.js +0 -131
- package/dist/auth/token.js.map +0 -1
- package/dist/defineRoute.js +0 -37
- package/dist/defineRoute.js.map +0 -1
- package/dist/index.d.ts +0 -32
- package/dist/index.js +0 -2578
- package/dist/index.js.map +0 -1
- package/dist/middleware/auth.d.ts +0 -16
- package/dist/middleware/auth.js +0 -205
- package/dist/middleware/auth.js.map +0 -1
- package/dist/middleware/authMiddleware.d.ts +0 -5
- package/dist/middleware/authMiddleware.js +0 -57
- package/dist/middleware/authMiddleware.js.map +0 -1
- package/dist/middleware/component-renderer.js +0 -139
- package/dist/middleware/component-renderer.js.map +0 -1
- package/dist/middleware/component-router.js +0 -36
- package/dist/middleware/component-router.js.map +0 -1
- package/dist/middleware/cors.d.ts +0 -12
- package/dist/middleware/cors.js +0 -43
- package/dist/middleware/cors.js.map +0 -1
- package/dist/middleware/rateLimit.d.ts +0 -10
- package/dist/middleware/rateLimit.js +0 -49
- package/dist/middleware/rateLimit.js.map +0 -1
- package/dist/middleware.d.ts +0 -21
- package/dist/middleware.js +0 -102
- package/dist/middleware.js.map +0 -1
- package/dist/monitoring/index.d.ts +0 -36
- package/dist/monitoring/index.js +0 -1487
- package/dist/monitoring/index.js.map +0 -1
- package/dist/monitoring/native-monitor.d.ts +0 -44
- package/dist/monitoring/native-monitor.js +0 -1454
- package/dist/monitoring/native-monitor.js.map +0 -1
- package/dist/monitoring/types.d.ts +0 -148
- package/dist/monitoring/types.js +0 -8
- package/dist/monitoring/types.js.map +0 -1
- package/dist/node-server/index.d.ts +0 -4
- package/dist/node-server/index.js +0 -298
- package/dist/node-server/index.js.map +0 -1
- package/dist/node-server/request.js +0 -125
- package/dist/node-server/request.js.map +0 -1
- package/dist/node-server/response.js +0 -76
- package/dist/node-server/response.js.map +0 -1
- package/dist/node-server/serve.d.ts +0 -71
- package/dist/node-server/serve.js +0 -281
- package/dist/node-server/serve.js.map +0 -1
- package/dist/router/index.d.ts +0 -3
- package/dist/router/index.js +0 -232
- package/dist/router/index.js.map +0 -1
- package/dist/router/radix-tree.d.ts +0 -66
- package/dist/router/radix-tree.js +0 -190
- package/dist/router/radix-tree.js.map +0 -1
- package/dist/router.js +0 -44
- package/dist/router.js.map +0 -1
- package/dist/serve.d.ts +0 -2
- package/dist/serve.js +0 -281
- package/dist/serve.js.map +0 -1
- package/dist/server/base-server.d.ts +0 -37
- package/dist/server/base-server.js +0 -134
- package/dist/server/base-server.js.map +0 -1
- package/dist/server/component-server.d.ts +0 -37
- package/dist/server/component-server.js +0 -488
- package/dist/server/component-server.js.map +0 -1
- package/dist/server/index.d.ts +0 -8
- package/dist/server/index.js +0 -1159
- package/dist/server/index.js.map +0 -1
- package/dist/server/server-factory.d.ts +0 -48
- package/dist/server/server-factory.js +0 -1156
- package/dist/server/server-factory.js.map +0 -1
- package/dist/server/server.d.ts +0 -64
- package/dist/server/server.js +0 -737
- package/dist/server/server.js.map +0 -1
- package/dist/types/component-route.d.ts +0 -29
- package/dist/types/component-route.js +0 -1
- package/dist/types/component-route.js.map +0 -1
- package/dist/types/index.d.ts +0 -5
- package/dist/types/index.js +0 -21
- package/dist/types/index.js.map +0 -1
- package/dist/types/route.d.ts +0 -42
- package/dist/types/route.js +0 -12
- package/dist/types/route.js.map +0 -1
- package/dist/types/schema.d.ts +0 -79
- package/dist/types/schema.js +0 -10
- package/dist/types/schema.js.map +0 -1
- package/dist/types/types.js +0 -1
- package/dist/types/types.js.map +0 -1
- package/dist/utils/base64url.d.ts +0 -4
- package/dist/utils/base64url.js +0 -14
- package/dist/utils/base64url.js.map +0 -1
- package/dist/utils/create-handler.js +0 -299
- package/dist/utils/create-handler.js.map +0 -1
- package/dist/utils/dependency-manager.d.ts +0 -25
- package/dist/utils/dependency-manager.js +0 -71
- package/dist/utils/dependency-manager.js.map +0 -1
- package/dist/utils/formats.d.ts +0 -40
- package/dist/utils/formats.js +0 -116
- package/dist/utils/formats.js.map +0 -1
- package/dist/utils/go-await.js +0 -16
- package/dist/utils/go-await.js.map +0 -1
- package/dist/utils/handle.js +0 -48
- package/dist/utils/handle.js.map +0 -1
- package/dist/utils/html-renderer.d.ts +0 -20
- package/dist/utils/html-renderer.js.map +0 -1
- package/dist/utils/index.d.ts +0 -16
- package/dist/utils/index.js +0 -1038
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/parsers.js +0 -160
- package/dist/utils/parsers.js.map +0 -1
- package/dist/utils/path-matcher.d.ts +0 -25
- package/dist/utils/path-matcher.js +0 -73
- package/dist/utils/path-matcher.js.map +0 -1
- package/dist/utils/request-validator.d.ts +0 -66
- package/dist/utils/request-validator.js +0 -158
- package/dist/utils/request-validator.js.map +0 -1
- package/dist/utils/response.js +0 -102
- package/dist/utils/response.js.map +0 -1
- package/dist/utils/route-registry.d.ts +0 -195
- package/dist/utils/route-registry.js +0 -152
- package/dist/utils/route-registry.js.map +0 -1
- package/dist/utils/sse.d.ts +0 -87
- package/dist/utils/sse.js +0 -181
- package/dist/utils/sse.js.map +0 -1
- package/dist/utils/validators/validators.d.ts +0 -76
- package/dist/utils/validators/validators.js +0 -97
- package/dist/utils/validators/validators.js.map +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { n as __exportAll, t as __esmMin } from "./chunk-DW4-Jl94.mjs";
|
|
2
|
+
import { n as init_base_server, t as BaseServer } from "./base-server-CSkyjEaY.mjs";
|
|
3
|
+
import { n as init_server$1, t as Server } from "./server-BmPKs8oM.mjs";
|
|
4
|
+
import { n as init_component_server, t as ComponentServer } from "./component-server-DAbIyIPI.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/server/server-factory.ts
|
|
7
|
+
var ServerFactory;
|
|
8
|
+
var init_server_factory = __esmMin((() => {
|
|
9
|
+
init_server();
|
|
10
|
+
init_component_server();
|
|
11
|
+
ServerFactory = class {
|
|
12
|
+
servers = /* @__PURE__ */ new Map();
|
|
13
|
+
/**
|
|
14
|
+
* 创建标准REST API服务器
|
|
15
|
+
*/
|
|
16
|
+
createRestServer(routes) {
|
|
17
|
+
const server = new Server(routes);
|
|
18
|
+
this.servers.set("rest", server);
|
|
19
|
+
return server;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 创建组件服务器
|
|
23
|
+
*/
|
|
24
|
+
createComponentServer(routes) {
|
|
25
|
+
const server = new ComponentServer(routes);
|
|
26
|
+
this.servers.set("component", server);
|
|
27
|
+
return server;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 获取指定类型的服务器
|
|
31
|
+
*/
|
|
32
|
+
getServer(type) {
|
|
33
|
+
return this.servers.get(type);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 获取所有服务器
|
|
37
|
+
*/
|
|
38
|
+
getAllServers() {
|
|
39
|
+
return this.servers;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 移除指定类型的服务器
|
|
43
|
+
*/
|
|
44
|
+
removeServer(type) {
|
|
45
|
+
return this.servers.delete(type);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 清除所有服务器
|
|
49
|
+
*/
|
|
50
|
+
clearServers() {
|
|
51
|
+
this.servers.clear();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 获取服务器状态信息
|
|
55
|
+
*/
|
|
56
|
+
getServerStatus() {
|
|
57
|
+
const status = {};
|
|
58
|
+
for (const [name, server] of this.servers) if (server instanceof Server) status[name] = {
|
|
59
|
+
type: "REST API",
|
|
60
|
+
routes: server.routes?.length || 0
|
|
61
|
+
};
|
|
62
|
+
else if (server instanceof ComponentServer) status[name] = {
|
|
63
|
+
type: "Component",
|
|
64
|
+
routes: server.routes?.length || 0
|
|
65
|
+
};
|
|
66
|
+
return status;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/server/index.ts
|
|
73
|
+
var server_exports = /* @__PURE__ */ __exportAll({
|
|
74
|
+
BaseServer: () => BaseServer,
|
|
75
|
+
ComponentServer: () => ComponentServer,
|
|
76
|
+
Server: () => Server,
|
|
77
|
+
ServerFactory: () => ServerFactory
|
|
78
|
+
});
|
|
79
|
+
var init_server = __esmMin((() => {
|
|
80
|
+
init_server$1();
|
|
81
|
+
init_component_server();
|
|
82
|
+
init_server_factory();
|
|
83
|
+
init_base_server();
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
export { init_server_factory as i, server_exports as n, ServerFactory as r, init_server as t };
|
|
88
|
+
//# sourceMappingURL=server-Cbd3Ia51.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-Cbd3Ia51.mjs","names":[],"sources":["../src/server/server-factory.ts","../src/server/index.ts"],"sourcesContent":["import type { Route, NestedRoute } from \"../types\";\nimport type {\n ComponentRoute,\n NestedComponentRoute,\n} from \"../types/component-route\";\nimport { Server } from \"../server\";\nimport { ComponentServer } from \"./component-server\";\n\n/**\n * 服务器工厂类\n * 用于创建和管理不同类型的服务器\n */\nexport class ServerFactory {\n private servers: Map<string, Server | ComponentServer> = new Map();\n\n /**\n * 创建标准REST API服务器\n */\n createRestServer(routes: (Route | NestedRoute)[]): Server {\n const server = new Server(routes);\n this.servers.set(\"rest\", server);\n return server;\n }\n\n /**\n * 创建组件服务器\n */\n createComponentServer(\n routes: (ComponentRoute | NestedComponentRoute)[],\n ): ComponentServer {\n const server = new ComponentServer(routes);\n this.servers.set(\"component\", server);\n return server;\n }\n\n /**\n * 获取指定类型的服务器\n */\n getServer(type: \"rest\" | \"component\"): Server | ComponentServer | undefined {\n return this.servers.get(type);\n }\n\n /**\n * 获取所有服务器\n */\n getAllServers(): Map<string, Server | ComponentServer> {\n return this.servers;\n }\n\n /**\n * 移除指定类型的服务器\n */\n removeServer(type: string): boolean {\n return this.servers.delete(type);\n }\n\n /**\n * 清除所有服务器\n */\n clearServers(): void {\n this.servers.clear();\n }\n\n /**\n * 获取服务器状态信息\n */\n getServerStatus(): Record<string, { type: string; routes: number }> {\n const status: Record<string, { type: string; routes: number }> = {};\n\n for (const [name, server] of this.servers) {\n if (server instanceof Server) {\n status[name] = {\n type: \"REST API\",\n routes: (server as any).routes?.length || 0,\n };\n } else if (server instanceof ComponentServer) {\n status[name] = {\n type: \"Component\",\n routes: (server as any).routes?.length || 0,\n };\n }\n }\n\n return status;\n }\n}\n","/**\n * 服务器模块导出\n */\n\n// 主服务器类\nexport { Server } from \"./server\";\n\n// 组件服务器 (SSR)\nexport { ComponentServer } from \"./component-server\";\n\n// 服务器工厂\nexport { ServerFactory } from \"./server-factory\";\n\n// 基类 (仅用于扩展)\nexport { BaseServer } from \"./base-server\";\n"],"mappings":";;;;;;;;cAKmC;wBACkB;CAMxC,gBAAb,MAA2B;EACzB,AAAQ,0BAAiD,IAAI,KAAK;;;;EAKlE,iBAAiB,QAAyC;GACxD,MAAM,SAAS,IAAI,OAAO,OAAO;AACjC,QAAK,QAAQ,IAAI,QAAQ,OAAO;AAChC,UAAO;;;;;EAMT,sBACE,QACiB;GACjB,MAAM,SAAS,IAAI,gBAAgB,OAAO;AAC1C,QAAK,QAAQ,IAAI,aAAa,OAAO;AACrC,UAAO;;;;;EAMT,UAAU,MAAkE;AAC1E,UAAO,KAAK,QAAQ,IAAI,KAAK;;;;;EAM/B,gBAAuD;AACrD,UAAO,KAAK;;;;;EAMd,aAAa,MAAuB;AAClC,UAAO,KAAK,QAAQ,OAAO,KAAK;;;;;EAMlC,eAAqB;AACnB,QAAK,QAAQ,OAAO;;;;;EAMtB,kBAAoE;GAClE,MAAM,SAA2D,EAAE;AAEnE,QAAK,MAAM,CAAC,MAAM,WAAW,KAAK,QAChC,KAAI,kBAAkB,OACpB,QAAO,QAAQ;IACb,MAAM;IACN,QAAS,OAAe,QAAQ,UAAU;IAC3C;YACQ,kBAAkB,gBAC3B,QAAO,QAAQ;IACb,MAAM;IACN,QAAS,OAAe,QAAQ,UAAU;IAC3C;AAIL,UAAO;;;;;;;;;;;;;;gBC9EuB;wBAGmB;sBAGJ;mBAGN"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { a as Method, l as Route, n as FlattenedRoute, s as NestedRoute } from "./types-DuTa8AVN.mjs";
|
|
2
|
+
import { t as BaseServer } from "./base-server-DvGS6ATg.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/server/server.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Vafast 服务器
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const server = new Server([
|
|
12
|
+
* { method: "GET", path: "/", handler: () => new Response("Hello") },
|
|
13
|
+
* ]);
|
|
14
|
+
* export default { fetch: server.fetch };
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
declare class Server extends BaseServer {
|
|
18
|
+
private router;
|
|
19
|
+
private routes;
|
|
20
|
+
/** 是否已预编译 */
|
|
21
|
+
private isCompiled;
|
|
22
|
+
/** 预编译时的全局中间件数量 */
|
|
23
|
+
private compiledWithMiddlewareCount;
|
|
24
|
+
constructor(routes?: readonly (Route | NestedRoute)[]);
|
|
25
|
+
/**
|
|
26
|
+
* 预编译所有路由处理链
|
|
27
|
+
* 在添加所有路由和全局中间件后调用,可提升运行时性能
|
|
28
|
+
*/
|
|
29
|
+
compile(): this;
|
|
30
|
+
private registerRoutes;
|
|
31
|
+
/** 快速提取 pathname */
|
|
32
|
+
private extractPathname;
|
|
33
|
+
/** 生成 404/405 响应 */
|
|
34
|
+
private createErrorResponse;
|
|
35
|
+
/** 处理请求 */
|
|
36
|
+
fetch: (req: Request) => Promise<Response>;
|
|
37
|
+
addRoute(route: Route): void;
|
|
38
|
+
addRoutes(routes: readonly (Route | NestedRoute)[]): void;
|
|
39
|
+
getRoutes(): Array<{
|
|
40
|
+
method: Method;
|
|
41
|
+
path: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* 获取完整的路由元信息(不含 handler 和 middleware)
|
|
45
|
+
*
|
|
46
|
+
* 用于 API 文档生成、Webhook 事件注册、权限检查等场景
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const routes = server.getRoutesWithMeta()
|
|
51
|
+
* for (const route of routes) {
|
|
52
|
+
* console.log(route.fullPath, route.name, route.description)
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
getRoutesWithMeta(): FlattenedRoute[];
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { Server as t };
|
|
60
|
+
//# sourceMappingURL=server-D9gjszHe.d.mts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { i as RouteSchema, t as HandlerContext } from "./schema-CPQudJpE.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/sse.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SSE 事件类型
|
|
7
|
+
*/
|
|
8
|
+
interface SSEEvent<T = unknown> {
|
|
9
|
+
/** 事件名称(可选,默认为 message) */
|
|
10
|
+
event?: string;
|
|
11
|
+
/** 事件数据 */
|
|
12
|
+
data: T;
|
|
13
|
+
/** 事件 ID(可选) */
|
|
14
|
+
id?: string;
|
|
15
|
+
/** 重试间隔(毫秒,可选) */
|
|
16
|
+
retry?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* SSE 生成器函数类型
|
|
20
|
+
*/
|
|
21
|
+
type SSEGenerator<T extends RouteSchema = RouteSchema> = (ctx: HandlerContext<T>) => AsyncGenerator<SSEEvent<unknown>, void, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* SSE 标记类型 - 使用字面量品牌类型
|
|
24
|
+
*/
|
|
25
|
+
type SSEMarker = {
|
|
26
|
+
readonly __brand: 'SSE';
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* SSE Handler 类型标记
|
|
30
|
+
*/
|
|
31
|
+
interface SSEHandler<TSchema extends RouteSchema = RouteSchema> {
|
|
32
|
+
(req: Request): Promise<Response>;
|
|
33
|
+
/** 返回类型标记 - SSE 流的数据类型 */
|
|
34
|
+
readonly __returnType: unknown;
|
|
35
|
+
/** Schema 类型标记 */
|
|
36
|
+
readonly __schema: TSchema;
|
|
37
|
+
/** SSE 标记 - 使用品牌类型确保不被扩展 */
|
|
38
|
+
readonly __sse: SSEMarker;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 创建 SSE 流式响应处理器
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // 基础用法
|
|
46
|
+
* const streamChat = createSSEHandler(
|
|
47
|
+
* { query: Type.Object({ message: Type.String() }) },
|
|
48
|
+
* async function* ({ query }) {
|
|
49
|
+
* const response = await ai.chat(query.message);
|
|
50
|
+
*
|
|
51
|
+
* for await (const chunk of response) {
|
|
52
|
+
* yield { data: { text: chunk } };
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* );
|
|
56
|
+
*
|
|
57
|
+
* // 使用路由
|
|
58
|
+
* route('GET', '/chat/stream', streamChat)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare function createSSEHandler<const T extends RouteSchema>(schema: T, generator: SSEGenerator<T>): SSEHandler<T>;
|
|
62
|
+
declare function createSSEHandler(generator: SSEGenerator<RouteSchema>): SSEHandler<RouteSchema>;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { createSSEHandler as a, SSEMarker as i, SSEGenerator as n, SSEHandler as r, SSEEvent as t };
|
|
65
|
+
//# sourceMappingURL=sse-BMM6KTfy.d.mts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { a as parseCookies, l as parseHeaders, u as parseQuery } from "./parsers-CI_TZ7pO.mjs";
|
|
2
|
+
import { a as validateAllSchemas, i as precompileSchemas } from "./validators-BBrGePBr.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/sse.ts
|
|
5
|
+
/**
|
|
6
|
+
* 格式化 SSE 事件为字符串
|
|
7
|
+
*/
|
|
8
|
+
function formatSSEEvent(event) {
|
|
9
|
+
const lines = [];
|
|
10
|
+
if (event.id !== void 0) lines.push(`id: ${event.id}`);
|
|
11
|
+
if (event.event !== void 0) lines.push(`event: ${event.event}`);
|
|
12
|
+
if (event.retry !== void 0) lines.push(`retry: ${event.retry}`);
|
|
13
|
+
const dataLines = (typeof event.data === "string" ? event.data : JSON.stringify(event.data)).split("\n");
|
|
14
|
+
for (const line of dataLines) lines.push(`data: ${line}`);
|
|
15
|
+
return lines.join("\n") + "\n\n";
|
|
16
|
+
}
|
|
17
|
+
function createSSEHandler(schemaOrGenerator, maybeGenerator) {
|
|
18
|
+
const hasSchema = typeof schemaOrGenerator !== "function";
|
|
19
|
+
const schema = hasSchema ? schemaOrGenerator : {};
|
|
20
|
+
const generator = hasSchema ? maybeGenerator : schemaOrGenerator;
|
|
21
|
+
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) precompileSchemas(schema);
|
|
22
|
+
const handlerFn = async (req) => {
|
|
23
|
+
try {
|
|
24
|
+
const query = parseQuery(req);
|
|
25
|
+
const headers = parseHeaders(req);
|
|
26
|
+
const cookies = parseCookies(req);
|
|
27
|
+
const params = req.params || {};
|
|
28
|
+
const data = {
|
|
29
|
+
body: void 0,
|
|
30
|
+
query,
|
|
31
|
+
params,
|
|
32
|
+
headers,
|
|
33
|
+
cookies
|
|
34
|
+
};
|
|
35
|
+
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) validateAllSchemas(schema, data);
|
|
36
|
+
const stream = new ReadableStream({ async start(controller) {
|
|
37
|
+
const encoder = new TextEncoder();
|
|
38
|
+
try {
|
|
39
|
+
const gen = generator({
|
|
40
|
+
req,
|
|
41
|
+
body: void 0,
|
|
42
|
+
query,
|
|
43
|
+
params,
|
|
44
|
+
headers,
|
|
45
|
+
cookies
|
|
46
|
+
});
|
|
47
|
+
for await (const event of gen) {
|
|
48
|
+
const formatted = formatSSEEvent(event);
|
|
49
|
+
controller.enqueue(encoder.encode(formatted));
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const errorEvent = formatSSEEvent({
|
|
53
|
+
event: "error",
|
|
54
|
+
data: { message: error instanceof Error ? error.message : "Unknown error" }
|
|
55
|
+
});
|
|
56
|
+
controller.enqueue(encoder.encode(errorEvent));
|
|
57
|
+
} finally {
|
|
58
|
+
controller.close();
|
|
59
|
+
}
|
|
60
|
+
} });
|
|
61
|
+
return new Response(stream, { headers: {
|
|
62
|
+
"Content-Type": "text/event-stream",
|
|
63
|
+
"Cache-Control": "no-cache",
|
|
64
|
+
"Connection": "keep-alive",
|
|
65
|
+
"X-Accel-Buffering": "no"
|
|
66
|
+
} });
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return new Response(JSON.stringify({
|
|
69
|
+
success: false,
|
|
70
|
+
error: "Validation Error",
|
|
71
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
72
|
+
}), {
|
|
73
|
+
status: 400,
|
|
74
|
+
headers: { "Content-Type": "application/json" }
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const handler = handlerFn;
|
|
79
|
+
handler.__sse = { __brand: "SSE" };
|
|
80
|
+
handler.__schema = schema;
|
|
81
|
+
handler.__returnType = void 0;
|
|
82
|
+
return handler;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { createSSEHandler as t };
|
|
87
|
+
//# sourceMappingURL=sse-BT5yyLgX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-BT5yyLgX.mjs","names":[],"sources":["../src/utils/sse.ts"],"sourcesContent":["/**\n * Server-Sent Events (SSE) 支持\n *\n * 用于实现流式响应,如 AI 聊天、实时通知等\n *\n * @example\n * ```typescript\n * import { createSSEHandler, Type } from 'vafast'\n *\n * const streamHandler = createSSEHandler(\n * { query: Type.Object({ prompt: Type.String() }) },\n * async function* ({ query }) {\n * yield { event: 'start', data: { message: 'Starting...' } }\n *\n * for await (const chunk of aiStream(query.prompt)) {\n * yield { data: chunk }\n * }\n *\n * yield { event: 'end', data: { message: 'Done!' } }\n * }\n * )\n * ```\n */\n\nimport type { RouteSchema, HandlerContext } from \"../types/schema\";\nimport { parseQuery, parseHeaders, parseCookies } from \"./parsers\";\nimport { precompileSchemas, validateAllSchemas } from \"./validators/validators\";\n\n/**\n * SSE 事件类型\n */\nexport interface SSEEvent<T = unknown> {\n /** 事件名称(可选,默认为 message) */\n event?: string;\n /** 事件数据 */\n data: T;\n /** 事件 ID(可选) */\n id?: string;\n /** 重试间隔(毫秒,可选) */\n retry?: number;\n}\n\n/**\n * SSE 生成器函数类型\n */\nexport type SSEGenerator<T extends RouteSchema = RouteSchema> = (\n ctx: HandlerContext<T>\n) => AsyncGenerator<SSEEvent<unknown>, void, unknown>;\n\n/**\n * 格式化 SSE 事件为字符串\n */\nfunction formatSSEEvent(event: SSEEvent): string {\n const lines: string[] = [];\n\n if (event.id !== undefined) {\n lines.push(`id: ${event.id}`);\n }\n\n if (event.event !== undefined) {\n lines.push(`event: ${event.event}`);\n }\n\n if (event.retry !== undefined) {\n lines.push(`retry: ${event.retry}`);\n }\n\n // 数据可能是多行的,需要分行处理\n const dataStr = typeof event.data === 'string'\n ? event.data\n : JSON.stringify(event.data);\n\n const dataLines = dataStr.split('\\n');\n for (const line of dataLines) {\n lines.push(`data: ${line}`);\n }\n\n return lines.join('\\n') + '\\n\\n';\n}\n\n/**\n * SSE 标记类型 - 使用字面量品牌类型\n */\nexport type SSEMarker = { readonly __brand: 'SSE' }\n\n/**\n * SSE Handler 类型标记\n */\nexport interface SSEHandler<TSchema extends RouteSchema = RouteSchema> {\n (req: Request): Promise<Response>;\n /** 返回类型标记 - SSE 流的数据类型 */\n readonly __returnType: unknown;\n /** Schema 类型标记 */\n readonly __schema: TSchema;\n /** SSE 标记 - 使用品牌类型确保不被扩展 */\n readonly __sse: SSEMarker;\n}\n\n/**\n * 创建 SSE 流式响应处理器\n *\n * @example\n * ```typescript\n * // 基础用法\n * const streamChat = createSSEHandler(\n * { query: Type.Object({ message: Type.String() }) },\n * async function* ({ query }) {\n * const response = await ai.chat(query.message);\n *\n * for await (const chunk of response) {\n * yield { data: { text: chunk } };\n * }\n * }\n * );\n *\n * // 使用路由\n * route('GET', '/chat/stream', streamChat)\n * ```\n */\nexport function createSSEHandler<const T extends RouteSchema>(\n schema: T,\n generator: SSEGenerator<T>\n): SSEHandler<T>;\n\nexport function createSSEHandler(\n generator: SSEGenerator<RouteSchema>\n): SSEHandler<RouteSchema>;\n\nexport function createSSEHandler<const T extends RouteSchema>(\n schemaOrGenerator: T | SSEGenerator<T>,\n maybeGenerator?: SSEGenerator<T>\n): SSEHandler<T> {\n // 判断调用方式\n const hasSchema = typeof schemaOrGenerator !== 'function';\n const schema = hasSchema ? (schemaOrGenerator as T) : ({} as T);\n const generator = hasSchema\n ? maybeGenerator!\n : (schemaOrGenerator as SSEGenerator<T>);\n\n // 预编译 schema\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\n precompileSchemas(schema);\n }\n\n const handlerFn = async (req: Request): Promise<Response> => {\n try {\n // 解析请求数据\n const query = parseQuery(req);\n const headers = parseHeaders(req);\n const cookies = parseCookies(req);\n const params = ((req as unknown as Record<string, unknown>).params as Record<string, string>) || {};\n\n // 验证 schema\n const data = { body: undefined, query, params, headers, cookies };\n if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {\n validateAllSchemas(schema, data);\n }\n\n // 创建 SSE 流\n const stream = new ReadableStream({\n async start(controller) {\n const encoder = new TextEncoder();\n\n try {\n const gen = generator({\n req,\n body: undefined as HandlerContext<T>['body'],\n query: query as HandlerContext<T>['query'],\n params: params as HandlerContext<T>['params'],\n headers: headers as HandlerContext<T>['headers'],\n cookies: cookies as HandlerContext<T>['cookies'],\n });\n\n for await (const event of gen) {\n const formatted = formatSSEEvent(event);\n controller.enqueue(encoder.encode(formatted));\n }\n } catch (error) {\n // 发送错误事件\n const errorEvent = formatSSEEvent({\n event: 'error',\n data: {\n message: error instanceof Error ? error.message : 'Unknown error'\n }\n });\n controller.enqueue(encoder.encode(errorEvent));\n } finally {\n controller.close();\n }\n }\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no', // Nginx 禁用缓冲\n }\n });\n } catch (error) {\n // 验证错误等\n return new Response(\n JSON.stringify({\n success: false,\n error: 'Validation Error',\n message: error instanceof Error ? error.message : 'Unknown error'\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n };\n\n // 添加类型标记\n const handler = handlerFn as SSEHandler<T>;\n (handler as unknown as { __sse: SSEMarker }).__sse = { __brand: 'SSE' } as const;\n (handler as unknown as { __schema: T }).__schema = schema;\n (handler as unknown as { __returnType: unknown }).__returnType = undefined;\n return handler;\n}\n\n\n"],"mappings":";;;;;;;AAoDA,SAAS,eAAe,OAAyB;CAC/C,MAAM,QAAkB,EAAE;AAE1B,KAAI,MAAM,OAAO,OACf,OAAM,KAAK,OAAO,MAAM,KAAK;AAG/B,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;AAGrC,KAAI,MAAM,UAAU,OAClB,OAAM,KAAK,UAAU,MAAM,QAAQ;CAQrC,MAAM,aAJU,OAAO,MAAM,SAAS,WAClC,MAAM,OACN,KAAK,UAAU,MAAM,KAAK,EAEJ,MAAM,KAAK;AACrC,MAAK,MAAM,QAAQ,UACjB,OAAM,KAAK,SAAS,OAAO;AAG7B,QAAO,MAAM,KAAK,KAAK,GAAG;;AAmD5B,SAAgB,iBACd,mBACA,gBACe;CAEf,MAAM,YAAY,OAAO,sBAAsB;CAC/C,MAAM,SAAS,YAAa,oBAA2B,EAAE;CACzD,MAAM,YAAY,YACd,iBACC;AAGL,KAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,mBAAkB,OAAO;CAG3B,MAAM,YAAY,OAAO,QAAoC;AAC3D,MAAI;GAEF,MAAM,QAAQ,WAAW,IAAI;GAC7B,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,UAAU,aAAa,IAAI;GACjC,MAAM,SAAW,IAA2C,UAAqC,EAAE;GAGnG,MAAM,OAAO;IAAE,MAAM;IAAW;IAAO;IAAQ;IAAS;IAAS;AACjE,OAAI,OAAO,QAAQ,OAAO,SAAS,OAAO,UAAU,OAAO,WAAW,OAAO,QAC3E,oBAAmB,QAAQ,KAAK;GAIlC,MAAM,SAAS,IAAI,eAAe,EAChC,MAAM,MAAM,YAAY;IACtB,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAI;KACF,MAAM,MAAM,UAAU;MACpB;MACA,MAAM;MACC;MACC;MACC;MACA;MACV,CAAC;AAEF,gBAAW,MAAM,SAAS,KAAK;MAC7B,MAAM,YAAY,eAAe,MAAM;AACvC,iBAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;;aAExC,OAAO;KAEd,MAAM,aAAa,eAAe;MAChC,OAAO;MACP,MAAM,EACJ,SAAS,iBAAiB,QAAQ,MAAM,UAAU,iBACnD;MACF,CAAC;AACF,gBAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;cACtC;AACR,gBAAW,OAAO;;MAGvB,CAAC;AAEF,UAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IACjB,cAAc;IACd,qBAAqB;IACtB,EACF,CAAC;WACK,OAAO;AAEd,UAAO,IAAI,SACT,KAAK,UAAU;IACb,SAAS;IACT,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;IACnD,CAAC,EACF;IACE,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAChD,CACF;;;CAKL,MAAM,UAAU;AAChB,CAAC,QAA4C,QAAQ,EAAE,SAAS,OAAO;AACvE,CAAC,QAAuC,WAAW;AACnD,CAAC,QAAiD,eAAe;AACjE,QAAO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { a as Method, c as ResponseBody, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute } from "../types-DuTa8AVN.mjs";
|
|
2
|
+
import { c as createTypedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BJ-40LNI.mjs";
|
|
3
|
+
import { n as FlattenedComponentRoute, r as NestedComponentRoute, t as ComponentRoute } from "../component-route-CZawYn61.mjs";
|
|
4
|
+
import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CPQudJpE.mjs";
|
|
5
|
+
import "../index-CzItj62a.mjs";
|
|
6
|
+
export { BaseRouteConfig, CompatibleRoute, ComponentRoute, ExtendedRouteConfig, FlattenedComponentRoute, FlattenedRoute, Handler, HandlerContext, HandlerContextWithExtra, InferSchema, Method, Middleware, NestedComponentRoute, NestedRoute, NestedRouteConfig, ResponseBody, Route, RouteSchema, TypedHandler, TypedRoute, TypedRouteConfig, createTypedRoute, isTypedRoute };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as Middleware, c as createTypedRoute, i as FlattenedRoute, l as isTypedRoute, n as CompatibleRoute, o as NestedRouteConfig, r as ExtendedRouteConfig, s as TypedRoute, t as BaseRouteConfig } from "../route-BJ-40LNI.mjs";
|
|
2
|
+
export { BaseRouteConfig, CompatibleRoute, ExtendedRouteConfig, FlattenedRoute, Middleware, NestedRouteConfig, TypedRoute, createTypedRoute, isTypedRoute };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as TypedHandler, i as RouteSchema, n as HandlerContextWithExtra, o as TypedRouteConfig, r as InferSchema, t as HandlerContext } from "../schema-CPQudJpE.mjs";
|
|
2
|
+
export { HandlerContext, HandlerContextWithExtra, InferSchema, RouteSchema, TypedHandler, TypedRouteConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as Method, c as ResponseBody, i as LegacyHandler, l as Route, n as FlattenedRoute, o as Middleware, r as Handler, s as NestedRoute, t as FactoryHandler } from "../types-DuTa8AVN.mjs";
|
|
2
|
+
export { FactoryHandler, FlattenedRoute, Handler, LegacyHandler, Method, Middleware, NestedRoute, ResponseBody, Route };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/types/types.d.ts
|
|
1
2
|
type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
|
2
3
|
/** 支持的响应类型 - 由 mapResponse 自动转换 */
|
|
3
4
|
type ResponseBody = Response | string | number | boolean | object | null | undefined | ReadableStream | Blob | ArrayBuffer;
|
|
@@ -11,33 +12,34 @@ type Handler = LegacyHandler | FactoryHandler;
|
|
|
11
12
|
/** 中间件(返回值必须是 Response 或 Promise<Response>) */
|
|
12
13
|
type Middleware = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>;
|
|
13
14
|
interface Route {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
method: Method;
|
|
16
|
+
path: string;
|
|
17
|
+
handler: Handler;
|
|
18
|
+
middleware?: Middleware[];
|
|
19
|
+
/** 路由名称(用于文档、事件等) */
|
|
20
|
+
name?: string;
|
|
21
|
+
/** 路由描述 */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** 允许任意扩展(支持 Webhook、权限等插件) */
|
|
24
|
+
[key: string]: unknown;
|
|
24
25
|
}
|
|
25
26
|
interface NestedRoute {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
path: string;
|
|
28
|
+
middleware?: Middleware[];
|
|
29
|
+
children?: (NestedRoute | Route)[];
|
|
30
|
+
/** 路由组名称 */
|
|
31
|
+
name?: string;
|
|
32
|
+
/** 路由组描述 */
|
|
33
|
+
description?: string;
|
|
34
|
+
/** 允许任意扩展 */
|
|
35
|
+
[key: string]: unknown;
|
|
35
36
|
}
|
|
36
37
|
interface FlattenedRoute extends Route {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
fullPath: string;
|
|
39
|
+
middlewareChain: Middleware[];
|
|
40
|
+
/** 父级路由的名称(用于分类显示) */
|
|
41
|
+
parentName?: string;
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
-
export
|
|
43
|
+
//#endregion
|
|
44
|
+
export { Method as a, ResponseBody as c, LegacyHandler as i, Route as l, FlattenedRoute as n, Middleware as o, Handler as r, NestedRoute as s, FactoryHandler as t };
|
|
45
|
+
//# sourceMappingURL=types-DuTa8AVN.d.mts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { FormatRegistry } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/formats.ts
|
|
4
|
+
/**
|
|
5
|
+
* TypeBox Format 验证器
|
|
6
|
+
*
|
|
7
|
+
* 内置常用的 format 验证,对标 Zod 的内置验证
|
|
8
|
+
* 框架启动时自动注册
|
|
9
|
+
*
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
13
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
14
|
+
const UUID_ANY_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15
|
+
const CUID_REGEX = /^c[^\s-]{8,}$/i;
|
|
16
|
+
const CUID2_REGEX = /^[0-9a-z]+$/;
|
|
17
|
+
const ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
|
|
18
|
+
const NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/;
|
|
19
|
+
const URL_REGEX = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$/;
|
|
20
|
+
const IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
21
|
+
const IPV6_REGEX = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$/;
|
|
22
|
+
const CIDR_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(?:3[0-2]|[12]?[0-9])$/;
|
|
23
|
+
const DATE_REGEX = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/;
|
|
24
|
+
const TIME_REGEX = /^(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.\d{1,3})?$/;
|
|
25
|
+
const DATE_TIME_REGEX = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.\d{1,3})?(?:Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])?$/;
|
|
26
|
+
const DURATION_REGEX = /^P(?:\d+Y)?(?:\d+M)?(?:\d+W)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/;
|
|
27
|
+
const HOSTNAME_REGEX = /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)*(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;
|
|
28
|
+
const PHONE_CN_REGEX = /^1[3-9]\d{9}$/;
|
|
29
|
+
const PHONE_E164_REGEX = /^\+[1-9]\d{6,14}$/;
|
|
30
|
+
const OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/;
|
|
31
|
+
const HEX_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
|
|
32
|
+
const RGB_COLOR_REGEX = /^rgba?\(\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/;
|
|
33
|
+
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
34
|
+
const BASE64URL_REGEX = /^[A-Za-z0-9_-]+$/;
|
|
35
|
+
const JWT_REGEX = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
36
|
+
const EMOJI_REGEX = /^[\p{Emoji}]+$/u;
|
|
37
|
+
const SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
38
|
+
const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
39
|
+
function isValidCreditCard(value) {
|
|
40
|
+
const digits = value.replace(/\D/g, "");
|
|
41
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
42
|
+
let sum = 0;
|
|
43
|
+
let isEven = false;
|
|
44
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
45
|
+
let digit = parseInt(digits[i], 10);
|
|
46
|
+
if (isEven) {
|
|
47
|
+
digit *= 2;
|
|
48
|
+
if (digit > 9) digit -= 9;
|
|
49
|
+
}
|
|
50
|
+
sum += digit;
|
|
51
|
+
isEven = !isEven;
|
|
52
|
+
}
|
|
53
|
+
return sum % 10 === 0;
|
|
54
|
+
}
|
|
55
|
+
let isRegistered = false;
|
|
56
|
+
/**
|
|
57
|
+
* 注册所有内置 format 验证器
|
|
58
|
+
* 框架自动调用,也可手动调用
|
|
59
|
+
*/
|
|
60
|
+
function registerFormats() {
|
|
61
|
+
if (isRegistered) return;
|
|
62
|
+
isRegistered = true;
|
|
63
|
+
FormatRegistry.Set("email", (v) => EMAIL_REGEX.test(v));
|
|
64
|
+
FormatRegistry.Set("uuid", (v) => UUID_REGEX.test(v));
|
|
65
|
+
FormatRegistry.Set("uuid-any", (v) => UUID_ANY_REGEX.test(v));
|
|
66
|
+
FormatRegistry.Set("cuid", (v) => CUID_REGEX.test(v));
|
|
67
|
+
FormatRegistry.Set("cuid2", (v) => CUID2_REGEX.test(v) && v.length >= 1);
|
|
68
|
+
FormatRegistry.Set("ulid", (v) => ULID_REGEX.test(v));
|
|
69
|
+
FormatRegistry.Set("nanoid", (v) => NANOID_REGEX.test(v));
|
|
70
|
+
FormatRegistry.Set("objectid", (v) => OBJECTID_REGEX.test(v));
|
|
71
|
+
FormatRegistry.Set("slug", (v) => SLUG_REGEX.test(v));
|
|
72
|
+
FormatRegistry.Set("url", (v) => URL_REGEX.test(v));
|
|
73
|
+
FormatRegistry.Set("uri", (v) => URL_REGEX.test(v));
|
|
74
|
+
FormatRegistry.Set("ipv4", (v) => IPV4_REGEX.test(v));
|
|
75
|
+
FormatRegistry.Set("ipv6", (v) => IPV6_REGEX.test(v));
|
|
76
|
+
FormatRegistry.Set("ip", (v) => IPV4_REGEX.test(v) || IPV6_REGEX.test(v));
|
|
77
|
+
FormatRegistry.Set("cidr", (v) => CIDR_REGEX.test(v));
|
|
78
|
+
FormatRegistry.Set("hostname", (v) => HOSTNAME_REGEX.test(v));
|
|
79
|
+
FormatRegistry.Set("date", (v) => DATE_REGEX.test(v));
|
|
80
|
+
FormatRegistry.Set("time", (v) => TIME_REGEX.test(v));
|
|
81
|
+
FormatRegistry.Set("date-time", (v) => DATE_TIME_REGEX.test(v));
|
|
82
|
+
FormatRegistry.Set("datetime", (v) => DATE_TIME_REGEX.test(v));
|
|
83
|
+
FormatRegistry.Set("duration", (v) => DURATION_REGEX.test(v));
|
|
84
|
+
FormatRegistry.Set("phone", (v) => PHONE_CN_REGEX.test(v));
|
|
85
|
+
FormatRegistry.Set("phone-cn", (v) => PHONE_CN_REGEX.test(v));
|
|
86
|
+
FormatRegistry.Set("phone-e164", (v) => PHONE_E164_REGEX.test(v));
|
|
87
|
+
FormatRegistry.Set("base64", (v) => BASE64_REGEX.test(v));
|
|
88
|
+
FormatRegistry.Set("base64url", (v) => BASE64URL_REGEX.test(v));
|
|
89
|
+
FormatRegistry.Set("jwt", (v) => JWT_REGEX.test(v));
|
|
90
|
+
FormatRegistry.Set("hex-color", (v) => HEX_COLOR_REGEX.test(v));
|
|
91
|
+
FormatRegistry.Set("rgb-color", (v) => RGB_COLOR_REGEX.test(v));
|
|
92
|
+
FormatRegistry.Set("color", (v) => HEX_COLOR_REGEX.test(v) || RGB_COLOR_REGEX.test(v));
|
|
93
|
+
FormatRegistry.Set("emoji", (v) => EMOJI_REGEX.test(v));
|
|
94
|
+
FormatRegistry.Set("semver", (v) => SEMVER_REGEX.test(v));
|
|
95
|
+
FormatRegistry.Set("credit-card", isValidCreditCard);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 自定义注册 format
|
|
99
|
+
*/
|
|
100
|
+
function registerFormat(name, validator) {
|
|
101
|
+
FormatRegistry.Set(name, validator);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 检查 format 是否已注册
|
|
105
|
+
*/
|
|
106
|
+
function hasFormat(name) {
|
|
107
|
+
return FormatRegistry.Has(name);
|
|
108
|
+
}
|
|
109
|
+
const Patterns = {
|
|
110
|
+
EMAIL: EMAIL_REGEX,
|
|
111
|
+
UUID: UUID_REGEX,
|
|
112
|
+
URL: URL_REGEX,
|
|
113
|
+
IPV4: IPV4_REGEX,
|
|
114
|
+
IPV6: IPV6_REGEX,
|
|
115
|
+
DATE: DATE_REGEX,
|
|
116
|
+
TIME: TIME_REGEX,
|
|
117
|
+
DATE_TIME: DATE_TIME_REGEX,
|
|
118
|
+
PHONE_CN: PHONE_CN_REGEX,
|
|
119
|
+
PHONE_E164: PHONE_E164_REGEX,
|
|
120
|
+
OBJECTID: OBJECTID_REGEX,
|
|
121
|
+
HEX_COLOR: HEX_COLOR_REGEX,
|
|
122
|
+
SLUG: SLUG_REGEX,
|
|
123
|
+
SEMVER: SEMVER_REGEX,
|
|
124
|
+
JWT: JWT_REGEX
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
export { Patterns, hasFormat, registerFormat, registerFormats };
|
|
129
|
+
//# sourceMappingURL=formats.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formats.mjs","names":[],"sources":["../../src/utils/formats.ts"],"sourcesContent":["/**\n * TypeBox Format 验证器\n *\n * 内置常用的 format 验证,对标 Zod 的内置验证\n * 框架启动时自动注册\n *\n * @version 1.0.0\n */\n\nimport { FormatRegistry } from \"@sinclair/typebox\";\n\n// ============== 正则表达式 ==============\n\n// 邮箱 (RFC 5322 简化版)\nconst EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n// UUID v4\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n// UUID 任意版本\nconst UUID_ANY_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// CUID\nconst CUID_REGEX = /^c[^\\s-]{8,}$/i;\n\n// CUID2\nconst CUID2_REGEX = /^[0-9a-z]+$/;\n\n// ULID\nconst ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/i;\n\n// NanoID (默认 21 字符)\nconst NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/;\n\n// URL\nconst URL_REGEX = /^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$/;\n\n// IPv4\nconst IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n// IPv6 (简化版)\nconst IPV6_REGEX = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$/;\n\n// CIDR (IPv4)\nconst CIDR_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(?:3[0-2]|[12]?[0-9])$/;\n\n// 日期 (YYYY-MM-DD)\nconst DATE_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/;\n\n// 时间 (HH:mm:ss 或 HH:mm:ss.SSS)\nconst TIME_REGEX = /^(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?$/;\n\n// ISO 日期时间\nconst DATE_TIME_REGEX = /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.\\d{1,3})?(?:Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])?$/;\n\n// ISO 8601 Duration (P1Y2M3DT4H5M6S)\nconst DURATION_REGEX = /^P(?:\\d+Y)?(?:\\d+M)?(?:\\d+W)?(?:\\d+D)?(?:T(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?$/;\n\n// Hostname (RFC 1123)\nconst HOSTNAME_REGEX = /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)*(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;\n\n// 手机号 (中国大陆)\nconst PHONE_CN_REGEX = /^1[3-9]\\d{9}$/;\n\n// 手机号 (国际格式 E.164)\nconst PHONE_E164_REGEX = /^\\+[1-9]\\d{6,14}$/;\n\n// MongoDB ObjectId\nconst OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/;\n\n// 十六进制颜色\nconst HEX_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n\n// RGB/RGBA 颜色\nconst RGB_COLOR_REGEX = /^rgba?\\(\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\s*,\\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\\s*,\\s*(?:0|1|0?\\.\\d+))?\\s*\\)$/;\n\n// Base64\nconst BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n// Base64 URL Safe\nconst BASE64URL_REGEX = /^[A-Za-z0-9_-]+$/;\n\n// JWT (3 部分 base64url)\nconst JWT_REGEX = /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\n\n// Emoji (简化检测)\nconst EMOJI_REGEX = /^[\\p{Emoji}]+$/u;\n\n// Slug (URL 友好字符串)\nconst SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n// Semver (语义化版本)\nconst SEMVER_REGEX = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n// 信用卡号 (Luhn 算法验证)\nfunction isValidCreditCard(value: string): boolean {\n const digits = value.replace(/\\D/g, \"\");\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let isEven = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let digit = parseInt(digits[i], 10);\n if (isEven) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n isEven = !isEven;\n }\n return sum % 10 === 0;\n}\n\n// ============== Format 注册 ==============\n\nlet isRegistered = false;\n\n/**\n * 注册所有内置 format 验证器\n * 框架自动调用,也可手动调用\n */\nexport function registerFormats(): void {\n if (isRegistered) return;\n isRegistered = true;\n\n // === 字符串标识符 ===\n FormatRegistry.Set(\"email\", (v) => EMAIL_REGEX.test(v));\n FormatRegistry.Set(\"uuid\", (v) => UUID_REGEX.test(v));\n FormatRegistry.Set(\"uuid-any\", (v) => UUID_ANY_REGEX.test(v));\n FormatRegistry.Set(\"cuid\", (v) => CUID_REGEX.test(v));\n FormatRegistry.Set(\"cuid2\", (v) => CUID2_REGEX.test(v) && v.length >= 1);\n FormatRegistry.Set(\"ulid\", (v) => ULID_REGEX.test(v));\n FormatRegistry.Set(\"nanoid\", (v) => NANOID_REGEX.test(v));\n FormatRegistry.Set(\"objectid\", (v) => OBJECTID_REGEX.test(v));\n FormatRegistry.Set(\"slug\", (v) => SLUG_REGEX.test(v));\n\n // === 网络相关 ===\n FormatRegistry.Set(\"url\", (v) => URL_REGEX.test(v));\n FormatRegistry.Set(\"uri\", (v) => URL_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"ipv4\", (v) => IPV4_REGEX.test(v));\n FormatRegistry.Set(\"ipv6\", (v) => IPV6_REGEX.test(v));\n FormatRegistry.Set(\"ip\", (v) => IPV4_REGEX.test(v) || IPV6_REGEX.test(v));\n FormatRegistry.Set(\"cidr\", (v) => CIDR_REGEX.test(v));\n FormatRegistry.Set(\"hostname\", (v) => HOSTNAME_REGEX.test(v));\n\n // === 日期时间 ===\n FormatRegistry.Set(\"date\", (v) => DATE_REGEX.test(v));\n FormatRegistry.Set(\"time\", (v) => TIME_REGEX.test(v));\n FormatRegistry.Set(\"date-time\", (v) => DATE_TIME_REGEX.test(v));\n FormatRegistry.Set(\"datetime\", (v) => DATE_TIME_REGEX.test(v)); // 别名\n FormatRegistry.Set(\"duration\", (v) => DURATION_REGEX.test(v));\n\n // === 手机号 ===\n FormatRegistry.Set(\"phone\", (v) => PHONE_CN_REGEX.test(v)); // 中国大陆\n FormatRegistry.Set(\"phone-cn\", (v) => PHONE_CN_REGEX.test(v));\n FormatRegistry.Set(\"phone-e164\", (v) => PHONE_E164_REGEX.test(v)); // 国际\n\n // === 编码格式 ===\n FormatRegistry.Set(\"base64\", (v) => BASE64_REGEX.test(v));\n FormatRegistry.Set(\"base64url\", (v) => BASE64URL_REGEX.test(v));\n FormatRegistry.Set(\"jwt\", (v) => JWT_REGEX.test(v));\n\n // === 颜色 ===\n FormatRegistry.Set(\"hex-color\", (v) => HEX_COLOR_REGEX.test(v));\n FormatRegistry.Set(\"rgb-color\", (v) => RGB_COLOR_REGEX.test(v));\n FormatRegistry.Set(\n \"color\",\n (v) => HEX_COLOR_REGEX.test(v) || RGB_COLOR_REGEX.test(v),\n );\n\n // === 其他 ===\n FormatRegistry.Set(\"emoji\", (v) => EMOJI_REGEX.test(v));\n FormatRegistry.Set(\"semver\", (v) => SEMVER_REGEX.test(v));\n FormatRegistry.Set(\"credit-card\", isValidCreditCard);\n}\n\n/**\n * 自定义注册 format\n */\nexport function registerFormat(\n name: string,\n validator: (value: string) => boolean,\n): void {\n FormatRegistry.Set(name, validator);\n}\n\n/**\n * 检查 format 是否已注册\n */\nexport function hasFormat(name: string): boolean {\n return FormatRegistry.Has(name);\n}\n\n// 导出正则(供外部使用)\nexport const Patterns = {\n EMAIL: EMAIL_REGEX,\n UUID: UUID_REGEX,\n URL: URL_REGEX,\n IPV4: IPV4_REGEX,\n IPV6: IPV6_REGEX,\n DATE: DATE_REGEX,\n TIME: TIME_REGEX,\n DATE_TIME: DATE_TIME_REGEX,\n PHONE_CN: PHONE_CN_REGEX,\n PHONE_E164: PHONE_E164_REGEX,\n OBJECTID: OBJECTID_REGEX,\n HEX_COLOR: HEX_COLOR_REGEX,\n SLUG: SLUG_REGEX,\n SEMVER: SEMVER_REGEX,\n JWT: JWT_REGEX,\n} as const;\n\n"],"mappings":"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"}
|