@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/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
- }, S = any> = {
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?: (code?: number | string, message?: string, tips?: string) => void;
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: string;
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
- declare class Route<U = {
190
- [key: string]: any;
191
- }, T extends SimpleObject = SimpleObject> {
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?: T;
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>): this;
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>): this;
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>): this;
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(code?: number | string, message?: string, tips?: string): void;
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): any;
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<any>;
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<any>;
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: any;
345
+ code: number;
315
346
  data: any;
316
- message: any;
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: any;
363
+ code: number;
333
364
  data: any;
334
- message: any;
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<T>, ctx?: RouteContext): (msg: {
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(code?: number | string, message?: string): void;
371
- throw(code?: number | string, opts?: CustomErrorOptions): void;
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?: QueryRouter;
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 = {}> = HandleCtx & RouteContext<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 QueryRouter {
765
+ declare class App<U = {}> extends QueryRouterServer<AppRouteContext<U>> {
701
766
  appId: string;
702
- router: QueryRouter;
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.82",
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.0",
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` | `object` | 请求参数,会自动合并 payload |
37
- | `body` | `number \| string \| Object` | 响应内容 |
38
- | `code` | `number` | 响应状态码,默认为 200 |
39
- | `message` | `string` | 响应消息 |
40
- | `state` | `any` | 状态数据,可在路由间传递 |
41
- | `appId` | `string` | 应用标识 |
42
- | `currentPath` | `string` | 当前路由路径 |
43
- | `currentKey` | `string` | 当前路由 key |
44
- | `currentRoute` | `Route` | 当前 Route 实例 |
45
- | `progress` | `[string, string][]` | 路由执行路径记录 |
46
- | `nextQuery` | `object` | 传递给下一个路由的参数 |
47
- | `end` | `boolean` | 是否提前结束路由执行 |
48
- | `app` | `QueryRouter` | 路由实例引用 |
49
- | `error` | `any` | 错误信息 |
50
- | `index` | `number` | 当前路由执行深度 |
51
- | `needSerialize` | `boolean` | 是否需要序列化响应数据 |
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?)` | `{ path, key?, payload?, ... } \| { id }` | 调用其他路由,返回完整 context |
58
- | `ctx.run(msg, ctx?)` | `{ path, key?, payload? }` | 调用其他路由,返回 `{ code, data, message }` |
59
- | `ctx.forward(res)` | `{ code, data?, message? }` | 设置响应结果 |
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.route({
144
- id: 'auth-example',
145
- description: '权限校验中间件'
146
- }).define(async(ctx) => {
147
- const token = ctx.query.token;
148
- if (!token) {
149
- ctx.throw(401, '未登录', '需要 token');
150
- }
151
- // 验证通过,设置用户信息到 state
152
- ctx.state.tokenUser = { id: 1, name: '用户A' };
153
- }).addTo(app);
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. **state 不会自动继承**,每个路由的 state 是独立的,除非显式传递或使用 nextRoute
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
- 6. **nextQuery 用于传递给 nextRoute**,在当前路由中设置 `ctx.nextQuery`,会在执行 nextRoute 时合并到 query。
195
+ 5. **nextQuery 用于传递给 nextRoute**,在当前路由中设置 `ctx.nextQuery`,会在执行 nextRoute 时合并到 query。
181
196
 
182
- 7. **避免 nextRoute 循环调用**,默认最大深度为 40 次,超过会返回 500 错误。
197
+ 6. **避免 nextRoute 循环调用**,默认最大深度为 40 次,超过会返回 500 错误。
183
198
 
184
- 8. **needSerialize 默认为 true**,会自动对 body 进行 JSON 序列化和反序列化。
199
+ 7. **needSerialize 默认为 true**,会自动对 body 进行 JSON 序列化和反序列化。
185
200
 
186
- 9. **progress 记录执行路径**,可用于调试和追踪路由调用链。
201
+ 8. **progress 记录执行路径**,可用于调试和追踪路由调用链。
187
202
 
188
- 10. **中间件找不到会返回 404**,错误信息中会包含找不到的中间件列表。
203
+ 9. **中间件找不到会返回 404**,错误信息中会包含找不到的中间件列表。