@kevisual/router 0.0.82 → 0.0.84
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/agent/routes/index.ts +16 -10
- package/agent/routes/route-create.ts +3 -3
- package/dist/app.js +98 -69
- package/dist/opencode.d.ts +89 -86
- package/dist/opencode.js +10 -5
- package/dist/router-browser.d.ts +87 -55
- package/dist/router-browser.js +26 -24
- package/dist/router-define.d.ts +84 -55
- package/dist/router.d.ts +92 -86
- package/dist/router.js +28 -62
- package/dist/ws.d.ts +112 -73
- package/package.json +2 -2
- package/readme.md +78 -63
- package/src/app.ts +7 -50
- package/src/opencode.ts +12 -5
- package/src/result/error.ts +22 -0
- package/src/route.ts +92 -78
- package/src/test/app-type.ts +66 -10
- package/src/test/chat.ts +1 -1
- package/src/test/route-ts.ts +15 -0
package/dist/ws.d.ts
CHANGED
|
@@ -57,6 +57,11 @@ type CustomErrorOptions = {
|
|
|
57
57
|
code?: number;
|
|
58
58
|
message?: string;
|
|
59
59
|
};
|
|
60
|
+
interface throwError {
|
|
61
|
+
throw(code?: number | string, message?: string): void;
|
|
62
|
+
throw(code?: number | string, opts?: CustomErrorOptions): void;
|
|
63
|
+
throw(opts?: CustomErrorOptions): void;
|
|
64
|
+
}
|
|
60
65
|
|
|
61
66
|
declare class MockProcess {
|
|
62
67
|
emitter?: EventEmitter;
|
|
@@ -75,9 +80,20 @@ type RouterContextT = {
|
|
|
75
80
|
code?: number;
|
|
76
81
|
[key: string]: any;
|
|
77
82
|
};
|
|
83
|
+
type BuildRouteContext<M, U> = M extends {
|
|
84
|
+
args?: infer A;
|
|
85
|
+
} ? A extends z.ZodObject<any> ? RouteContext<{
|
|
86
|
+
args?: z.infer<A>;
|
|
87
|
+
}, U> : A extends Record<string, z.ZodTypeAny> ? RouteContext<{
|
|
88
|
+
args?: {
|
|
89
|
+
[K in keyof A]: z.infer<A[K]>;
|
|
90
|
+
};
|
|
91
|
+
}, U> : RouteContext<U> : RouteContext<U>;
|
|
78
92
|
type RouteContext<T = {
|
|
79
93
|
code?: number;
|
|
80
|
-
},
|
|
94
|
+
}, U extends SimpleObject = {}, S = {
|
|
95
|
+
[key: string]: any;
|
|
96
|
+
}> = {
|
|
81
97
|
/**
|
|
82
98
|
* 本地自己调用的时候使用,可以标识为当前自调用,那么 auth 就不许重复的校验
|
|
83
99
|
* 或者不需要登录的,直接调用
|
|
@@ -100,7 +116,14 @@ type RouteContext<T = {
|
|
|
100
116
|
code?: number;
|
|
101
117
|
/** return msg */
|
|
102
118
|
message?: string;
|
|
119
|
+
/**
|
|
120
|
+
* 传递状态
|
|
121
|
+
*/
|
|
103
122
|
state?: S;
|
|
123
|
+
/**
|
|
124
|
+
* 当前routerId
|
|
125
|
+
*/
|
|
126
|
+
currentId?: string;
|
|
104
127
|
/**
|
|
105
128
|
* 当前路径
|
|
106
129
|
*/
|
|
@@ -141,14 +164,12 @@ type RouteContext<T = {
|
|
|
141
164
|
path: string;
|
|
142
165
|
key?: string;
|
|
143
166
|
payload?: any;
|
|
144
|
-
}, ctx?: RouteContext
|
|
145
|
-
[key: string]: any;
|
|
146
|
-
}) => Promise<any>;
|
|
167
|
+
}, ctx?: RouteContext) => Promise<any>;
|
|
147
168
|
index?: number;
|
|
148
|
-
throw?:
|
|
169
|
+
throw?: throwError['throw'];
|
|
149
170
|
/** 是否需要序列化, 使用JSON.stringify和JSON.parse */
|
|
150
171
|
needSerialize?: boolean;
|
|
151
|
-
} & T;
|
|
172
|
+
} & T & U;
|
|
152
173
|
type SimpleObject = Record<string, any>;
|
|
153
174
|
type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
|
|
154
175
|
type RunMessage = {
|
|
@@ -159,7 +180,7 @@ type RunMessage = {
|
|
|
159
180
|
};
|
|
160
181
|
type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
|
|
161
182
|
type RouteMiddleware = {
|
|
162
|
-
path
|
|
183
|
+
path?: string;
|
|
163
184
|
key?: string;
|
|
164
185
|
id?: string;
|
|
165
186
|
} | string;
|
|
@@ -186,9 +207,11 @@ type RouteOpts<U = {}, T = SimpleObject> = {
|
|
|
186
207
|
type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'nextRoute'>;
|
|
187
208
|
declare const pickValue: readonly ["path", "key", "id", "description", "type", "middleware", "metadata"];
|
|
188
209
|
type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
210
|
+
/**
|
|
211
|
+
* @M 是 route的 metadate的类型,默认是 SimpleObject
|
|
212
|
+
* @U 是 RouteContext 里 state的类型
|
|
213
|
+
*/
|
|
214
|
+
declare class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject = SimpleObject> implements throwError {
|
|
192
215
|
/**
|
|
193
216
|
* 一级路径
|
|
194
217
|
*/
|
|
@@ -198,10 +221,10 @@ declare class Route<U = {
|
|
|
198
221
|
*/
|
|
199
222
|
key?: string;
|
|
200
223
|
id?: string;
|
|
201
|
-
run?: Run
|
|
224
|
+
run?: Run<BuildRouteContext<M, U>>;
|
|
202
225
|
nextRoute?: NextRoute;
|
|
203
226
|
description?: string;
|
|
204
|
-
metadata?:
|
|
227
|
+
metadata?: M;
|
|
205
228
|
middleware?: RouteMiddleware[];
|
|
206
229
|
type?: string;
|
|
207
230
|
/**
|
|
@@ -216,19 +239,19 @@ declare class Route<U = {
|
|
|
216
239
|
} = RouterContextT>(opts: DefineRouteOpts): this;
|
|
217
240
|
define<T extends {
|
|
218
241
|
[key: string]: any;
|
|
219
|
-
} = RouterContextT>(fn: Run<T & U
|
|
242
|
+
} = RouterContextT>(fn: Run<T & BuildRouteContext<M, U>>): this;
|
|
220
243
|
define<T extends {
|
|
221
244
|
[key: string]: any;
|
|
222
|
-
} = RouterContextT>(key: string, fn: Run<T & U
|
|
245
|
+
} = RouterContextT>(key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
|
|
223
246
|
define<T extends {
|
|
224
247
|
[key: string]: any;
|
|
225
|
-
} = RouterContextT>(path: string, key: string, fn: Run<T & U
|
|
248
|
+
} = RouterContextT>(path: string, key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
|
|
226
249
|
update(opts: DefineRouteOpts, onlyUpdateList?: string[]): this;
|
|
227
250
|
addTo(router: QueryRouter | {
|
|
228
251
|
add: (route: Route) => void;
|
|
229
252
|
[key: string]: any;
|
|
230
253
|
}, opts?: AddOpts): void;
|
|
231
|
-
throw(
|
|
254
|
+
throw(...args: any[]): void;
|
|
232
255
|
}
|
|
233
256
|
/**
|
|
234
257
|
* @parmas overwrite 是否覆盖已存在的route,默认true
|
|
@@ -236,11 +259,11 @@ declare class Route<U = {
|
|
|
236
259
|
type AddOpts = {
|
|
237
260
|
overwrite?: boolean;
|
|
238
261
|
};
|
|
239
|
-
declare class QueryRouter {
|
|
262
|
+
declare class QueryRouter<T extends SimpleObject = SimpleObject> implements throwError {
|
|
240
263
|
appId: string;
|
|
241
264
|
routes: Route[];
|
|
242
265
|
maxNextRoute: number;
|
|
243
|
-
context?: RouteContext
|
|
266
|
+
context?: RouteContext<T>;
|
|
244
267
|
constructor();
|
|
245
268
|
/**
|
|
246
269
|
* add route
|
|
@@ -268,7 +291,7 @@ declare class QueryRouter {
|
|
|
268
291
|
* @param ctx
|
|
269
292
|
* @returns
|
|
270
293
|
*/
|
|
271
|
-
runRoute(path: string, key: string, ctx?: RouteContext):
|
|
294
|
+
runRoute(path: string, key: string, ctx?: RouteContext<T>): Promise<RouteContext<T>>;
|
|
272
295
|
/**
|
|
273
296
|
* 第一次执行
|
|
274
297
|
* @param message
|
|
@@ -279,9 +302,11 @@ declare class QueryRouter {
|
|
|
279
302
|
path: string;
|
|
280
303
|
key?: string;
|
|
281
304
|
payload?: any;
|
|
282
|
-
}, ctx?: RouteContext & {
|
|
305
|
+
}, ctx?: RouteContext<T> & {
|
|
283
306
|
[key: string]: any;
|
|
284
|
-
}): Promise<
|
|
307
|
+
}): Promise<RouteContext<T, {}, {
|
|
308
|
+
[key: string]: any;
|
|
309
|
+
}>>;
|
|
285
310
|
/**
|
|
286
311
|
* 返回的数据包含所有的context的请求返回的内容,可做其他处理
|
|
287
312
|
* @param message
|
|
@@ -293,9 +318,15 @@ declare class QueryRouter {
|
|
|
293
318
|
path?: string;
|
|
294
319
|
key?: string;
|
|
295
320
|
payload?: any;
|
|
296
|
-
}, ctx?: RouteContext & {
|
|
321
|
+
}, ctx?: RouteContext<T> & {
|
|
297
322
|
[key: string]: any;
|
|
298
|
-
}): Promise<
|
|
323
|
+
}): Promise<RouteContext<T, {}, {
|
|
324
|
+
[key: string]: any;
|
|
325
|
+
}> | {
|
|
326
|
+
code: number;
|
|
327
|
+
body: any;
|
|
328
|
+
message: string;
|
|
329
|
+
}>;
|
|
299
330
|
/**
|
|
300
331
|
* 请求 result 的数据
|
|
301
332
|
* @param message
|
|
@@ -311,9 +342,9 @@ declare class QueryRouter {
|
|
|
311
342
|
}, ctx?: RouteContext & {
|
|
312
343
|
[key: string]: any;
|
|
313
344
|
}): Promise<{
|
|
314
|
-
code:
|
|
345
|
+
code: number;
|
|
315
346
|
data: any;
|
|
316
|
-
message:
|
|
347
|
+
message: string;
|
|
317
348
|
}>;
|
|
318
349
|
/**
|
|
319
350
|
* Router Run获取数据
|
|
@@ -326,12 +357,12 @@ declare class QueryRouter {
|
|
|
326
357
|
path?: string;
|
|
327
358
|
key?: string;
|
|
328
359
|
payload?: any;
|
|
329
|
-
}, ctx?: RouteContext & {
|
|
360
|
+
}, ctx?: RouteContext<T> & {
|
|
330
361
|
[key: string]: any;
|
|
331
362
|
}): Promise<{
|
|
332
|
-
code:
|
|
363
|
+
code: number;
|
|
333
364
|
data: any;
|
|
334
|
-
message:
|
|
365
|
+
message: string;
|
|
335
366
|
}>;
|
|
336
367
|
/**
|
|
337
368
|
* 设置上下文
|
|
@@ -343,12 +374,12 @@ declare class QueryRouter {
|
|
|
343
374
|
/**
|
|
344
375
|
* 获取handle函数, 这里会去执行parse函数
|
|
345
376
|
*/
|
|
346
|
-
getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn
|
|
377
|
+
getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn, ctx?: RouteContext): (msg: {
|
|
347
378
|
id?: string;
|
|
348
379
|
path?: string;
|
|
349
380
|
key?: string;
|
|
350
381
|
[key: string]: any;
|
|
351
|
-
}, handleContext?: RouteContext) => Promise<{
|
|
382
|
+
}, handleContext?: RouteContext<T>) => Promise<{
|
|
352
383
|
[key: string]: any;
|
|
353
384
|
code: string;
|
|
354
385
|
data?: any;
|
|
@@ -362,24 +393,16 @@ declare class QueryRouter {
|
|
|
362
393
|
message: any;
|
|
363
394
|
data?: undefined;
|
|
364
395
|
}>;
|
|
365
|
-
exportRoutes(): Route<
|
|
366
|
-
[key: string]: any;
|
|
367
|
-
}, SimpleObject>[];
|
|
396
|
+
exportRoutes(): Route<SimpleObject, SimpleObject>[];
|
|
368
397
|
importRoutes(routes: Route[]): void;
|
|
369
398
|
importRouter(router: QueryRouter): void;
|
|
370
|
-
throw(
|
|
371
|
-
|
|
372
|
-
throw(opts?: CustomErrorOptions): void;
|
|
373
|
-
hasRoute(path: string, key?: string): Route<{
|
|
374
|
-
[key: string]: any;
|
|
375
|
-
}, SimpleObject>;
|
|
399
|
+
throw(...args: any[]): void;
|
|
400
|
+
hasRoute(path: string, key?: string): Route<SimpleObject, SimpleObject>;
|
|
376
401
|
findRoute(opts?: {
|
|
377
402
|
path?: string;
|
|
378
403
|
key?: string;
|
|
379
404
|
id?: string;
|
|
380
|
-
}): Route<
|
|
381
|
-
[key: string]: any;
|
|
382
|
-
}, SimpleObject>;
|
|
405
|
+
}): Route<SimpleObject, SimpleObject>;
|
|
383
406
|
createRouteList(opts?: {
|
|
384
407
|
force?: boolean;
|
|
385
408
|
filter?: (route: Route) => boolean;
|
|
@@ -421,6 +444,12 @@ declare class QueryRouter {
|
|
|
421
444
|
[key: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
422
445
|
};
|
|
423
446
|
}
|
|
447
|
+
type QueryRouterServerOpts<C extends SimpleObject = SimpleObject> = {
|
|
448
|
+
handleFn?: HandleFn;
|
|
449
|
+
context?: RouteContext<C>;
|
|
450
|
+
appId?: string;
|
|
451
|
+
initHandle?: boolean;
|
|
452
|
+
};
|
|
424
453
|
interface HandleFn<T = any> {
|
|
425
454
|
(msg: {
|
|
426
455
|
path: string;
|
|
@@ -433,6 +462,42 @@ interface HandleFn<T = any> {
|
|
|
433
462
|
};
|
|
434
463
|
(res: RouteContext<T>): any;
|
|
435
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* QueryRouterServer
|
|
467
|
+
* @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
|
|
468
|
+
* @template C 自定义 RouteContext 类型
|
|
469
|
+
*/
|
|
470
|
+
declare class QueryRouterServer<C extends SimpleObject = SimpleObject> extends QueryRouter<C> {
|
|
471
|
+
appId: string;
|
|
472
|
+
handle: any;
|
|
473
|
+
context: RouteContext<C>;
|
|
474
|
+
constructor(opts?: QueryRouterServerOpts<C>);
|
|
475
|
+
setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void;
|
|
476
|
+
addRoute(route: Route, opts?: AddOpts): void;
|
|
477
|
+
Route: typeof Route;
|
|
478
|
+
route<M extends SimpleObject = SimpleObject>(opts: RouteOpts & {
|
|
479
|
+
metadata?: M;
|
|
480
|
+
}): Route<M, Required<RouteContext<C>>>;
|
|
481
|
+
route<M extends SimpleObject = SimpleObject>(path: string, opts?: RouteOpts & {
|
|
482
|
+
metadata?: M;
|
|
483
|
+
}): Route<M, Required<RouteContext<C>>>;
|
|
484
|
+
route<M extends SimpleObject = SimpleObject>(path: string, key?: string): Route<M, Required<RouteContext<C>>>;
|
|
485
|
+
route<M extends SimpleObject = SimpleObject>(path: string, key?: string, opts?: RouteOpts & {
|
|
486
|
+
metadata?: M;
|
|
487
|
+
}): Route<M, Required<RouteContext<C>>>;
|
|
488
|
+
prompt(description: string): Route<SimpleObject, SimpleObject>;
|
|
489
|
+
/**
|
|
490
|
+
* 调用了handle
|
|
491
|
+
* @param param0
|
|
492
|
+
* @returns
|
|
493
|
+
*/
|
|
494
|
+
run(msg: {
|
|
495
|
+
id?: string;
|
|
496
|
+
path?: string;
|
|
497
|
+
key?: string;
|
|
498
|
+
payload?: any;
|
|
499
|
+
}, ctx?: Partial<RouteContext<C>>): Promise<any>;
|
|
500
|
+
}
|
|
436
501
|
|
|
437
502
|
type Cors = {
|
|
438
503
|
/**
|
|
@@ -682,7 +747,7 @@ type RouterHandle = (msg: {
|
|
|
682
747
|
[key: string]: any;
|
|
683
748
|
};
|
|
684
749
|
type AppOptions<T = {}> = {
|
|
685
|
-
router?:
|
|
750
|
+
router?: QueryRouterServer;
|
|
686
751
|
server?: ServerType;
|
|
687
752
|
/** handle msg 关联 */
|
|
688
753
|
routerHandle?: RouterHandle;
|
|
@@ -690,17 +755,18 @@ type AppOptions<T = {}> = {
|
|
|
690
755
|
serverOptions?: ServerNodeOpts;
|
|
691
756
|
appId?: string;
|
|
692
757
|
};
|
|
693
|
-
type AppRouteContext<T
|
|
758
|
+
type AppRouteContext<T> = HandleCtx & RouteContext<T> & {
|
|
694
759
|
app: App<T>;
|
|
695
760
|
};
|
|
696
761
|
/**
|
|
697
762
|
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
|
698
763
|
* U - Route Context的扩展类型
|
|
699
764
|
*/
|
|
700
|
-
declare class App<U = {}> extends
|
|
765
|
+
declare class App<U = {}> extends QueryRouterServer<AppRouteContext<U>> {
|
|
701
766
|
appId: string;
|
|
702
|
-
router:
|
|
767
|
+
router: QueryRouterServer;
|
|
703
768
|
server: ServerType;
|
|
769
|
+
context: AppRouteContext<U>;
|
|
704
770
|
constructor(opts?: AppOptions<U>);
|
|
705
771
|
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
|
|
706
772
|
listen(port: number, hostname?: string, listeningListener?: () => void): void;
|
|
@@ -710,34 +776,7 @@ declare class App<U = {}> extends QueryRouter {
|
|
|
710
776
|
listen(path: string, listeningListener?: () => void): void;
|
|
711
777
|
listen(handle: any, backlog?: number, listeningListener?: () => void): void;
|
|
712
778
|
listen(handle: any, listeningListener?: () => void): void;
|
|
713
|
-
addRoute(route: Route, opts?: AddOpts): void;
|
|
714
779
|
Route: typeof Route;
|
|
715
|
-
route(opts: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
|
716
|
-
route(path: string, key?: string): Route<AppRouteContext<U>>;
|
|
717
|
-
route(path: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
|
718
|
-
route(path: string, key?: string, opts?: RouteOpts<AppRouteContext<U>>): Route<AppRouteContext<U>>;
|
|
719
|
-
prompt(description: string): Route<AppRouteContext<U>>;
|
|
720
|
-
prompt(description: Function): Route<AppRouteContext<U>>;
|
|
721
|
-
call(message: {
|
|
722
|
-
id?: string;
|
|
723
|
-
path?: string;
|
|
724
|
-
key?: string;
|
|
725
|
-
payload?: any;
|
|
726
|
-
}, ctx?: AppRouteContext<U> & {
|
|
727
|
-
[key: string]: any;
|
|
728
|
-
}): Promise<any>;
|
|
729
|
-
run(msg: {
|
|
730
|
-
id?: string;
|
|
731
|
-
path?: string;
|
|
732
|
-
key?: string;
|
|
733
|
-
payload?: any;
|
|
734
|
-
}, ctx?: Partial<AppRouteContext<U>> & {
|
|
735
|
-
[key: string]: any;
|
|
736
|
-
}): Promise<{
|
|
737
|
-
code: any;
|
|
738
|
-
data: any;
|
|
739
|
-
message: any;
|
|
740
|
-
}>;
|
|
741
780
|
static handleRequest(req: IncomingMessage$1, res: ServerResponse$1): Promise<{
|
|
742
781
|
cookies: Record<string, string>;
|
|
743
782
|
token: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@kevisual/router",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.84",
|
|
5
5
|
"description": "",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/router.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@types/xml2js": "^0.4.14",
|
|
38
38
|
"eventemitter3": "^5.0.4",
|
|
39
39
|
"fast-glob": "^3.3.3",
|
|
40
|
-
"hono": "^4.12.
|
|
40
|
+
"hono": "^4.12.2",
|
|
41
41
|
"nanoid": "^5.1.6",
|
|
42
42
|
"path-to-regexp": "^8.3.0",
|
|
43
43
|
"send": "^1.2.1",
|
package/readme.md
CHANGED
|
@@ -31,63 +31,58 @@ app
|
|
|
31
31
|
|
|
32
32
|
在 route handler 中,你可以通过 `ctx` 访问以下属性:
|
|
33
33
|
|
|
34
|
-
| 属性
|
|
35
|
-
|
|
36
|
-
| `query`
|
|
37
|
-
| `body`
|
|
38
|
-
| `code`
|
|
39
|
-
| `message`
|
|
40
|
-
| `state`
|
|
41
|
-
| `appId`
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
34
|
+
| 属性 | 类型 | 说明 |
|
|
35
|
+
| --------------- | ---------------------------- | ---------------------------- |
|
|
36
|
+
| `query` | `object` | 请求参数,会自动合并 payload |
|
|
37
|
+
| `body` | `number \| string \| Object` | 响应内容 |
|
|
38
|
+
| `code` | `number` | 响应状态码,默认为 200 |
|
|
39
|
+
| `message` | `string` | 响应消息 |
|
|
40
|
+
| `state` | `any` | 状态数据,可在路由间传递 |
|
|
41
|
+
| `appId` | `string` | 应用标识 |
|
|
42
|
+
| `currentId` | `string` | 当前路由ID |
|
|
43
|
+
| `currentPath` | `string` | 当前路由路径 |
|
|
44
|
+
| `currentKey` | `string` | 当前路由 key |
|
|
45
|
+
| `currentRoute` | `Route` | 当前 Route 实例 |
|
|
46
|
+
| `progress` | `[string, string][]` | 路由执行路径记录 |
|
|
47
|
+
| `nextQuery` | `object` | 传递给下一个路由的参数 |
|
|
48
|
+
| `end` | `boolean` | 是否提前结束路由执行 |
|
|
49
|
+
| `app` | `QueryRouter` | 路由实例引用 |
|
|
50
|
+
| `error` | `any` | 错误信息 |
|
|
51
|
+
| `index` | `number` | 当前路由执行深度 |
|
|
52
|
+
| `needSerialize` | `boolean` | 是否需要序列化响应数据 |
|
|
52
53
|
|
|
53
54
|
### 上下文方法
|
|
54
55
|
|
|
55
|
-
| 方法
|
|
56
|
-
|
|
57
|
-
| `ctx.call(msg, ctx?)`
|
|
58
|
-
| `ctx.run(msg, ctx?)`
|
|
59
|
-
| `ctx.forward(res)`
|
|
60
|
-
| `ctx.throw(code?, message?, tips?)` | -
|
|
56
|
+
| 方法 | 参数 | 说明 |
|
|
57
|
+
| ----------------------------------- | ----------------------------------------- | -------------------------------------------- |
|
|
58
|
+
| `ctx.call(msg, ctx?)` | `{ path, key?, payload?, ... } \| { id }` | 调用其他路由,返回完整 context |
|
|
59
|
+
| `ctx.run(msg, ctx?)` | `{ path, key?, payload? }` | 调用其他路由,返回 `{ code, data, message }` |
|
|
60
|
+
| `ctx.forward(res)` | `{ code, data?, message? }` | 设置响应结果 |
|
|
61
|
+
| `ctx.throw(code?, message?, tips?)` | - | 抛出自定义错误 |
|
|
61
62
|
|
|
62
63
|
## 完整示例
|
|
63
64
|
|
|
64
65
|
```ts
|
|
65
66
|
import { App } from '@kevisual/router';
|
|
66
|
-
|
|
67
|
+
import z from 'zod';
|
|
67
68
|
const app = new App();
|
|
68
69
|
app.listen(4002);
|
|
69
70
|
|
|
70
71
|
// 基本路由
|
|
71
72
|
app
|
|
72
|
-
.route({ path: 'user', key: 'info' })
|
|
73
|
+
.route({ path: 'user', key: 'info', id: 'user-info' })
|
|
73
74
|
.define(async (ctx) => {
|
|
74
75
|
// ctx.query 包含请求参数
|
|
75
76
|
const { id } = ctx.query;
|
|
77
|
+
// 使用 state 在路由间传递数据
|
|
78
|
+
ctx.state.orderId = '12345';
|
|
76
79
|
ctx.body = { id, name: '张三' };
|
|
77
80
|
ctx.code = 200;
|
|
78
81
|
})
|
|
79
82
|
.addTo(app);
|
|
80
83
|
|
|
81
|
-
// 使用 state 在路由间传递数据
|
|
82
|
-
app
|
|
83
|
-
.route({ path: 'order', key: 'create' })
|
|
84
|
-
.define(async (ctx) => {
|
|
85
|
-
ctx.state = { orderId: '12345' };
|
|
86
|
-
})
|
|
87
|
-
.addTo(app);
|
|
88
|
-
|
|
89
84
|
app
|
|
90
|
-
.route({ path: 'order', key: 'pay' })
|
|
85
|
+
.route({ path: 'order', key: 'pay', middleware: ['user-info'] })
|
|
91
86
|
.define(async (ctx) => {
|
|
92
87
|
// 可以获取前一个路由设置的 state
|
|
93
88
|
const { orderId } = ctx.state;
|
|
@@ -95,14 +90,6 @@ app
|
|
|
95
90
|
})
|
|
96
91
|
.addTo(app);
|
|
97
92
|
|
|
98
|
-
// 链式调用
|
|
99
|
-
app
|
|
100
|
-
.route({ path: 'product', key: 'list' })
|
|
101
|
-
.define(async (ctx) => {
|
|
102
|
-
ctx.body = [{ id: 1, name: '商品A' }];
|
|
103
|
-
})
|
|
104
|
-
.addTo(app);
|
|
105
|
-
|
|
106
93
|
// 调用其他路由
|
|
107
94
|
app
|
|
108
95
|
.route({ path: 'dashboard', key: 'stats' })
|
|
@@ -114,7 +101,7 @@ app
|
|
|
114
101
|
|
|
115
102
|
ctx.body = {
|
|
116
103
|
user: userRes.data,
|
|
117
|
-
products: productRes.data
|
|
104
|
+
products: productRes.data,
|
|
118
105
|
};
|
|
119
106
|
})
|
|
120
107
|
.addTo(app);
|
|
@@ -140,17 +127,20 @@ import { App, Route } from '@kevisual/router';
|
|
|
140
127
|
const app = new App();
|
|
141
128
|
|
|
142
129
|
// 定义中间件
|
|
143
|
-
app
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
130
|
+
app
|
|
131
|
+
.route({
|
|
132
|
+
id: 'auth-example',
|
|
133
|
+
description: '权限校验中间件',
|
|
134
|
+
})
|
|
135
|
+
.define(async (ctx) => {
|
|
136
|
+
const token = ctx.query.token;
|
|
137
|
+
if (!token) {
|
|
138
|
+
ctx.throw(401, '未登录', '需要 token');
|
|
139
|
+
}
|
|
140
|
+
// 验证通过,设置用户信息到 state
|
|
141
|
+
ctx.state.tokenUser = { id: 1, name: '用户A' };
|
|
142
|
+
})
|
|
143
|
+
.addTo(app);
|
|
154
144
|
|
|
155
145
|
// 使用中间件(通过 id 引用)
|
|
156
146
|
app
|
|
@@ -163,6 +153,33 @@ app
|
|
|
163
153
|
.addTo(app);
|
|
164
154
|
```
|
|
165
155
|
|
|
156
|
+
## 一个丰富的router示例
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { App } from '@kevisual/router';
|
|
160
|
+
const app = new App();
|
|
161
|
+
|
|
162
|
+
app
|
|
163
|
+
.router({
|
|
164
|
+
path: 'dog',
|
|
165
|
+
key: 'info',
|
|
166
|
+
description: '获取狗的信息',
|
|
167
|
+
metedata: {
|
|
168
|
+
args: {
|
|
169
|
+
owner: z.string().describe('狗主人姓名'),
|
|
170
|
+
age: z.number().describe('狗的年龄'),
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
.define(async (ctx) => {
|
|
175
|
+
const { owner, age } = ctx.query;
|
|
176
|
+
ctx.body = {
|
|
177
|
+
content: `这是一只${age}岁的狗,主人是${owner}`,
|
|
178
|
+
};
|
|
179
|
+
})
|
|
180
|
+
.addTo(app);
|
|
181
|
+
```
|
|
182
|
+
|
|
166
183
|
## 注意事项
|
|
167
184
|
|
|
168
185
|
1. **path 和 key 的组合是路由的唯一标识**,同一个 path+key 只能添加一个路由,后添加的会覆盖之前的。
|
|
@@ -173,16 +190,14 @@ app
|
|
|
173
190
|
|
|
174
191
|
3. **ctx.throw 会自动结束执行**,抛出自定义错误。
|
|
175
192
|
|
|
176
|
-
4. **
|
|
177
|
-
|
|
178
|
-
5. **payload 会自动合并到 query**,调用 `ctx.run({ path, key, payload })` 时,payload 会合并到 query。
|
|
193
|
+
4. **payload 会自动合并到 query**,调用 `ctx.run({ path, key, payload })` 时,payload 会合并到 query。
|
|
179
194
|
|
|
180
|
-
|
|
195
|
+
5. **nextQuery 用于传递给 nextRoute**,在当前路由中设置 `ctx.nextQuery`,会在执行 nextRoute 时合并到 query。
|
|
181
196
|
|
|
182
|
-
|
|
197
|
+
6. **避免 nextRoute 循环调用**,默认最大深度为 40 次,超过会返回 500 错误。
|
|
183
198
|
|
|
184
|
-
|
|
199
|
+
7. **needSerialize 默认为 true**,会自动对 body 进行 JSON 序列化和反序列化。
|
|
185
200
|
|
|
186
|
-
|
|
201
|
+
8. **progress 记录执行路径**,可用于调试和追踪路由调用链。
|
|
187
202
|
|
|
188
|
-
|
|
203
|
+
9. **中间件找不到会返回 404**,错误信息中会包含找不到的中间件列表。
|