vafast 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +437 -143
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/node-server/index.d.ts +22 -0
- package/dist/node-server/index.js +21 -0
- package/dist/node-server/request.d.ts +11 -0
- package/dist/node-server/request.js +157 -0
- package/dist/node-server/response.d.ts +15 -0
- package/dist/node-server/response.js +98 -0
- package/dist/node-server/serve.d.ts +52 -0
- package/dist/node-server/serve.js +88 -0
- package/dist/router/radix-tree.d.ts +12 -0
- package/dist/router/radix-tree.js +37 -1
- package/dist/serve.d.ts +12 -0
- package/dist/serve.js +11 -0
- package/dist/server/server.d.ts +9 -0
- package/dist/server/server.js +26 -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 +93 -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 +9 -2
package/README.md
CHANGED
|
@@ -1,219 +1,513 @@
|
|
|
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/)
|
|
6
|
+
|
|
7
|
+
**超高性能的 TypeScript Web 框架,类型安全、轻量、快速。**
|
|
8
|
+
|
|
9
|
+
> Vafast 不只是框架,更是一种 **结构、清晰、可控** 的开发哲学。
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { Server, createHandler } from 'vafast';
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
const server = new Server([
|
|
15
|
+
{ method: 'GET', path: '/', handler: createHandler(() => 'Hello Vafast!') }
|
|
16
|
+
]);
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
export default { port: 3000, fetch: server.fetch };
|
|
19
|
+
```
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
```bash
|
|
22
|
+
# 启动服务器
|
|
23
|
+
bun run index.ts # 或
|
|
24
|
+
npx tsx index.ts
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## ⚡ 性能
|
|
28
|
+
|
|
29
|
+
| 框架 | RPS | 相对性能 |
|
|
30
|
+
|------|-----|----------|
|
|
31
|
+
| Elysia | ~118K | 100% |
|
|
32
|
+
| **Vafast** | **~101K** | **86%** |
|
|
33
|
+
| Express | ~56K | 48% |
|
|
34
|
+
| Hono | ~56K | 47% |
|
|
35
|
+
|
|
36
|
+
> **Vafast 比 Express/Hono 快约 1.8x!**
|
|
37
|
+
> 测试环境:Bun 1.2.20, macOS, wrk 基准测试 (4线程, 100连接, 30s)
|
|
19
38
|
|
|
20
39
|
## 📦 安装
|
|
21
40
|
|
|
22
41
|
```bash
|
|
23
|
-
#
|
|
42
|
+
# npm
|
|
43
|
+
npm install vafast
|
|
44
|
+
|
|
45
|
+
# bun
|
|
24
46
|
bun add vafast
|
|
47
|
+
```
|
|
25
48
|
|
|
26
|
-
|
|
27
|
-
npm install vafast
|
|
49
|
+
## 💡 设计哲学
|
|
28
50
|
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
### 结构即真相 — 无装饰器,无链式魔法
|
|
52
|
+
|
|
53
|
+
**Elysia 完整示例:**
|
|
54
|
+
```typescript
|
|
55
|
+
import { Elysia } from 'elysia';
|
|
56
|
+
|
|
57
|
+
const app = new Elysia()
|
|
58
|
+
.get('/users', () => 'list users')
|
|
59
|
+
.post('/users', ({ body }) => body)
|
|
60
|
+
.get('/users/:id', ({ params }) => `User ${params.id}`)
|
|
61
|
+
.use(somePlugin); // 插件作用域?要看文档
|
|
62
|
+
|
|
63
|
+
export default app;
|
|
31
64
|
```
|
|
32
65
|
|
|
33
|
-
|
|
66
|
+
**Hono 完整示例:**
|
|
67
|
+
```typescript
|
|
68
|
+
import { Hono } from 'hono';
|
|
69
|
+
|
|
70
|
+
const app = new Hono();
|
|
71
|
+
app.get('/users', (c) => c.text('list users'));
|
|
72
|
+
app.post('/users', async (c) => c.json(await c.req.json()));
|
|
73
|
+
app.get('/users/:id', (c) => c.text(`User ${c.req.param('id')}`));
|
|
34
74
|
|
|
35
|
-
|
|
75
|
+
export default app;
|
|
76
|
+
```
|
|
36
77
|
|
|
78
|
+
**Vafast 完整示例:**
|
|
37
79
|
```typescript
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
80
|
+
import { Server, createHandler } from 'vafast';
|
|
81
|
+
import type { Route } from 'vafast';
|
|
40
82
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
83
|
+
const routes: Route[] = [
|
|
84
|
+
{ method: 'GET', path: '/users', handler: createHandler(() => 'list users') },
|
|
85
|
+
{ method: 'POST', path: '/users', handler: createHandler(({ body }) => body) },
|
|
86
|
+
{ method: 'GET', path: '/users/:id', handler: createHandler(({ params }) => `User ${params.id}`) },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const server = new Server(routes);
|
|
90
|
+
export default { fetch: server.fetch };
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**对比:Vafast 的路由是一个数组,一眼看清所有 API 端点。**
|
|
94
|
+
|
|
95
|
+
### 错误即数据 — 不是混乱,是契约
|
|
96
|
+
|
|
97
|
+
**Hono 完整示例:**
|
|
98
|
+
```typescript
|
|
99
|
+
import { Hono } from 'hono';
|
|
100
|
+
import { HTTPException } from 'hono/http-exception';
|
|
101
|
+
|
|
102
|
+
const app = new Hono();
|
|
47
103
|
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
handler: async (req) => {
|
|
54
|
-
const { name, email, age } = req.body;
|
|
55
|
-
return { success: true, user: { name, email, age } };
|
|
104
|
+
app.get('/user', (c) => {
|
|
105
|
+
const name = c.req.query('name');
|
|
106
|
+
if (!name) {
|
|
107
|
+
throw new HTTPException(400, { message: 'Missing name' });
|
|
108
|
+
// 响应格式自己定,没有标准
|
|
56
109
|
}
|
|
110
|
+
return c.text(`Hello, ${name}`);
|
|
57
111
|
});
|
|
58
112
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
server.addRoute(userRoute);
|
|
113
|
+
export default app;
|
|
114
|
+
```
|
|
62
115
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
116
|
+
**Vafast 完整示例:**
|
|
117
|
+
```typescript
|
|
118
|
+
import { Server, VafastError, createHandler } from 'vafast';
|
|
119
|
+
import type { Route } from 'vafast';
|
|
120
|
+
|
|
121
|
+
const routes: Route[] = [
|
|
122
|
+
{
|
|
123
|
+
method: 'GET',
|
|
124
|
+
path: '/user',
|
|
125
|
+
handler: createHandler((ctx) => {
|
|
126
|
+
const name = ctx.query.name;
|
|
127
|
+
if (!name) {
|
|
128
|
+
throw new VafastError('Missing name', {
|
|
129
|
+
status: 400,
|
|
130
|
+
type: 'bad_request',
|
|
131
|
+
expose: true, // 控制是否暴露给客户端
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return `Hello, ${name}`;
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const server = new Server(routes);
|
|
140
|
+
export default { fetch: server.fetch };
|
|
141
|
+
// 错误响应: { type: 'bad_request', message: 'Missing name' }
|
|
66
142
|
```
|
|
67
143
|
|
|
68
|
-
|
|
144
|
+
**对比:VafastError 有统一的 `type` + `status` + `expose` 契约。**
|
|
145
|
+
|
|
146
|
+
### 组合优于约定 — 显式优于隐式
|
|
69
147
|
|
|
148
|
+
**Hono 完整示例:**
|
|
70
149
|
```typescript
|
|
71
|
-
import {
|
|
150
|
+
import { Hono } from 'hono';
|
|
151
|
+
import { cors } from 'hono/cors';
|
|
152
|
+
|
|
153
|
+
const app = new Hono();
|
|
154
|
+
|
|
155
|
+
// 中间件作用域通过路径匹配,容易出错
|
|
156
|
+
app.use('/*', cors()); // 全局
|
|
157
|
+
app.use('/api/*', authMiddleware); // /api/* 但 /api 本身呢?
|
|
72
158
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
159
|
+
app.get('/public', (c) => c.text('public'));
|
|
160
|
+
app.get('/api/users', (c) => c.text('users'));
|
|
161
|
+
|
|
162
|
+
export default app;
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Vafast 完整示例:**
|
|
166
|
+
```typescript
|
|
167
|
+
import { Server, createHandler } from 'vafast';
|
|
168
|
+
import type { Route, Middleware } from 'vafast';
|
|
169
|
+
|
|
170
|
+
const authMiddleware: Middleware = async (req, next) => {
|
|
171
|
+
const token = req.headers.get('Authorization');
|
|
172
|
+
if (!token) return new Response('Unauthorized', { status: 401 });
|
|
173
|
+
return next();
|
|
80
174
|
};
|
|
81
175
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
176
|
+
const routes: Route[] = [
|
|
177
|
+
// 无中间件
|
|
178
|
+
{ method: 'GET', path: '/public', handler: createHandler(() => 'public') },
|
|
179
|
+
// 仅 auth
|
|
180
|
+
{ method: 'GET', path: '/api/users', middleware: [authMiddleware], handler: createHandler(() => 'users') },
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
const server = new Server(routes);
|
|
184
|
+
export default { fetch: server.fetch };
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**对比:Vafast 的中间件直接声明在路由上,一目了然。**
|
|
188
|
+
|
|
189
|
+
### 类型注入 — 跨文件不丢失
|
|
190
|
+
|
|
191
|
+
**Hono 跨文件类型问题:**
|
|
192
|
+
```typescript
|
|
193
|
+
// -------- file: app.ts --------
|
|
194
|
+
import { Hono } from 'hono';
|
|
195
|
+
|
|
196
|
+
type Env = { Variables: { user: { id: string; role: string } } };
|
|
197
|
+
const app = new Hono<Env>();
|
|
198
|
+
|
|
199
|
+
// -------- file: routes.ts --------
|
|
200
|
+
import { Hono } from 'hono';
|
|
201
|
+
|
|
202
|
+
// 类型参数丢失!
|
|
203
|
+
export function setupRoutes(app: Hono) {
|
|
204
|
+
app.get('/profile', (c) => {
|
|
205
|
+
const user = c.get('user'); // ❌ 类型是 unknown
|
|
206
|
+
return c.json(user);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Vafast 跨文件类型完整:**
|
|
212
|
+
```typescript
|
|
213
|
+
// -------- file: types.ts --------
|
|
214
|
+
export type AuthContext = { user: { id: string; role: string } };
|
|
215
|
+
|
|
216
|
+
// -------- file: middleware/auth.ts --------
|
|
217
|
+
import type { Middleware } from 'vafast';
|
|
218
|
+
|
|
219
|
+
export const authMiddleware: Middleware = async (req, next) => {
|
|
220
|
+
const user = await verifyToken(req.headers.get('Authorization'));
|
|
221
|
+
(req as any).__locals = { user };
|
|
222
|
+
return next();
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// -------- file: handlers/profile.ts --------
|
|
226
|
+
import { createHandlerWithExtra } from 'vafast';
|
|
227
|
+
import type { AuthContext } from '../types';
|
|
228
|
+
|
|
229
|
+
// 类型在 Handler 级别定义,任意文件都能用!
|
|
230
|
+
export const getProfile = createHandlerWithExtra<AuthContext>((ctx) => {
|
|
231
|
+
const user = ctx.user; // ✅ 类型完整: { id: string; role: string }
|
|
232
|
+
return { profile: user, isAdmin: user.role === 'admin' };
|
|
89
233
|
});
|
|
234
|
+
|
|
235
|
+
// -------- file: routes.ts --------
|
|
236
|
+
import { Server } from 'vafast';
|
|
237
|
+
import type { Route } from 'vafast';
|
|
238
|
+
import { authMiddleware } from './middleware/auth';
|
|
239
|
+
import { getProfile } from './handlers/profile';
|
|
240
|
+
|
|
241
|
+
const routes: Route[] = [
|
|
242
|
+
{ method: 'GET', path: '/profile', middleware: [authMiddleware], handler: getProfile },
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
const server = new Server(routes);
|
|
246
|
+
export default { fetch: server.fetch };
|
|
90
247
|
```
|
|
91
248
|
|
|
92
|
-
|
|
249
|
+
**对比:Vafast 的类型跟着 Handler 走,而不是跟着 App 实例走。**
|
|
250
|
+
|
|
251
|
+
### 边缘原生 — 一行代码,任意运行时
|
|
93
252
|
|
|
94
|
-
|
|
253
|
+
**Bun 环境完整示例:**
|
|
254
|
+
```typescript
|
|
255
|
+
import { Server, createHandler } from 'vafast';
|
|
95
256
|
|
|
96
|
-
|
|
257
|
+
const server = new Server([
|
|
258
|
+
{ method: 'GET', path: '/', handler: createHandler(() => 'Hello Bun!') }
|
|
259
|
+
]);
|
|
97
260
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- **类型特化**: 针对特定数据类型的优化验证器
|
|
101
|
-
- **批量验证**: 支持数组数据的批量验证
|
|
261
|
+
export default { port: 3000, fetch: server.fetch };
|
|
262
|
+
```
|
|
102
263
|
|
|
264
|
+
**Cloudflare Workers 完整示例:**
|
|
103
265
|
```typescript
|
|
104
|
-
import {
|
|
105
|
-
validateAllSchemasExpanded,
|
|
106
|
-
createTypedValidator,
|
|
107
|
-
validateBatch
|
|
108
|
-
} from 'vafast/utils/validators/validators-ultra';
|
|
266
|
+
import { Server, createHandler } from 'vafast';
|
|
109
267
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
268
|
+
const server = new Server([
|
|
269
|
+
{ method: 'GET', path: '/', handler: createHandler(() => 'Hello Workers!') }
|
|
270
|
+
]);
|
|
113
271
|
|
|
114
|
-
|
|
115
|
-
const validatedUsers = validateBatch(userSchema, userArray);
|
|
272
|
+
export default { fetch: server.fetch };
|
|
116
273
|
```
|
|
117
274
|
|
|
118
|
-
|
|
275
|
+
**Node.js 完整示例:**
|
|
276
|
+
```typescript
|
|
277
|
+
import { Server, createHandler } from 'vafast';
|
|
278
|
+
import { serve } from '@vafast/node-server';
|
|
119
279
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- [🔧 高级功能](./docs/advanced/)
|
|
124
|
-
- [📖 API参考](./docs/api/)
|
|
125
|
-
- [🧪 示例代码](./examples/)
|
|
280
|
+
const server = new Server([
|
|
281
|
+
{ method: 'GET', path: '/', handler: createHandler(() => 'Hello Node!') }
|
|
282
|
+
]);
|
|
126
283
|
|
|
127
|
-
|
|
284
|
+
serve({ fetch: server.fetch, port: 3000 }, () => {
|
|
285
|
+
console.log('Server running on http://localhost:3000');
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**对比:同一套代码,只需改导出方式即可切换运行时。**
|
|
290
|
+
|
|
291
|
+
### 零样板 — 一个文件,即刻运行
|
|
128
292
|
|
|
129
293
|
```bash
|
|
130
|
-
#
|
|
131
|
-
|
|
294
|
+
# ❌ NestJS - 需要脚手架和大量文件
|
|
295
|
+
nest new my-app # 生成 20+ 文件
|
|
132
296
|
|
|
133
|
-
#
|
|
134
|
-
|
|
297
|
+
# ❌ Express - 需要配置和样板代码
|
|
298
|
+
npm init && npm install express && mkdir routes controllers...
|
|
299
|
+
|
|
300
|
+
# ✅ Vafast - 一个文件搞定
|
|
301
|
+
echo "import { Server } from 'vafast';
|
|
302
|
+
const server = new Server([{ method: 'GET', path: '/', handler: () => 'Hi' }]);
|
|
303
|
+
export default { fetch: server.fetch };" > index.ts && bun index.ts
|
|
304
|
+
```
|
|
135
305
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
306
|
+
### 与 Elysia/Hono 详细对比
|
|
307
|
+
|
|
308
|
+
| 特性 | Elysia | Hono | **Vafast** |
|
|
309
|
+
|------|--------|------|------------|
|
|
310
|
+
| **路由风格** | 链式 builder | 链式 builder | **声明式数组** |
|
|
311
|
+
| **路由一览性** | 分散在链中 | 分散在链中 | **一个数组看全部** |
|
|
312
|
+
| **中间件绑定** | .use() 隐式 | .use() 路径匹配 | **显式声明在路由上** |
|
|
313
|
+
| **错误类型** | error() 函数 | HTTPException | **VafastError 契约** |
|
|
314
|
+
| **类型推断** | 优秀 | 良好 | **优秀 (TypeBox)** |
|
|
315
|
+
| **跨文件类型** | ⚠️ 链断裂丢失 | ❌ 实例绑定丢失 | **✅ Handler 级独立** |
|
|
316
|
+
| **类型定义位置** | 链式调用上下文 | App 实例泛型 | **Handler 泛型参数** |
|
|
317
|
+
| **性能 (RPS)** | ~118K | ~56K | **~101K** |
|
|
318
|
+
| **学习曲线** | 中等 | 简单 | **简单** |
|
|
319
|
+
| **API 风格** | 函数式链 | Express-like | **配置式** |
|
|
320
|
+
|
|
321
|
+
### 为什么选择 Vafast?
|
|
322
|
+
|
|
323
|
+
| 如果你... | 选择 |
|
|
324
|
+
|----------|------|
|
|
325
|
+
| 追求极致性能 | Elysia (~118K) > **Vafast (~101K)** > Hono (~56K) |
|
|
326
|
+
| 喜欢链式 API | Elysia 或 Hono |
|
|
327
|
+
| **需要路由一览表** | **✅ Vafast** |
|
|
328
|
+
| **需要精确中间件控制** | **✅ Vafast** |
|
|
329
|
+
| **需要结构化错误** | **✅ Vafast** |
|
|
330
|
+
| **大型项目多文件拆分** | **✅ Vafast (类型不丢失)** |
|
|
331
|
+
| **团队协作类型安全** | **✅ Vafast** |
|
|
332
|
+
| 从 Express 迁移 | Hono (API 相似) |
|
|
333
|
+
|
|
334
|
+
## 🎯 核心功能
|
|
335
|
+
|
|
336
|
+
- ⚡ **JIT 编译验证器** - Schema 验证器编译缓存,避免重复编译
|
|
337
|
+
- 🔗 **中间件链预编译** - 路由注册时预编译处理链,运行时零开销
|
|
338
|
+
- 🎯 **快速请求解析** - 优化的 Query/Cookie 解析,比标准方法快 2x
|
|
339
|
+
- 🔒 **端到端类型安全** - 完整的 TypeScript 类型推断
|
|
340
|
+
- 🧩 **灵活中间件系统** - 可组合的中间件架构
|
|
341
|
+
- 📦 **零配置** - 开箱即用,无需复杂配置
|
|
342
|
+
|
|
343
|
+
### 类型安全的路由
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import { Server, defineRoutes, createHandler, Type } from 'vafast';
|
|
347
|
+
|
|
348
|
+
const routes = defineRoutes([
|
|
349
|
+
{
|
|
350
|
+
method: 'POST',
|
|
351
|
+
path: '/users',
|
|
352
|
+
handler: createHandler(
|
|
353
|
+
{ body: Type.Object({ name: Type.String(), email: Type.String() }) },
|
|
354
|
+
({ body }) => {
|
|
355
|
+
// body.name 和 body.email 自动类型推断
|
|
356
|
+
return { success: true, user: body };
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
]);
|
|
140
361
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
bun benchmark:validators # 验证器测试
|
|
144
|
-
bun benchmark:ultra # 超性能测试
|
|
145
|
-
bun benchmark:ultimate # 终极性能测试
|
|
146
|
-
bun benchmark:comprehensive # 综合测试
|
|
362
|
+
const server = new Server(routes);
|
|
363
|
+
export default { port: 3000, fetch: server.fetch };
|
|
147
364
|
```
|
|
148
365
|
|
|
149
|
-
|
|
366
|
+
### 路径参数
|
|
150
367
|
|
|
151
|
-
|
|
368
|
+
```typescript
|
|
369
|
+
{
|
|
370
|
+
method: 'GET',
|
|
371
|
+
path: '/users/:id',
|
|
372
|
+
handler: createHandler(
|
|
373
|
+
{ params: Type.Object({ id: Type.String() }) },
|
|
374
|
+
({ params }) => ({ userId: params.id })
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
```
|
|
152
378
|
|
|
153
|
-
|
|
154
|
-
|--------|--------|----------|---------|
|
|
155
|
-
| **Ultra标准版** | 24.28ms | 基准 | 稳定 |
|
|
156
|
-
| **Ultra展开版** | 23.63ms | **+2.7%** | 稳定 |
|
|
379
|
+
### 中间件
|
|
157
380
|
|
|
158
|
-
|
|
381
|
+
```typescript
|
|
382
|
+
const authMiddleware = async (req, next) => {
|
|
383
|
+
const token = req.headers.get('Authorization');
|
|
384
|
+
if (!token) return new Response('Unauthorized', { status: 401 });
|
|
385
|
+
return next(req);
|
|
386
|
+
};
|
|
159
387
|
|
|
160
|
-
|
|
388
|
+
const routes = defineRoutes([
|
|
389
|
+
{
|
|
390
|
+
method: 'GET',
|
|
391
|
+
path: '/protected',
|
|
392
|
+
middleware: [authMiddleware],
|
|
393
|
+
handler: createHandler(() => ({ secret: 'data' }))
|
|
394
|
+
}
|
|
395
|
+
]);
|
|
396
|
+
```
|
|
161
397
|
|
|
162
|
-
###
|
|
163
|
-
1. [Fork](https://github.com/vafast/vafast/fork) 项目
|
|
164
|
-
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
|
|
165
|
-
3. 提交更改 (`git commit -m 'feat: 添加新功能'`)
|
|
166
|
-
4. 推送到分支 (`git push origin feature/amazing-feature`)
|
|
167
|
-
5. 创建 [Pull Request](https://github.com/vafast/vafast/compare)
|
|
398
|
+
### 嵌套路由
|
|
168
399
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
400
|
+
```typescript
|
|
401
|
+
const routes = defineRoutes([
|
|
402
|
+
{
|
|
403
|
+
path: '/api',
|
|
404
|
+
middleware: [apiMiddleware],
|
|
405
|
+
children: [
|
|
406
|
+
{ method: 'GET', path: '/users', handler: getUsers },
|
|
407
|
+
{ method: 'POST', path: '/users', handler: createUser },
|
|
408
|
+
{
|
|
409
|
+
path: '/users/:id',
|
|
410
|
+
children: [
|
|
411
|
+
{ method: 'GET', path: '/', handler: getUser },
|
|
412
|
+
{ method: 'PUT', path: '/', handler: updateUser },
|
|
413
|
+
{ method: 'DELETE', path: '/', handler: deleteUser },
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
]);
|
|
419
|
+
```
|
|
175
420
|
|
|
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) - 查看最新版本
|
|
421
|
+
### JIT 编译验证器
|
|
180
422
|
|
|
181
|
-
|
|
423
|
+
Vafast 内置验证器 JIT 编译,自动缓存编译后的验证器:
|
|
182
424
|
|
|
183
|
-
|
|
425
|
+
```typescript
|
|
426
|
+
import { createValidator, validateFast, precompileSchemas } from 'vafast';
|
|
427
|
+
import { Type } from '@sinclair/typebox';
|
|
184
428
|
|
|
185
|
-
|
|
429
|
+
const UserSchema = Type.Object({
|
|
430
|
+
name: Type.String(),
|
|
431
|
+
age: Type.Number()
|
|
432
|
+
});
|
|
186
433
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
4. **⚡ 零配置**: 开箱即用的最佳实践配置
|
|
191
|
-
5. **🔄 活跃维护**: 持续的性能优化和功能更新
|
|
434
|
+
// 方式一:自动缓存(推荐)
|
|
435
|
+
// 首次调用编译,后续调用使用缓存
|
|
436
|
+
const result = validateFast(UserSchema, data);
|
|
192
437
|
|
|
193
|
-
|
|
438
|
+
// 方式二:预编译验证器(最高性能)
|
|
439
|
+
const validateUser = createValidator(UserSchema);
|
|
440
|
+
const isValid = validateUser(data);
|
|
194
441
|
|
|
195
|
-
|
|
442
|
+
// 启动时预编译(避免首次请求开销)
|
|
443
|
+
precompileSchemas([UserSchema, PostSchema, CommentSchema]);
|
|
444
|
+
```
|
|
196
445
|
|
|
197
|
-
|
|
198
|
-
|--------|--------|----------|---------|
|
|
199
|
-
| **Ultra标准版** | 24.28ms | 基准 | 稳定 |
|
|
200
|
-
| **Ultra展开版** | 23.63ms | **+2.7%** | 稳定 |
|
|
446
|
+
**性能效果:首次编译后,10000 次验证仅需 ~5ms**
|
|
201
447
|
|
|
202
|
-
|
|
448
|
+
### 中间件预编译
|
|
203
449
|
|
|
204
|
-
|
|
205
|
-
- **🔒 类型安全**: 完整的TypeScript支持
|
|
206
|
-
- **🧩 中间件系统**: 灵活可扩展的中间件架构
|
|
207
|
-
- **✅ 内置验证**: 超优化的Schema验证器
|
|
208
|
-
- **🎯 零依赖**: 最小化外部依赖
|
|
209
|
-
- **🚀 Bun原生**: 专为Bun运行时优化
|
|
450
|
+
Vafast 自动在路由注册时预编译中间件链,消除运行时组合开销:
|
|
210
451
|
|
|
211
|
-
|
|
452
|
+
```typescript
|
|
453
|
+
const server = new Server(routes);
|
|
454
|
+
|
|
455
|
+
// 添加全局中间件后,手动触发预编译
|
|
456
|
+
server.use(authMiddleware);
|
|
457
|
+
server.use(logMiddleware);
|
|
458
|
+
server.compile(); // 预编译所有路由的处理链
|
|
459
|
+
|
|
460
|
+
// 预编译后,每次请求直接执行编译好的处理链,无需运行时组合
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**性能效果:1000 次请求仅需 ~4ms,平均每次 0.004ms**
|
|
464
|
+
|
|
465
|
+
## 🔧 运行时支持
|
|
466
|
+
|
|
467
|
+
### Bun
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
export default { port: 3000, fetch: server.fetch };
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Node.js
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import { serve } from '@vafast/node-server';
|
|
477
|
+
serve({ fetch: server.fetch, port: 3000 });
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
> 💡 两种运行时使用相同的 API,代码可无缝迁移
|
|
481
|
+
|
|
482
|
+
## 📚 文档
|
|
483
|
+
|
|
484
|
+
### 入门
|
|
485
|
+
- [快速开始](./docs/getting-started/quickstart.md)
|
|
486
|
+
- [示例代码](./examples/)
|
|
487
|
+
|
|
488
|
+
### 架构设计
|
|
489
|
+
- [路由设计与网关架构](./docs/router-design.md) - 声明式路由的设计哲学、AI 时代能力、网关优势
|
|
490
|
+
- [本地工具模式](./docs/local-tools-mode.md) - 声明式路由作为 AI Tools,无需 HTTP 服务
|
|
212
491
|
|
|
213
|
-
|
|
492
|
+
### 参考
|
|
493
|
+
- [服务器优化](./docs/server-optimization.md)
|
|
494
|
+
- [认证系统](./docs/auth.md)
|
|
495
|
+
|
|
496
|
+
## 🤝 贡献
|
|
497
|
+
|
|
498
|
+
欢迎贡献!请查看 [贡献指南](./CONTRIBUTING.md)。
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
git clone https://github.com/vafast/vafast.git
|
|
502
|
+
cd vafast
|
|
503
|
+
npm install # 或 bun install
|
|
504
|
+
npm test # 或 bun test
|
|
505
|
+
```
|
|
214
506
|
|
|
215
507
|
## 📄 许可证
|
|
216
508
|
|
|
217
|
-
|
|
509
|
+
[MIT](./LICENSE)
|
|
218
510
|
|
|
511
|
+
---
|
|
219
512
|
|
|
513
|
+
**Vafast** - 让 Web 开发更快、更安全、更高效!
|
package/dist/index.d.ts
CHANGED
|
@@ -9,4 +9,6 @@ export * from "./auth/token";
|
|
|
9
9
|
export * from "./middleware/auth";
|
|
10
10
|
export * from "./defineRoute";
|
|
11
11
|
export * from "./types/index";
|
|
12
|
+
export { serve } from "./serve";
|
|
13
|
+
export type { ServeOptions, ServeResult, FetchHandler } from "./serve";
|
|
12
14
|
export { Type } from "@sinclair/typebox";
|
package/dist/index.js
CHANGED
|
@@ -9,5 +9,7 @@ export * from "./auth/token";
|
|
|
9
9
|
export * from "./middleware/auth";
|
|
10
10
|
export * from "./defineRoute";
|
|
11
11
|
export * from "./types/index";
|
|
12
|
+
// 统一的 serve 函数(自动适配 Bun/Node.js)
|
|
13
|
+
export { serve } from "./serve";
|
|
12
14
|
// 重新导出 Type 以便用户使用
|
|
13
15
|
export { Type } from "@sinclair/typebox";
|