vafast 0.2.3 → 0.2.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 +156 -157
- package/dist/router/radix-tree.d.ts +12 -0
- package/dist/router/radix-tree.js +37 -1
- package/dist/server/server.d.ts +9 -0
- package/dist/server/server.js +25 -1
- package/dist/types/types.d.ts +6 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/parsers.d.ts +19 -1
- package/dist/utils/parsers.js +92 -9
- package/dist/utils/response.js +4 -3
- package/dist/utils/validators/validators.d.ts +36 -1
- package/dist/utils/validators/validators.js +83 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,219 +1,218 @@
|
|
|
1
1
|
# Vafast 🚀
|
|
2
2
|
|
|
3
|
-
> 超高性能的Node.js Web框架,专为Bun运行时设计
|
|
4
|
-
|
|
5
|
-
[](https://github.com/vafast/vafast/actions)
|
|
6
3
|
[](https://badge.fury.io/js/vafast)
|
|
7
4
|
[](https://opensource.org/licenses/MIT)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
**超高性能的 TypeScript Web 框架,类型安全、轻量、快速。**
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
```typescript
|
|
10
|
+
import { Server, createHandler } from 'vafast';
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- **内置验证**: 超优化的Schema验证器
|
|
18
|
-
- **零依赖**: 最小化外部依赖
|
|
12
|
+
const server = new Server([
|
|
13
|
+
{ method: 'GET', path: '/', handler: createHandler(() => 'Hello Vafast!') }
|
|
14
|
+
]);
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
export default { port: 3000, fetch: server.fetch };
|
|
17
|
+
```
|
|
21
18
|
|
|
22
19
|
```bash
|
|
23
|
-
#
|
|
24
|
-
bun
|
|
20
|
+
# 启动服务器
|
|
21
|
+
bun run index.ts # 或
|
|
22
|
+
npx tsx index.ts
|
|
23
|
+
```
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
## ⚡ 性能
|
|
26
|
+
|
|
27
|
+
| 框架 | RPS | 相对性能 |
|
|
28
|
+
|------|-----|----------|
|
|
29
|
+
| Elysia | ~118K | 100% |
|
|
30
|
+
| **Vafast** | **~101K** | **86%** |
|
|
31
|
+
| Express | ~56K | 48% |
|
|
32
|
+
| Hono | ~56K | 47% |
|
|
33
|
+
|
|
34
|
+
> **Vafast 比 Express/Hono 快约 1.8x!**
|
|
35
|
+
> 测试环境:Bun 1.2.20, macOS, wrk 基准测试 (4线程, 100连接, 30s)
|
|
36
|
+
|
|
37
|
+
## 📦 安装
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# npm
|
|
27
41
|
npm install vafast
|
|
28
42
|
|
|
29
|
-
#
|
|
30
|
-
|
|
43
|
+
# bun
|
|
44
|
+
bun add vafast
|
|
31
45
|
```
|
|
32
46
|
|
|
33
|
-
## 🎯
|
|
34
|
-
|
|
35
|
-
### 基础示例
|
|
47
|
+
## 🎯 核心功能
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
- ⚡ **JIT 编译验证器** - Schema 验证器编译缓存,避免重复编译
|
|
50
|
+
- 🔗 **中间件链预编译** - 路由注册时预编译处理链,运行时零开销
|
|
51
|
+
- 🎯 **快速请求解析** - 优化的 Query/Cookie 解析,比标准方法快 2x
|
|
52
|
+
- 🔒 **端到端类型安全** - 完整的 TypeScript 类型推断
|
|
53
|
+
- 🧩 **灵活中间件系统** - 可组合的中间件架构
|
|
54
|
+
- 📦 **零配置** - 开箱即用,无需复杂配置
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
const userSchema = Type.Object({
|
|
43
|
-
name: Type.String({ minLength: 1 }),
|
|
44
|
-
email: Type.String({ pattern: '^[^@]+@[^@]+\\.[^@]+$' }),
|
|
45
|
-
age: Type.Optional(Type.Number({ minimum: 0 }))
|
|
46
|
-
});
|
|
56
|
+
### 类型安全的路由
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
```typescript
|
|
59
|
+
import { Server, defineRoutes, createHandler, Type } from 'vafast';
|
|
60
|
+
|
|
61
|
+
const routes = defineRoutes([
|
|
62
|
+
{
|
|
63
|
+
method: 'POST',
|
|
64
|
+
path: '/users',
|
|
65
|
+
handler: createHandler(
|
|
66
|
+
{ body: Type.Object({ name: Type.String(), email: Type.String() }) },
|
|
67
|
+
({ body }) => {
|
|
68
|
+
// body.name 和 body.email 自动类型推断
|
|
69
|
+
return { success: true, user: body };
|
|
70
|
+
}
|
|
71
|
+
)
|
|
56
72
|
}
|
|
57
|
-
|
|
73
|
+
]);
|
|
58
74
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
const server = new Server(routes);
|
|
76
|
+
export default { port: 3000, fetch: server.fetch };
|
|
77
|
+
```
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
### 路径参数
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
{
|
|
83
|
+
method: 'GET',
|
|
84
|
+
path: '/users/:id',
|
|
85
|
+
handler: createHandler(
|
|
86
|
+
{ params: Type.Object({ id: Type.String() }) },
|
|
87
|
+
({ params }) => ({ userId: params.id })
|
|
88
|
+
)
|
|
89
|
+
}
|
|
66
90
|
```
|
|
67
91
|
|
|
68
|
-
###
|
|
92
|
+
### 中间件
|
|
69
93
|
|
|
70
94
|
```typescript
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
body: userSchema,
|
|
76
|
-
query: querySchema,
|
|
77
|
-
params: paramsSchema,
|
|
78
|
-
headers: headersSchema,
|
|
79
|
-
cookies: cookiesSchema
|
|
95
|
+
const authMiddleware = async (req, next) => {
|
|
96
|
+
const token = req.headers.get('Authorization');
|
|
97
|
+
if (!token) return new Response('Unauthorized', { status: 401 });
|
|
98
|
+
return next(req);
|
|
80
99
|
};
|
|
81
100
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
101
|
+
const routes = defineRoutes([
|
|
102
|
+
{
|
|
103
|
+
method: 'GET',
|
|
104
|
+
path: '/protected',
|
|
105
|
+
middleware: [authMiddleware],
|
|
106
|
+
handler: createHandler(() => ({ secret: 'data' }))
|
|
107
|
+
}
|
|
108
|
+
]);
|
|
90
109
|
```
|
|
91
110
|
|
|
92
|
-
|
|
111
|
+
### 嵌套路由
|
|
93
112
|
|
|
94
|
-
|
|
113
|
+
```typescript
|
|
114
|
+
const routes = defineRoutes([
|
|
115
|
+
{
|
|
116
|
+
path: '/api',
|
|
117
|
+
middleware: [apiMiddleware],
|
|
118
|
+
children: [
|
|
119
|
+
{ method: 'GET', path: '/users', handler: getUsers },
|
|
120
|
+
{ method: 'POST', path: '/users', handler: createUser },
|
|
121
|
+
{
|
|
122
|
+
path: '/users/:id',
|
|
123
|
+
children: [
|
|
124
|
+
{ method: 'GET', path: '/', handler: getUser },
|
|
125
|
+
{ method: 'PUT', path: '/', handler: updateUser },
|
|
126
|
+
{ method: 'DELETE', path: '/', handler: deleteUser },
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
]);
|
|
132
|
+
```
|
|
95
133
|
|
|
96
|
-
|
|
134
|
+
### JIT 编译验证器
|
|
97
135
|
|
|
98
|
-
|
|
99
|
-
- **内存优化**: 智能缓存和内存池管理
|
|
100
|
-
- **类型特化**: 针对特定数据类型的优化验证器
|
|
101
|
-
- **批量验证**: 支持数组数据的批量验证
|
|
136
|
+
Vafast 内置验证器 JIT 编译,自动缓存编译后的验证器:
|
|
102
137
|
|
|
103
138
|
```typescript
|
|
104
|
-
import {
|
|
105
|
-
|
|
106
|
-
createTypedValidator,
|
|
107
|
-
validateBatch
|
|
108
|
-
} from 'vafast/utils/validators/validators-ultra';
|
|
109
|
-
|
|
110
|
-
// 创建类型特化验证器
|
|
111
|
-
const userValidator = createTypedValidator(userSchema);
|
|
112
|
-
const validatedUser = userValidator(userData);
|
|
113
|
-
|
|
114
|
-
// 批量验证
|
|
115
|
-
const validatedUsers = validateBatch(userSchema, userArray);
|
|
116
|
-
```
|
|
139
|
+
import { createValidator, validateFast, precompileSchemas } from 'vafast';
|
|
140
|
+
import { Type } from '@sinclair/typebox';
|
|
117
141
|
|
|
118
|
-
|
|
142
|
+
const UserSchema = Type.Object({
|
|
143
|
+
name: Type.String(),
|
|
144
|
+
age: Type.Number()
|
|
145
|
+
});
|
|
119
146
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- [🔧 高级功能](./docs/advanced/)
|
|
124
|
-
- [📖 API参考](./docs/api/)
|
|
125
|
-
- [🧪 示例代码](./examples/)
|
|
147
|
+
// 方式一:自动缓存(推荐)
|
|
148
|
+
// 首次调用编译,后续调用使用缓存
|
|
149
|
+
const result = validateFast(UserSchema, data);
|
|
126
150
|
|
|
127
|
-
|
|
151
|
+
// 方式二:预编译验证器(最高性能)
|
|
152
|
+
const validateUser = createValidator(UserSchema);
|
|
153
|
+
const isValid = validateUser(data);
|
|
128
154
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
bun test
|
|
132
|
-
|
|
133
|
-
# 运行性能测试
|
|
134
|
-
bun run benchmark
|
|
135
|
-
|
|
136
|
-
# 运行特定测试
|
|
137
|
-
bun test:unit # 单元测试
|
|
138
|
-
bun test:integration # 集成测试
|
|
139
|
-
bun test:coverage # 覆盖率测试
|
|
140
|
-
|
|
141
|
-
# 运行基准测试
|
|
142
|
-
bun benchmark:quick # 快速测试
|
|
143
|
-
bun benchmark:validators # 验证器测试
|
|
144
|
-
bun benchmark:ultra # 超性能测试
|
|
145
|
-
bun benchmark:ultimate # 终极性能测试
|
|
146
|
-
bun benchmark:comprehensive # 综合测试
|
|
155
|
+
// 启动时预编译(避免首次请求开销)
|
|
156
|
+
precompileSchemas([UserSchema, PostSchema, CommentSchema]);
|
|
147
157
|
```
|
|
148
158
|
|
|
149
|
-
|
|
159
|
+
**性能效果:首次编译后,10000 次验证仅需 ~5ms**
|
|
150
160
|
|
|
151
|
-
|
|
161
|
+
### 中间件预编译
|
|
152
162
|
|
|
153
|
-
|
|
154
|
-
|--------|--------|----------|---------|
|
|
155
|
-
| **Ultra标准版** | 24.28ms | 基准 | 稳定 |
|
|
156
|
-
| **Ultra展开版** | 23.63ms | **+2.7%** | 稳定 |
|
|
163
|
+
Vafast 自动在路由注册时预编译中间件链,消除运行时组合开销:
|
|
157
164
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
我们欢迎所有形式的贡献!请查看我们的 [贡献指南](./docs/contributing/) 开始参与。
|
|
165
|
+
```typescript
|
|
166
|
+
const server = new Server(routes);
|
|
161
167
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
4. 推送到分支 (`git push origin feature/amazing-feature`)
|
|
167
|
-
5. 创建 [Pull Request](https://github.com/vafast/vafast/compare)
|
|
168
|
+
// 添加全局中间件后,手动触发预编译
|
|
169
|
+
server.use(authMiddleware);
|
|
170
|
+
server.use(logMiddleware);
|
|
171
|
+
server.compile(); // 预编译所有路由的处理链
|
|
168
172
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
- ✨ 新功能
|
|
172
|
-
- 📚 文档改进
|
|
173
|
-
- 🧪 测试用例
|
|
174
|
-
- 🚀 性能优化
|
|
173
|
+
// 预编译后,每次请求直接执行编译好的处理链,无需运行时组合
|
|
174
|
+
```
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
- [Issues](https://github.com/vafast/vafast/issues) - 报告 Bug 或请求功能
|
|
178
|
-
- [Discussions](https://github.com/vafast/vafast/discussions) - 讨论想法和问题
|
|
179
|
-
- [Releases](https://github.com/vafast/vafast/releases) - 查看最新版本
|
|
176
|
+
**性能效果:1000 次请求仅需 ~4ms,平均每次 0.004ms**
|
|
180
177
|
|
|
181
|
-
##
|
|
178
|
+
## 🔧 运行时支持
|
|
182
179
|
|
|
183
|
-
|
|
180
|
+
### Bun
|
|
184
181
|
|
|
185
|
-
|
|
182
|
+
```typescript
|
|
183
|
+
export default { port: 3000, fetch: server.fetch };
|
|
184
|
+
```
|
|
186
185
|
|
|
187
|
-
|
|
188
|
-
2. **🔒 开发体验**: 完整的TypeScript支持和智能提示
|
|
189
|
-
3. **✅ 生产就绪**: 经过严格测试的稳定版本
|
|
190
|
-
4. **⚡ 零配置**: 开箱即用的最佳实践配置
|
|
191
|
-
5. **🔄 活跃维护**: 持续的性能优化和功能更新
|
|
186
|
+
### Node.js
|
|
192
187
|
|
|
193
|
-
|
|
188
|
+
```typescript
|
|
189
|
+
import { serve } from '@vafast/node-server';
|
|
190
|
+
serve({ fetch: server.fetch, port: 3000 });
|
|
191
|
+
```
|
|
194
192
|
|
|
195
|
-
|
|
193
|
+
> 💡 两种运行时使用相同的 API,代码可无缝迁移
|
|
196
194
|
|
|
197
|
-
|
|
198
|
-
|--------|--------|----------|---------|
|
|
199
|
-
| **Ultra标准版** | 24.28ms | 基准 | 稳定 |
|
|
200
|
-
| **Ultra展开版** | 23.63ms | **+2.7%** | 稳定 |
|
|
195
|
+
## 📚 文档
|
|
201
196
|
|
|
202
|
-
|
|
197
|
+
- [快速开始](./docs/getting-started/quickstart.md)
|
|
198
|
+
- [API 参考](./docs/api/)
|
|
199
|
+
- [示例代码](./examples/)
|
|
203
200
|
|
|
204
|
-
|
|
205
|
-
- **🔒 类型安全**: 完整的TypeScript支持
|
|
206
|
-
- **🧩 中间件系统**: 灵活可扩展的中间件架构
|
|
207
|
-
- **✅ 内置验证**: 超优化的Schema验证器
|
|
208
|
-
- **🎯 零依赖**: 最小化外部依赖
|
|
209
|
-
- **🚀 Bun原生**: 专为Bun运行时优化
|
|
201
|
+
## 🤝 贡献
|
|
210
202
|
|
|
211
|
-
|
|
203
|
+
欢迎贡献!请查看 [贡献指南](./CONTRIBUTING.md)。
|
|
212
204
|
|
|
213
|
-
|
|
205
|
+
```bash
|
|
206
|
+
git clone https://github.com/vafast/vafast.git
|
|
207
|
+
cd vafast
|
|
208
|
+
npm install # 或 bun install
|
|
209
|
+
npm test # 或 bun test
|
|
210
|
+
```
|
|
214
211
|
|
|
215
212
|
## 📄 许可证
|
|
216
213
|
|
|
217
|
-
|
|
214
|
+
[MIT](./LICENSE)
|
|
218
215
|
|
|
216
|
+
---
|
|
219
217
|
|
|
218
|
+
**Vafast** - 让 Web 开发更快、更安全、更高效!
|
|
@@ -9,11 +9,15 @@
|
|
|
9
9
|
* - 通配符: /files/*, /static/*filepath
|
|
10
10
|
*/
|
|
11
11
|
import type { Handler, Middleware, Method } from "../types";
|
|
12
|
+
/** 预编译的处理器类型 */
|
|
13
|
+
type CompiledHandler = (req: Request) => Promise<Response>;
|
|
12
14
|
/** 路由匹配结果 */
|
|
13
15
|
export interface MatchResult {
|
|
14
16
|
handler: Handler;
|
|
15
17
|
middleware: Middleware[];
|
|
16
18
|
params: Record<string, string>;
|
|
19
|
+
/** 预编译后的完整处理链 */
|
|
20
|
+
compiled?: CompiledHandler;
|
|
17
21
|
}
|
|
18
22
|
/**
|
|
19
23
|
* Radix Tree 路由器
|
|
@@ -32,8 +36,15 @@ export declare class RadixRouter {
|
|
|
32
36
|
private createNode;
|
|
33
37
|
/** 分割路径 */
|
|
34
38
|
private splitPath;
|
|
39
|
+
/** 编译器函数 - 用于预编译中间件链 */
|
|
40
|
+
private compiler?;
|
|
41
|
+
/** 设置中间件编译器 */
|
|
42
|
+
setCompiler(compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler): void;
|
|
35
43
|
/** 注册路由 */
|
|
36
44
|
register(method: Method, pattern: string, handler: Handler, middleware?: Middleware[]): void;
|
|
45
|
+
/** 预编译所有路由(在添加全局中间件后调用) */
|
|
46
|
+
precompileAll(globalMiddleware: Middleware[]): void;
|
|
47
|
+
private precompileNode;
|
|
37
48
|
/** 匹配路由 */
|
|
38
49
|
match(method: Method, path: string): MatchResult | null;
|
|
39
50
|
/** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */
|
|
@@ -49,3 +60,4 @@ export declare class RadixRouter {
|
|
|
49
60
|
}>;
|
|
50
61
|
private collectRoutes;
|
|
51
62
|
}
|
|
63
|
+
export {};
|
|
@@ -35,6 +35,12 @@ export class RadixRouter {
|
|
|
35
35
|
splitPath(path) {
|
|
36
36
|
return path.split("/").filter(Boolean);
|
|
37
37
|
}
|
|
38
|
+
/** 编译器函数 - 用于预编译中间件链 */
|
|
39
|
+
compiler;
|
|
40
|
+
/** 设置中间件编译器 */
|
|
41
|
+
setCompiler(compiler) {
|
|
42
|
+
this.compiler = compiler;
|
|
43
|
+
}
|
|
38
44
|
/** 注册路由 */
|
|
39
45
|
register(method, pattern, handler, middleware = []) {
|
|
40
46
|
const segments = this.splitPath(pattern);
|
|
@@ -67,7 +73,36 @@ export class RadixRouter {
|
|
|
67
73
|
node = node.children[segment];
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
|
-
|
|
76
|
+
const routeHandler = { handler, middleware };
|
|
77
|
+
// 如果没有全局中间件且设置了编译器,预编译处理链
|
|
78
|
+
if (this.compiler && middleware.length === 0) {
|
|
79
|
+
routeHandler.compiled = this.compiler([], handler);
|
|
80
|
+
}
|
|
81
|
+
node.handlers[method] = routeHandler;
|
|
82
|
+
}
|
|
83
|
+
/** 预编译所有路由(在添加全局中间件后调用) */
|
|
84
|
+
precompileAll(globalMiddleware) {
|
|
85
|
+
if (!this.compiler)
|
|
86
|
+
return;
|
|
87
|
+
this.precompileNode(this.root, globalMiddleware);
|
|
88
|
+
}
|
|
89
|
+
precompileNode(node, globalMiddleware) {
|
|
90
|
+
for (const method in node.handlers) {
|
|
91
|
+
const routeHandler = node.handlers[method];
|
|
92
|
+
if (routeHandler) {
|
|
93
|
+
const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];
|
|
94
|
+
routeHandler.compiled = this.compiler(allMiddleware, routeHandler.handler);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const key in node.children) {
|
|
98
|
+
this.precompileNode(node.children[key], globalMiddleware);
|
|
99
|
+
}
|
|
100
|
+
if (node.paramChild) {
|
|
101
|
+
this.precompileNode(node.paramChild, globalMiddleware);
|
|
102
|
+
}
|
|
103
|
+
if (node.wildcardChild) {
|
|
104
|
+
this.precompileNode(node.wildcardChild, globalMiddleware);
|
|
105
|
+
}
|
|
71
106
|
}
|
|
72
107
|
/** 匹配路由 */
|
|
73
108
|
match(method, path) {
|
|
@@ -83,6 +118,7 @@ export class RadixRouter {
|
|
|
83
118
|
handler: routeHandler.handler,
|
|
84
119
|
middleware: routeHandler.middleware,
|
|
85
120
|
params,
|
|
121
|
+
compiled: routeHandler.compiled,
|
|
86
122
|
};
|
|
87
123
|
}
|
|
88
124
|
/** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */
|
package/dist/server/server.d.ts
CHANGED
|
@@ -20,7 +20,16 @@ import { BaseServer } from "./base-server";
|
|
|
20
20
|
export declare class Server extends BaseServer {
|
|
21
21
|
private router;
|
|
22
22
|
private routes;
|
|
23
|
+
/** 是否已预编译 */
|
|
24
|
+
private isCompiled;
|
|
25
|
+
/** 预编译时的全局中间件数量 */
|
|
26
|
+
private compiledWithMiddlewareCount;
|
|
23
27
|
constructor(routes?: (Route | NestedRoute)[]);
|
|
28
|
+
/**
|
|
29
|
+
* 预编译所有路由处理链
|
|
30
|
+
* 在添加所有路由和全局中间件后调用,可提升运行时性能
|
|
31
|
+
*/
|
|
32
|
+
compile(): this;
|
|
24
33
|
private registerRoutes;
|
|
25
34
|
/** 快速提取 pathname */
|
|
26
35
|
private extractPathname;
|
package/dist/server/server.js
CHANGED
|
@@ -23,14 +23,30 @@ import { RadixRouter } from "../router/radix-tree";
|
|
|
23
23
|
export class Server extends BaseServer {
|
|
24
24
|
router;
|
|
25
25
|
routes;
|
|
26
|
+
/** 是否已预编译 */
|
|
27
|
+
isCompiled = false;
|
|
28
|
+
/** 预编译时的全局中间件数量 */
|
|
29
|
+
compiledWithMiddlewareCount = 0;
|
|
26
30
|
constructor(routes = []) {
|
|
27
31
|
super();
|
|
28
32
|
this.router = new RadixRouter();
|
|
29
33
|
this.routes = [];
|
|
34
|
+
// 设置中间件编译器
|
|
35
|
+
this.router.setCompiler((middleware, handler) => composeMiddleware(middleware, handler));
|
|
30
36
|
if (routes.length > 0) {
|
|
31
37
|
this.registerRoutes(routes);
|
|
32
38
|
}
|
|
33
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* 预编译所有路由处理链
|
|
42
|
+
* 在添加所有路由和全局中间件后调用,可提升运行时性能
|
|
43
|
+
*/
|
|
44
|
+
compile() {
|
|
45
|
+
this.router.precompileAll(this.globalMiddleware);
|
|
46
|
+
this.isCompiled = true;
|
|
47
|
+
this.compiledWithMiddlewareCount = this.globalMiddleware.length;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
34
50
|
registerRoutes(routes) {
|
|
35
51
|
const flattened = flattenNestedRoutes(routes);
|
|
36
52
|
this.routes.push(...flattened);
|
|
@@ -39,6 +55,10 @@ export class Server extends BaseServer {
|
|
|
39
55
|
}
|
|
40
56
|
this.detectRouteConflicts(flattened);
|
|
41
57
|
this.logFlattenedRoutes(flattened);
|
|
58
|
+
// 自动预编译(如果没有全局中间件)
|
|
59
|
+
if (this.globalMiddleware.length === 0 && !this.isCompiled) {
|
|
60
|
+
this.compile();
|
|
61
|
+
}
|
|
42
62
|
}
|
|
43
63
|
/** 快速提取 pathname */
|
|
44
64
|
extractPathname(url) {
|
|
@@ -61,7 +81,11 @@ export class Server extends BaseServer {
|
|
|
61
81
|
const match = this.router.match(method, pathname);
|
|
62
82
|
if (match) {
|
|
63
83
|
req.params = match.params;
|
|
64
|
-
//
|
|
84
|
+
// 优先使用预编译的处理链(仅当全局中间件未变化时)
|
|
85
|
+
if (match.compiled && this.globalMiddleware.length === this.compiledWithMiddlewareCount) {
|
|
86
|
+
return match.compiled(req);
|
|
87
|
+
}
|
|
88
|
+
// 回退:运行时组合中间件
|
|
65
89
|
const allMiddleware = [...this.globalMiddleware, ...match.middleware];
|
|
66
90
|
const handler = composeMiddleware(allMiddleware, match.handler);
|
|
67
91
|
return handler(req);
|
package/dist/types/types.d.ts
CHANGED
|
@@ -2,7 +2,12 @@ export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "
|
|
|
2
2
|
/** 支持的响应类型 - 由 mapResponse 自动转换 */
|
|
3
3
|
export type ResponseBody = Response | string | number | boolean | object | null | undefined | ReadableStream | Blob | ArrayBuffer;
|
|
4
4
|
/** Handler 返回值(支持同步/异步,任意类型) */
|
|
5
|
-
|
|
5
|
+
/** 传统 Handler 类型 */
|
|
6
|
+
export type LegacyHandler = (req: Request, params?: Record<string, string>, user?: Record<string, any>) => ResponseBody | Promise<ResponseBody>;
|
|
7
|
+
/** createHandler 返回的类型 */
|
|
8
|
+
export type FactoryHandler = (req: Request) => Promise<Response>;
|
|
9
|
+
/** Handler 联合类型(支持两种风格) */
|
|
10
|
+
export type Handler = LegacyHandler | FactoryHandler;
|
|
6
11
|
/** 中间件(返回值必须是 Response 或 Promise<Response>) */
|
|
7
12
|
export type Middleware = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>;
|
|
8
13
|
export interface Route {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 工具函数模块导出
|
|
3
3
|
*/
|
|
4
4
|
export { createHandler, createHandlerWithExtra, simpleHandler, } from "./create-handler";
|
|
5
|
-
export { parseBody, parseQuery, parseHeaders, parseCookies } from "./parsers";
|
|
5
|
+
export { parseBody, parseQuery, parseQueryFast, parseHeaders, getHeader, parseCookies, parseCookiesFast, getCookie, } from "./parsers";
|
|
6
6
|
export { json, text, html, redirect, empty, stream } from "./response";
|
|
7
7
|
export { goAwait } from "./go-await";
|
|
8
8
|
export { base64urlEncode, base64urlDecode } from "./base64url";
|
|
@@ -10,3 +10,4 @@ export { setLocals, getLocals } from "./handle";
|
|
|
10
10
|
export { parseRequest, validateRequest, parseAndValidateRequest, createRequestValidator, } from "./request-validator";
|
|
11
11
|
export { HtmlRenderer } from "./html-renderer";
|
|
12
12
|
export { DependencyManager } from "./dependency-manager";
|
|
13
|
+
export { validateSchema, createValidator, validateFast, precompileSchemas, getValidatorCacheStats, } from "./validators/validators";
|
package/dist/utils/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// 处理器工厂
|
|
5
5
|
export { createHandler, createHandlerWithExtra, simpleHandler, } from "./create-handler";
|
|
6
6
|
// 请求解析
|
|
7
|
-
export { parseBody, parseQuery, parseHeaders, parseCookies } from "./parsers";
|
|
7
|
+
export { parseBody, parseQuery, parseQueryFast, parseHeaders, getHeader, parseCookies, parseCookiesFast, getCookie, } from "./parsers";
|
|
8
8
|
// 响应工具
|
|
9
9
|
export { json, text, html, redirect, empty, stream } from "./response";
|
|
10
10
|
// Go 风格错误处理
|
|
@@ -19,3 +19,5 @@ export { parseRequest, validateRequest, parseAndValidateRequest, createRequestVa
|
|
|
19
19
|
export { HtmlRenderer } from "./html-renderer";
|
|
20
20
|
// 依赖管理
|
|
21
21
|
export { DependencyManager } from "./dependency-manager";
|
|
22
|
+
// 验证器(JIT 编译)
|
|
23
|
+
export { validateSchema, createValidator, validateFast, precompileSchemas, getValidatorCacheStats, } from "./validators/validators";
|
package/dist/utils/parsers.d.ts
CHANGED
|
@@ -29,8 +29,26 @@ export declare function parseFormData(req: Request): Promise<FormData>;
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function parseFile(req: Request): Promise<FileInfo>;
|
|
31
31
|
/** 获取查询字符串,直接返回对象 */
|
|
32
|
-
export declare function parseQuery(req: Request): Record<string,
|
|
32
|
+
export declare function parseQuery(req: Request): Record<string, unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* 快速解析简单查询字符串(不支持嵌套,但更快)
|
|
35
|
+
* 适用于简单的 key=value&key2=value2 场景
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseQueryFast(req: Request): Record<string, string>;
|
|
33
38
|
/** 解析请求头,返回对象 */
|
|
34
39
|
export declare function parseHeaders(req: Request): Record<string, string>;
|
|
40
|
+
/**
|
|
41
|
+
* 获取单个请求头(避免解析全部)
|
|
42
|
+
*/
|
|
43
|
+
export declare function getHeader(req: Request, name: string): string | null;
|
|
35
44
|
/** 使用cookie库解析Cookie,保证可靠性 */
|
|
36
45
|
export declare function parseCookies(req: Request): Record<string, string>;
|
|
46
|
+
/**
|
|
47
|
+
* 快速解析 Cookie(简化版,不使用外部库)
|
|
48
|
+
* 适用于简单的 cookie 场景
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseCookiesFast(req: Request): Record<string, string>;
|
|
51
|
+
/**
|
|
52
|
+
* 获取单个 Cookie 值(避免解析全部)
|
|
53
|
+
*/
|
|
54
|
+
export declare function getCookie(req: Request, name: string): string | null;
|
package/dist/utils/parsers.js
CHANGED
|
@@ -87,21 +87,62 @@ export async function parseFile(req) {
|
|
|
87
87
|
}
|
|
88
88
|
return formData.files[fileKeys[0]];
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* 快速提取 query string(避免创建 URL 对象)
|
|
92
|
+
*/
|
|
93
|
+
function extractQueryString(url) {
|
|
94
|
+
const qIndex = url.indexOf("?");
|
|
95
|
+
if (qIndex === -1)
|
|
96
|
+
return "";
|
|
97
|
+
const hashIndex = url.indexOf("#", qIndex);
|
|
98
|
+
return hashIndex === -1
|
|
99
|
+
? url.substring(qIndex + 1)
|
|
100
|
+
: url.substring(qIndex + 1, hashIndex);
|
|
101
|
+
}
|
|
90
102
|
/** 获取查询字符串,直接返回对象 */
|
|
91
103
|
export function parseQuery(req) {
|
|
92
|
-
const
|
|
93
|
-
|
|
104
|
+
const queryString = extractQueryString(req.url);
|
|
105
|
+
if (!queryString)
|
|
106
|
+
return {};
|
|
107
|
+
return qs.parse(queryString);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 快速解析简单查询字符串(不支持嵌套,但更快)
|
|
111
|
+
* 适用于简单的 key=value&key2=value2 场景
|
|
112
|
+
*/
|
|
113
|
+
export function parseQueryFast(req) {
|
|
114
|
+
const queryString = extractQueryString(req.url);
|
|
115
|
+
if (!queryString)
|
|
116
|
+
return {};
|
|
117
|
+
const result = Object.create(null);
|
|
118
|
+
const pairs = queryString.split("&");
|
|
119
|
+
for (const pair of pairs) {
|
|
120
|
+
const eqIndex = pair.indexOf("=");
|
|
121
|
+
if (eqIndex === -1) {
|
|
122
|
+
result[decodeURIComponent(pair)] = "";
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
const key = decodeURIComponent(pair.substring(0, eqIndex));
|
|
126
|
+
const value = decodeURIComponent(pair.substring(eqIndex + 1));
|
|
127
|
+
result[key] = value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
94
131
|
}
|
|
95
132
|
/** 解析请求头,返回对象 */
|
|
96
133
|
export function parseHeaders(req) {
|
|
97
|
-
const headers =
|
|
134
|
+
const headers = Object.create(null);
|
|
98
135
|
req.headers.forEach((value, key) => {
|
|
99
|
-
|
|
100
|
-
headers[key] = value;
|
|
101
|
-
}
|
|
136
|
+
headers[key] = value;
|
|
102
137
|
});
|
|
103
138
|
return headers;
|
|
104
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* 获取单个请求头(避免解析全部)
|
|
142
|
+
*/
|
|
143
|
+
export function getHeader(req, name) {
|
|
144
|
+
return req.headers.get(name);
|
|
145
|
+
}
|
|
105
146
|
/** 使用cookie库解析Cookie,保证可靠性 */
|
|
106
147
|
export function parseCookies(req) {
|
|
107
148
|
const cookieHeader = req.headers.get("cookie");
|
|
@@ -118,9 +159,51 @@ export function parseCookies(req) {
|
|
|
118
159
|
}
|
|
119
160
|
return result;
|
|
120
161
|
}
|
|
121
|
-
catch
|
|
122
|
-
console.error("Cookie解析失败:", error);
|
|
123
|
-
console.error("原始Cookie字符串:", cookieHeader);
|
|
162
|
+
catch {
|
|
124
163
|
return {};
|
|
125
164
|
}
|
|
126
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* 快速解析 Cookie(简化版,不使用外部库)
|
|
168
|
+
* 适用于简单的 cookie 场景
|
|
169
|
+
*/
|
|
170
|
+
export function parseCookiesFast(req) {
|
|
171
|
+
const cookieHeader = req.headers.get("cookie");
|
|
172
|
+
if (!cookieHeader)
|
|
173
|
+
return {};
|
|
174
|
+
const result = Object.create(null);
|
|
175
|
+
const pairs = cookieHeader.split(";");
|
|
176
|
+
for (const pair of pairs) {
|
|
177
|
+
const trimmed = pair.trim();
|
|
178
|
+
const eqIndex = trimmed.indexOf("=");
|
|
179
|
+
if (eqIndex > 0) {
|
|
180
|
+
const key = trimmed.substring(0, eqIndex).trim();
|
|
181
|
+
const value = trimmed.substring(eqIndex + 1).trim();
|
|
182
|
+
// 移除引号
|
|
183
|
+
result[key] = value.startsWith('"') && value.endsWith('"')
|
|
184
|
+
? value.slice(1, -1)
|
|
185
|
+
: value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 获取单个 Cookie 值(避免解析全部)
|
|
192
|
+
*/
|
|
193
|
+
export function getCookie(req, name) {
|
|
194
|
+
const cookieHeader = req.headers.get("cookie");
|
|
195
|
+
if (!cookieHeader)
|
|
196
|
+
return null;
|
|
197
|
+
const prefix = `${name}=`;
|
|
198
|
+
const pairs = cookieHeader.split(";");
|
|
199
|
+
for (const pair of pairs) {
|
|
200
|
+
const trimmed = pair.trim();
|
|
201
|
+
if (trimmed.startsWith(prefix)) {
|
|
202
|
+
const value = trimmed.substring(prefix.length).trim();
|
|
203
|
+
return value.startsWith('"') && value.endsWith('"')
|
|
204
|
+
? value.slice(1, -1)
|
|
205
|
+
: value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
}
|
package/dist/utils/response.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/response.ts
|
|
2
2
|
/** 生成 JSON 响应 */
|
|
3
3
|
export function json(data, status = 200, headers = {}) {
|
|
4
|
+
const body = JSON.stringify(data);
|
|
4
5
|
// 优化:只在有自定义 headers 时才创建 Headers 对象
|
|
5
6
|
if (Object.keys(headers).length === 0) {
|
|
6
|
-
return new Response(
|
|
7
|
+
return new Response(body, {
|
|
7
8
|
status,
|
|
8
9
|
headers: { "Content-Type": "application/json" },
|
|
9
10
|
});
|
|
@@ -13,7 +14,7 @@ export function json(data, status = 200, headers = {}) {
|
|
|
13
14
|
"Content-Type": "application/json",
|
|
14
15
|
...headers,
|
|
15
16
|
});
|
|
16
|
-
return new Response(
|
|
17
|
+
return new Response(body, {
|
|
17
18
|
status,
|
|
18
19
|
headers: h,
|
|
19
20
|
});
|
|
@@ -55,7 +56,7 @@ export function mapResponse(response) {
|
|
|
55
56
|
if (response instanceof Promise) {
|
|
56
57
|
return response.then(mapResponse);
|
|
57
58
|
}
|
|
58
|
-
//
|
|
59
|
+
// 其他情况使用 JSON 序列化
|
|
59
60
|
return new Response(JSON.stringify(response), { headers: JSON_HEADERS });
|
|
60
61
|
}
|
|
61
62
|
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 高性能 Schema 验证器
|
|
3
|
+
*
|
|
4
|
+
* 使用 TypeBox TypeCompiler 进行 JIT 编译
|
|
5
|
+
* 编译后的验证器会被缓存,避免重复编译开销
|
|
6
|
+
*
|
|
7
|
+
* @version 2.0.0 - 添加预编译缓存
|
|
8
|
+
*/
|
|
1
9
|
import { Type } from "@sinclair/typebox";
|
|
2
10
|
import type { Static, TSchema } from "@sinclair/typebox";
|
|
3
11
|
/** 验证错误接口 */
|
|
@@ -21,10 +29,37 @@ export interface ValidationSuccess<T> {
|
|
|
21
29
|
/** 验证结果联合类型 */
|
|
22
30
|
export type ValidationResult<T = unknown> = ValidationSuccess<T> | ValidationFailure;
|
|
23
31
|
/**
|
|
24
|
-
*
|
|
32
|
+
* 预编译 Schema(在启动时调用,避免首次请求的编译开销)
|
|
33
|
+
* @param schemas 要预编译的 Schema 数组
|
|
34
|
+
*/
|
|
35
|
+
export declare function precompileSchemas(schemas: TSchema[]): void;
|
|
36
|
+
/**
|
|
37
|
+
* 使用TypeBox Schema验证数据(带缓存优化)
|
|
25
38
|
* @param schema TypeBox Schema
|
|
26
39
|
* @param data 要验证的数据
|
|
27
40
|
* @returns 验证结果,包含类型安全的数据或详细错误信息
|
|
28
41
|
*/
|
|
29
42
|
export declare function validateSchema<T extends TSchema>(schema: T, data: unknown): ValidationResult<Static<T>>;
|
|
43
|
+
/**
|
|
44
|
+
* 创建类型特化的验证器(最高性能)
|
|
45
|
+
* 适用于频繁验证同一 Schema 的场景
|
|
46
|
+
* @param schema TypeBox Schema
|
|
47
|
+
* @returns 类型安全的验证函数
|
|
48
|
+
*/
|
|
49
|
+
export declare function createValidator<T extends TSchema>(schema: T): (data: unknown) => ValidationResult<Static<T>>;
|
|
50
|
+
/**
|
|
51
|
+
* 快速验证(只返回布尔值,不收集错误)
|
|
52
|
+
* 适用于只需要知道验证结果的场景
|
|
53
|
+
* @param schema TypeBox Schema
|
|
54
|
+
* @param data 要验证的数据
|
|
55
|
+
* @returns 验证是否通过
|
|
56
|
+
*/
|
|
57
|
+
export declare function validateFast<T extends TSchema>(schema: T, data: unknown): data is Static<T>;
|
|
58
|
+
/**
|
|
59
|
+
* 获取缓存统计信息(用于调试)
|
|
60
|
+
*/
|
|
61
|
+
export declare function getValidatorCacheStats(): {
|
|
62
|
+
cacheType: string;
|
|
63
|
+
note: string;
|
|
64
|
+
};
|
|
30
65
|
export { Type, Static, TSchema };
|
|
@@ -1,16 +1,51 @@
|
|
|
1
1
|
// src/utils/validators.ts
|
|
2
|
+
/**
|
|
3
|
+
* 高性能 Schema 验证器
|
|
4
|
+
*
|
|
5
|
+
* 使用 TypeBox TypeCompiler 进行 JIT 编译
|
|
6
|
+
* 编译后的验证器会被缓存,避免重复编译开销
|
|
7
|
+
*
|
|
8
|
+
* @version 2.0.0 - 添加预编译缓存
|
|
9
|
+
*/
|
|
2
10
|
import { Type } from "@sinclair/typebox";
|
|
3
11
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
4
12
|
/**
|
|
5
|
-
*
|
|
13
|
+
* 编译器缓存
|
|
14
|
+
* 使用 WeakMap 避免内存泄漏(Schema 对象被垃圾回收时,缓存也会自动清理)
|
|
15
|
+
*/
|
|
16
|
+
const compilerCache = new WeakMap();
|
|
17
|
+
/**
|
|
18
|
+
* 获取或创建编译后的验证器
|
|
19
|
+
* @param schema TypeBox Schema
|
|
20
|
+
* @returns 编译后的验证器
|
|
21
|
+
*/
|
|
22
|
+
function getCompiledValidator(schema) {
|
|
23
|
+
let compiler = compilerCache.get(schema);
|
|
24
|
+
if (!compiler) {
|
|
25
|
+
compiler = TypeCompiler.Compile(schema);
|
|
26
|
+
compilerCache.set(schema, compiler);
|
|
27
|
+
}
|
|
28
|
+
return compiler;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 预编译 Schema(在启动时调用,避免首次请求的编译开销)
|
|
32
|
+
* @param schemas 要预编译的 Schema 数组
|
|
33
|
+
*/
|
|
34
|
+
export function precompileSchemas(schemas) {
|
|
35
|
+
for (const schema of schemas) {
|
|
36
|
+
getCompiledValidator(schema);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 使用TypeBox Schema验证数据(带缓存优化)
|
|
6
41
|
* @param schema TypeBox Schema
|
|
7
42
|
* @param data 要验证的数据
|
|
8
43
|
* @returns 验证结果,包含类型安全的数据或详细错误信息
|
|
9
44
|
*/
|
|
10
45
|
export function validateSchema(schema, data) {
|
|
11
46
|
try {
|
|
12
|
-
//
|
|
13
|
-
const compiler =
|
|
47
|
+
// 从缓存获取或编译验证器
|
|
48
|
+
const compiler = getCompiledValidator(schema);
|
|
14
49
|
if (compiler.Check(data)) {
|
|
15
50
|
return {
|
|
16
51
|
success: true,
|
|
@@ -50,5 +85,50 @@ export function validateSchema(schema, data) {
|
|
|
50
85
|
};
|
|
51
86
|
}
|
|
52
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* 创建类型特化的验证器(最高性能)
|
|
90
|
+
* 适用于频繁验证同一 Schema 的场景
|
|
91
|
+
* @param schema TypeBox Schema
|
|
92
|
+
* @returns 类型安全的验证函数
|
|
93
|
+
*/
|
|
94
|
+
export function createValidator(schema) {
|
|
95
|
+
const compiler = getCompiledValidator(schema);
|
|
96
|
+
return (data) => {
|
|
97
|
+
if (compiler.Check(data)) {
|
|
98
|
+
return { success: true, data: data };
|
|
99
|
+
}
|
|
100
|
+
const errors = [];
|
|
101
|
+
for (const error of compiler.Errors(data)) {
|
|
102
|
+
errors.push({
|
|
103
|
+
path: error.path,
|
|
104
|
+
message: error.message,
|
|
105
|
+
code: "VALIDATION_FAILED",
|
|
106
|
+
value: error.value,
|
|
107
|
+
schema: error.schema,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return { success: false, errors };
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 快速验证(只返回布尔值,不收集错误)
|
|
115
|
+
* 适用于只需要知道验证结果的场景
|
|
116
|
+
* @param schema TypeBox Schema
|
|
117
|
+
* @param data 要验证的数据
|
|
118
|
+
* @returns 验证是否通过
|
|
119
|
+
*/
|
|
120
|
+
export function validateFast(schema, data) {
|
|
121
|
+
const compiler = getCompiledValidator(schema);
|
|
122
|
+
return compiler.Check(data);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 获取缓存统计信息(用于调试)
|
|
126
|
+
*/
|
|
127
|
+
export function getValidatorCacheStats() {
|
|
128
|
+
return {
|
|
129
|
+
cacheType: "WeakMap",
|
|
130
|
+
note: "WeakMap 不支持 size 属性,缓存会随 Schema 对象自动清理",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
53
133
|
// 导出常用的TypeBox类型,方便使用
|
|
54
134
|
export { Type };
|