vafast 0.3.11 → 0.4.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 +61 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +168 -1
- package/dist/index.js.map +1 -1
- package/dist/monitoring/index.js +151 -1
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/native-monitor.js +151 -1
- package/dist/monitoring/native-monitor.js.map +1 -1
- package/dist/router/index.js +2 -1
- package/dist/router/index.js.map +1 -1
- package/dist/router.js +2 -1
- package/dist/router.js.map +1 -1
- package/dist/server/index.js +144 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/server-factory.js +144 -1
- package/dist/server/server-factory.js.map +1 -1
- package/dist/server/server.d.ts +15 -1
- package/dist/server/server.js +144 -1
- package/dist/server/server.js.map +1 -1
- package/dist/types/types.d.ts +12 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +146 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/route-registry.d.ts +195 -0
- package/dist/utils/route-registry.js +152 -0
- package/dist/utils/route-registry.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -507,6 +507,67 @@ server.compile(); // 预编译所有路由的处理链
|
|
|
507
507
|
|
|
508
508
|
**性能效果:1000 次请求仅需 ~4ms,平均每次 0.004ms**
|
|
509
509
|
|
|
510
|
+
### 路由注册表 (RouteRegistry)
|
|
511
|
+
|
|
512
|
+
Vafast 提供 `RouteRegistry` 用于路由元信息的收集和查询,适用于 API 文档生成、Webhook 事件注册、权限检查等场景:
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
import { Server, createRouteRegistry } from 'vafast';
|
|
516
|
+
import type { Route } from 'vafast';
|
|
517
|
+
|
|
518
|
+
// 定义带扩展字段的路由
|
|
519
|
+
const routes: Route[] = [
|
|
520
|
+
{
|
|
521
|
+
method: 'POST',
|
|
522
|
+
path: '/auth/signIn',
|
|
523
|
+
handler: signInHandler,
|
|
524
|
+
name: '用户登录', // 扩展字段
|
|
525
|
+
description: '用户通过邮箱密码登录', // 扩展字段
|
|
526
|
+
webhook: { eventKey: 'auth.signIn' }, // 自定义扩展
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
method: 'GET',
|
|
530
|
+
path: '/users',
|
|
531
|
+
handler: getUsersHandler,
|
|
532
|
+
permission: 'users.read', // 自定义扩展
|
|
533
|
+
},
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
const server = new Server(routes);
|
|
537
|
+
|
|
538
|
+
// 创建路由注册表
|
|
539
|
+
const registry = createRouteRegistry(server.getRoutesWithMeta());
|
|
540
|
+
|
|
541
|
+
// 查询路由
|
|
542
|
+
const route = registry.get('POST', '/auth/signIn');
|
|
543
|
+
console.log(route?.name); // '用户登录'
|
|
544
|
+
|
|
545
|
+
// 按分类获取
|
|
546
|
+
const authRoutes = registry.getByCategory('auth');
|
|
547
|
+
|
|
548
|
+
// 筛选有特定字段的路由
|
|
549
|
+
const webhookRoutes = registry.filter('webhook');
|
|
550
|
+
const permissionRoutes = registry.filter('permission');
|
|
551
|
+
|
|
552
|
+
// 获取所有分类
|
|
553
|
+
const categories = registry.getCategories(); // ['auth', 'users']
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**完整 API:**
|
|
557
|
+
|
|
558
|
+
| 方法 | 说明 |
|
|
559
|
+
|------|------|
|
|
560
|
+
| `getAll()` | 获取所有路由元信息 |
|
|
561
|
+
| `get(method, path)` | 按 method+path 查询 |
|
|
562
|
+
| `has(method, path)` | 检查路由是否存在 |
|
|
563
|
+
| `getByCategory(category)` | 按分类获取路由 |
|
|
564
|
+
| `getCategories()` | 获取所有分类 |
|
|
565
|
+
| `filter(field)` | 筛选有特定字段的路由 |
|
|
566
|
+
| `filterBy(predicate)` | 自定义条件筛选 |
|
|
567
|
+
| `forEach(callback)` | 遍历所有路由 |
|
|
568
|
+
| `map(callback)` | 映射所有路由 |
|
|
569
|
+
| `size` | 路由数量 |
|
|
570
|
+
|
|
510
571
|
## 🔧 运行时支持
|
|
511
572
|
|
|
512
573
|
### Bun
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export { DependencyManager } from './utils/dependency-manager.js';
|
|
|
15
15
|
export { SchemaConfig, ValidationError, ValidationResult, createValidator, getValidatorCacheStats, precompileSchemas, validateAllSchemas, validateFast, validateSchema, validateSchemaOrThrow } from './utils/validators/validators.js';
|
|
16
16
|
export { Patterns, hasFormat, registerFormat, registerFormats } from './utils/formats.js';
|
|
17
17
|
export { SSEEvent, SSEHandler, SSEMarker, createSSEHandler } from './utils/sse.js';
|
|
18
|
+
export { RouteMeta, RouteRegistry, createRouteRegistry, filterRoutes, getAllRoutes, getRoute, getRouteRegistry } from './utils/route-registry.js';
|
|
18
19
|
export { flattenNestedRoutes, normalizePath } from './router.js';
|
|
19
20
|
export { requireAuth } from './middleware/authMiddleware.js';
|
|
20
21
|
export { rateLimit } from './middleware/rateLimit.js';
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,9 @@ function flattenNestedRoutes(routes) {
|
|
|
8
8
|
...route2.middleware || []
|
|
9
9
|
];
|
|
10
10
|
if ("method" in route2 && "handler" in route2) {
|
|
11
|
+
const leafRoute = route2;
|
|
11
12
|
flattened.push({
|
|
12
|
-
...
|
|
13
|
+
...leafRoute,
|
|
13
14
|
fullPath: currentPath,
|
|
14
15
|
middlewareChain: currentMiddleware
|
|
15
16
|
});
|
|
@@ -494,6 +495,149 @@ var RadixRouter = class {
|
|
|
494
495
|
}
|
|
495
496
|
};
|
|
496
497
|
|
|
498
|
+
// src/utils/route-registry.ts
|
|
499
|
+
var RouteRegistry = class {
|
|
500
|
+
/** 所有路由元信息 */
|
|
501
|
+
routes = [];
|
|
502
|
+
/** 路由映射表:METHOD:fullPath -> RouteMeta */
|
|
503
|
+
routeMap = /* @__PURE__ */ new Map();
|
|
504
|
+
/** 分类映射表:category -> RouteMeta[] */
|
|
505
|
+
categoryMap = /* @__PURE__ */ new Map();
|
|
506
|
+
constructor(routes) {
|
|
507
|
+
this.buildRegistry(routes);
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* 构建注册表
|
|
511
|
+
*/
|
|
512
|
+
buildRegistry(routes) {
|
|
513
|
+
for (const route2 of routes) {
|
|
514
|
+
const meta = {
|
|
515
|
+
method: route2.method,
|
|
516
|
+
path: route2.path,
|
|
517
|
+
fullPath: route2.fullPath,
|
|
518
|
+
name: route2.name,
|
|
519
|
+
description: route2.description
|
|
520
|
+
};
|
|
521
|
+
for (const key of Object.keys(route2)) {
|
|
522
|
+
if (!["method", "path", "fullPath", "name", "description", "handler", "middleware", "middlewareChain"].includes(key)) {
|
|
523
|
+
meta[key] = route2[key];
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
this.routes.push(meta);
|
|
527
|
+
this.routeMap.set(`${route2.method}:${route2.fullPath}`, meta);
|
|
528
|
+
const category = this.extractCategory(route2.fullPath);
|
|
529
|
+
if (!this.categoryMap.has(category)) {
|
|
530
|
+
this.categoryMap.set(category, []);
|
|
531
|
+
}
|
|
532
|
+
this.categoryMap.get(category).push(meta);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* 提取分类(第一段路径)
|
|
537
|
+
*/
|
|
538
|
+
extractCategory(path) {
|
|
539
|
+
const segments = path.split("/").filter(Boolean);
|
|
540
|
+
return segments[0] || "root";
|
|
541
|
+
}
|
|
542
|
+
// ============================================
|
|
543
|
+
// 查询接口
|
|
544
|
+
// ============================================
|
|
545
|
+
/**
|
|
546
|
+
* 获取所有路由元信息
|
|
547
|
+
*/
|
|
548
|
+
getAll() {
|
|
549
|
+
return [...this.routes];
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* 按 method + path 查询路由
|
|
553
|
+
*/
|
|
554
|
+
get(method, path) {
|
|
555
|
+
return this.routeMap.get(`${method}:${path}`);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* 检查路由是否存在
|
|
559
|
+
*/
|
|
560
|
+
has(method, path) {
|
|
561
|
+
return this.routeMap.has(`${method}:${path}`);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* 按分类获取路由
|
|
565
|
+
*/
|
|
566
|
+
getByCategory(category) {
|
|
567
|
+
return this.categoryMap.get(category) || [];
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* 获取所有分类
|
|
571
|
+
*/
|
|
572
|
+
getCategories() {
|
|
573
|
+
return Array.from(this.categoryMap.keys()).sort();
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* 筛选有特定字段的路由
|
|
577
|
+
*
|
|
578
|
+
* @example
|
|
579
|
+
* ```typescript
|
|
580
|
+
* // 获取所有配置了 webhook 的路由
|
|
581
|
+
* const webhookRoutes = registry.filter('webhook')
|
|
582
|
+
* ```
|
|
583
|
+
*/
|
|
584
|
+
filter(field) {
|
|
585
|
+
return this.routes.filter((r) => field in r && r[field] !== void 0);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* 按条件筛选路由
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* // 获取所有 POST 请求
|
|
593
|
+
* const postRoutes = registry.filterBy(r => r.method === 'POST')
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
596
|
+
filterBy(predicate) {
|
|
597
|
+
return this.routes.filter(predicate);
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* 获取路由数量
|
|
601
|
+
*/
|
|
602
|
+
get size() {
|
|
603
|
+
return this.routes.length;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* 遍历所有路由
|
|
607
|
+
*/
|
|
608
|
+
forEach(callback) {
|
|
609
|
+
this.routes.forEach(callback);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* 映射所有路由
|
|
613
|
+
*/
|
|
614
|
+
map(callback) {
|
|
615
|
+
return this.routes.map(callback);
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
function createRouteRegistry(routes) {
|
|
619
|
+
return new RouteRegistry(routes);
|
|
620
|
+
}
|
|
621
|
+
var globalRegistry = null;
|
|
622
|
+
function setGlobalRegistry(registry) {
|
|
623
|
+
globalRegistry = registry;
|
|
624
|
+
}
|
|
625
|
+
function getRouteRegistry() {
|
|
626
|
+
if (!globalRegistry) {
|
|
627
|
+
throw new Error("RouteRegistry not initialized. Make sure Server is created first.");
|
|
628
|
+
}
|
|
629
|
+
return globalRegistry;
|
|
630
|
+
}
|
|
631
|
+
function getRoute(method, path) {
|
|
632
|
+
return getRouteRegistry().get(method, path);
|
|
633
|
+
}
|
|
634
|
+
function getAllRoutes() {
|
|
635
|
+
return getRouteRegistry().getAll();
|
|
636
|
+
}
|
|
637
|
+
function filterRoutes(field) {
|
|
638
|
+
return getRouteRegistry().filter(field);
|
|
639
|
+
}
|
|
640
|
+
|
|
497
641
|
// src/server/server.ts
|
|
498
642
|
var Server = class extends BaseServer {
|
|
499
643
|
router;
|
|
@@ -539,6 +683,7 @@ var Server = class extends BaseServer {
|
|
|
539
683
|
if (this.globalMiddleware.length === 0 && !this.isCompiled) {
|
|
540
684
|
this.compile();
|
|
541
685
|
}
|
|
686
|
+
setGlobalRegistry(new RouteRegistry(this.routes));
|
|
542
687
|
}
|
|
543
688
|
/** 快速提取 pathname */
|
|
544
689
|
extractPathname(url) {
|
|
@@ -628,6 +773,22 @@ var Server = class extends BaseServer {
|
|
|
628
773
|
getRoutes() {
|
|
629
774
|
return this.router.getRoutes();
|
|
630
775
|
}
|
|
776
|
+
/**
|
|
777
|
+
* 获取完整的路由元信息(不含 handler 和 middleware)
|
|
778
|
+
*
|
|
779
|
+
* 用于 API 文档生成、Webhook 事件注册、权限检查等场景
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* ```typescript
|
|
783
|
+
* const routes = server.getRoutesWithMeta()
|
|
784
|
+
* for (const route of routes) {
|
|
785
|
+
* console.log(route.fullPath, route.name, route.description)
|
|
786
|
+
* }
|
|
787
|
+
* ```
|
|
788
|
+
*/
|
|
789
|
+
getRoutesWithMeta() {
|
|
790
|
+
return this.routes;
|
|
791
|
+
}
|
|
631
792
|
};
|
|
632
793
|
|
|
633
794
|
// src/middleware/component-router.ts
|
|
@@ -2299,6 +2460,7 @@ export {
|
|
|
2299
2460
|
FormatRegistry2 as FormatRegistry,
|
|
2300
2461
|
HtmlRenderer,
|
|
2301
2462
|
Patterns,
|
|
2463
|
+
RouteRegistry,
|
|
2302
2464
|
Server,
|
|
2303
2465
|
ServerFactory,
|
|
2304
2466
|
TokenError,
|
|
@@ -2315,6 +2477,7 @@ export {
|
|
|
2315
2477
|
createPermissionAuth,
|
|
2316
2478
|
createRequestValidator,
|
|
2317
2479
|
createRoleAuth,
|
|
2480
|
+
createRouteRegistry,
|
|
2318
2481
|
createSSEHandler,
|
|
2319
2482
|
createTokenPair,
|
|
2320
2483
|
createTypedRoute,
|
|
@@ -2322,12 +2485,16 @@ export {
|
|
|
2322
2485
|
defineRoutes,
|
|
2323
2486
|
del,
|
|
2324
2487
|
empty,
|
|
2488
|
+
filterRoutes,
|
|
2325
2489
|
flattenNestedRoutes,
|
|
2326
2490
|
generateToken,
|
|
2327
2491
|
get,
|
|
2492
|
+
getAllRoutes,
|
|
2328
2493
|
getCookie,
|
|
2329
2494
|
getHeader,
|
|
2330
2495
|
getLocals,
|
|
2496
|
+
getRoute,
|
|
2497
|
+
getRouteRegistry,
|
|
2331
2498
|
getTokenTimeRemaining,
|
|
2332
2499
|
getValidatorCacheStats,
|
|
2333
2500
|
goAwait,
|