@kevisual/router 0.0.14 → 0.0.16

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.
@@ -110,6 +110,11 @@ type RouteContext<T = {
110
110
  } & T;
111
111
  type Run<T = any> = (ctx: RouteContext<T>) => Promise<typeof ctx | null | void>;
112
112
  type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
113
+ type RouteMiddleware = {
114
+ path: string;
115
+ key?: string;
116
+ id?: string;
117
+ } | string;
113
118
  type RouteOpts = {
114
119
  path?: string;
115
120
  key?: string;
@@ -120,7 +125,7 @@ type RouteOpts = {
120
125
  metadata?: {
121
126
  [key: string]: any;
122
127
  };
123
- middleware?: Route[] | string[];
128
+ middleware?: RouteMiddleware[];
124
129
  type?: 'route' | 'middleware';
125
130
  /**
126
131
  * validator: {
@@ -143,6 +148,10 @@ type RouteOpts = {
143
148
  * $#$ will be used to split path and key
144
149
  */
145
150
  idUsePath?: boolean;
151
+ /**
152
+ * id 合并的分隔符,默认为 $#$
153
+ */
154
+ delimiter?: string;
146
155
  isDebug?: boolean;
147
156
  };
148
157
  type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -167,7 +176,7 @@ declare class Route<U = {
167
176
  metadata?: {
168
177
  [key: string]: any;
169
178
  };
170
- middleware?: (Route | string)[];
179
+ middleware?: RouteMiddleware[];
171
180
  type?: string;
172
181
  private _validator?;
173
182
  schema?: {
@@ -403,6 +412,12 @@ declare class CustomError extends Error {
403
412
  message: string;
404
413
  tips: string;
405
414
  };
415
+ /**
416
+ * 判断 throw 的错误是否不是当前这个错误
417
+ * @param err
418
+ * @returns
419
+ */
420
+ static isError(err: any): boolean;
406
421
  parse(e?: CustomError): {
407
422
  code: number;
408
423
  data: any;
@@ -51,11 +51,23 @@ class CustomError extends Error {
51
51
  tips: e?.tips,
52
52
  };
53
53
  }
54
+ /**
55
+ * 判断 throw 的错误是否不是当前这个错误
56
+ * @param err
57
+ * @returns
58
+ */
59
+ static isError(err) {
60
+ if (err instanceof CustomError || err?.code) {
61
+ return true;
62
+ }
63
+ return false;
64
+ }
54
65
  parse(e) {
55
66
  if (e) {
56
67
  return CustomError.parseError(e);
57
68
  }
58
69
  else {
70
+ const e = this;
59
71
  return {
60
72
  code: e?.code,
61
73
  data: e?.data,
@@ -5656,7 +5668,8 @@ class Route {
5656
5668
  if (opts) {
5657
5669
  this.id = opts.id || nanoid();
5658
5670
  if (!opts.id && opts.idUsePath) {
5659
- this.id = path + '$#$' + key;
5671
+ const delimiter = opts.delimiter ?? '$#$';
5672
+ this.id = path + delimiter + key;
5660
5673
  }
5661
5674
  this.run = opts.run;
5662
5675
  this.nextRoute = opts.nextRoute;
@@ -5898,7 +5911,15 @@ class QueryRouter {
5898
5911
  route = this.routes.find((r) => r.id === item);
5899
5912
  }
5900
5913
  else {
5901
- route = this.routes.find((r) => r.path === item.path && r.key === item.key);
5914
+ route = this.routes.find((r) => {
5915
+ if (item.id) {
5916
+ return r.id === item.id;
5917
+ }
5918
+ else {
5919
+ // key 可以是空,所以可以不严格验证
5920
+ return r.path === item.path && r.key == item.key;
5921
+ }
5922
+ });
5902
5923
  }
5903
5924
  if (!route) {
5904
5925
  if (isString) {
@@ -0,0 +1,464 @@
1
+ import * as node_modules_zod_lib_types_js from 'node_modules/zod/lib/types.js';
2
+ import { Schema } from 'zod';
3
+
4
+ type BaseRule = {
5
+ value?: any;
6
+ required?: boolean;
7
+ message?: string;
8
+ };
9
+ type RuleString = {
10
+ type: 'string';
11
+ minLength?: number;
12
+ maxLength?: number;
13
+ regex?: string;
14
+ } & BaseRule;
15
+ type RuleNumber = {
16
+ type: 'number';
17
+ min?: number;
18
+ max?: number;
19
+ } & BaseRule;
20
+ type RuleBoolean = {
21
+ type: 'boolean';
22
+ } & BaseRule;
23
+ type RuleArray = {
24
+ type: 'array';
25
+ items: Rule;
26
+ minItems?: number;
27
+ maxItems?: number;
28
+ } & BaseRule;
29
+ type RuleObject = {
30
+ type: 'object';
31
+ properties: {
32
+ [key: string]: Rule;
33
+ };
34
+ } & BaseRule;
35
+ type RuleAny = {
36
+ type: 'any';
37
+ } & BaseRule;
38
+ type Rule = RuleString | RuleNumber | RuleBoolean | RuleArray | RuleObject | RuleAny;
39
+
40
+ type RouterContextT = {
41
+ code?: number;
42
+ [key: string]: any;
43
+ };
44
+ type RouteContext<T = {
45
+ code?: number;
46
+ }, S = any> = {
47
+ query?: {
48
+ [key: string]: any;
49
+ };
50
+ /** return body */
51
+ body?: number | string | Object;
52
+ /** return code */
53
+ code?: number;
54
+ /** return msg */
55
+ message?: string;
56
+ state?: S;
57
+ /**
58
+ * 当前路径
59
+ */
60
+ currentPath?: string;
61
+ /**
62
+ * 当前key
63
+ */
64
+ currentKey?: string;
65
+ /**
66
+ * 当前route
67
+ */
68
+ currentRoute?: Route;
69
+ /**
70
+ * 进度
71
+ */
72
+ progress?: [string, string][];
73
+ nextQuery?: {
74
+ [key: string]: any;
75
+ };
76
+ end?: boolean;
77
+ /**
78
+ * 请求 route的返回结果,包函ctx
79
+ */
80
+ queryRouter?: QueryRouter;
81
+ error?: any;
82
+ /** 请求 route的返回结果,包函ctx */
83
+ call?: (message: {
84
+ path: string;
85
+ key?: string;
86
+ payload?: any;
87
+ [key: string]: any;
88
+ } | {
89
+ id: string;
90
+ apyload?: any;
91
+ [key: string]: any;
92
+ }, ctx?: RouteContext & {
93
+ [key: string]: any;
94
+ }) => Promise<any>;
95
+ /** 请求 route的返回结果,不包函ctx */
96
+ queryRoute?: (message: {
97
+ path: string;
98
+ key?: string;
99
+ payload?: any;
100
+ }, ctx?: RouteContext & {
101
+ [key: string]: any;
102
+ }) => Promise<any>;
103
+ index?: number;
104
+ throw?: (code?: number | string, message?: string, tips?: string) => void;
105
+ /** 是否需要序列化 */
106
+ needSerialize?: boolean;
107
+ } & T;
108
+ type Run<T = any> = (ctx: RouteContext<T>) => Promise<typeof ctx | null | void>;
109
+ type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
110
+ type RouteMiddleware = {
111
+ path: string;
112
+ key?: string;
113
+ id?: string;
114
+ } | string;
115
+ type RouteOpts = {
116
+ path?: string;
117
+ key?: string;
118
+ id?: string;
119
+ run?: Run;
120
+ nextRoute?: NextRoute;
121
+ description?: string;
122
+ metadata?: {
123
+ [key: string]: any;
124
+ };
125
+ middleware?: RouteMiddleware[];
126
+ type?: 'route' | 'middleware';
127
+ /**
128
+ * validator: {
129
+ * packageName: {
130
+ * type: 'string',
131
+ * required: true,
132
+ * },
133
+ * }
134
+ */
135
+ validator?: {
136
+ [key: string]: Rule;
137
+ };
138
+ schema?: {
139
+ [key: string]: Schema<any>;
140
+ };
141
+ isVerify?: boolean;
142
+ verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
143
+ verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
144
+ /**
145
+ * $#$ will be used to split path and key
146
+ */
147
+ idUsePath?: boolean;
148
+ /**
149
+ * id 合并的分隔符,默认为 $#$
150
+ */
151
+ delimiter?: string;
152
+ isDebug?: boolean;
153
+ };
154
+ type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
155
+ declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
156
+ type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
157
+ declare class Route<U = {
158
+ [key: string]: any;
159
+ }> {
160
+ /**
161
+ * 一级路径
162
+ */
163
+ path?: string;
164
+ /**
165
+ * 二级路径
166
+ */
167
+ key?: string;
168
+ id?: string;
169
+ share?: boolean;
170
+ run?: Run;
171
+ nextRoute?: NextRoute;
172
+ description?: string;
173
+ metadata?: {
174
+ [key: string]: any;
175
+ };
176
+ middleware?: RouteMiddleware[];
177
+ type?: string;
178
+ private _validator?;
179
+ schema?: {
180
+ [key: string]: Schema<any>;
181
+ };
182
+ data?: any;
183
+ /**
184
+ * 是否需要验证
185
+ */
186
+ isVerify?: boolean;
187
+ /**
188
+ * 是否开启debug,开启后会打印错误信息
189
+ */
190
+ isDebug?: boolean;
191
+ constructor(path: string, key?: string, opts?: RouteOpts);
192
+ private createSchema;
193
+ /**
194
+ * set validator and create schema
195
+ * @param validator
196
+ */
197
+ set validator(validator: {
198
+ [key: string]: Rule;
199
+ });
200
+ get validator(): {
201
+ [key: string]: Rule;
202
+ };
203
+ /**
204
+ * has code, body, message in ctx, return ctx if has error
205
+ * @param ctx
206
+ * @param dev
207
+ * @returns
208
+ */
209
+ verify(ctx: RouteContext, dev?: boolean): void;
210
+ /**
211
+ * Need to manully call return ctx fn and configure body, code, message
212
+ * @param key
213
+ * @param ctx
214
+ * @param dev
215
+ * @returns
216
+ */
217
+ verifyKey(key: string, ctx: RouteContext, dev?: boolean): {
218
+ message: string;
219
+ path: string;
220
+ key: string;
221
+ error: any;
222
+ } | {
223
+ message: string;
224
+ path: string;
225
+ key: string;
226
+ error?: undefined;
227
+ };
228
+ setValidator(validator: {
229
+ [key: string]: Rule;
230
+ }): this;
231
+ define<T extends {
232
+ [key: string]: any;
233
+ } = RouterContextT>(opts: DefineRouteOpts): this;
234
+ define<T extends {
235
+ [key: string]: any;
236
+ } = RouterContextT>(fn: Run<T & U>): this;
237
+ define<T extends {
238
+ [key: string]: any;
239
+ } = RouterContextT>(key: string, fn: Run<T & U>): this;
240
+ define<T extends {
241
+ [key: string]: any;
242
+ } = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
243
+ addTo(router: QueryRouter | {
244
+ add: (route: Route) => void;
245
+ [key: string]: any;
246
+ }): void;
247
+ setData(data: any): this;
248
+ throw(code?: number | string, message?: string, tips?: string): void;
249
+ }
250
+ declare class QueryRouter {
251
+ routes: Route[];
252
+ maxNextRoute: number;
253
+ context?: RouteContext;
254
+ constructor();
255
+ add(route: Route): void;
256
+ /**
257
+ * remove route by path and key
258
+ * @param route
259
+ */
260
+ remove(route: Route | {
261
+ path: string;
262
+ key?: string;
263
+ }): void;
264
+ /**
265
+ * remove route by id
266
+ * @param uniqueId
267
+ */
268
+ removeById(unique: string): void;
269
+ /**
270
+ * 执行route
271
+ * @param path
272
+ * @param key
273
+ * @param ctx
274
+ * @returns
275
+ */
276
+ runRoute(path: string, key: string, ctx?: RouteContext): any;
277
+ /**
278
+ * 第一次执行
279
+ * @param message
280
+ * @param ctx
281
+ * @returns
282
+ */
283
+ parse(message: {
284
+ path: string;
285
+ key?: string;
286
+ payload?: any;
287
+ }, ctx?: RouteContext & {
288
+ [key: string]: any;
289
+ }): Promise<any>;
290
+ /**
291
+ * 返回的数据包含所有的context的请求返回的内容,可做其他处理
292
+ * @param message
293
+ * @param ctx
294
+ * @returns
295
+ */
296
+ call(message: {
297
+ id?: string;
298
+ path?: string;
299
+ key?: string;
300
+ payload?: any;
301
+ }, ctx?: RouteContext & {
302
+ [key: string]: any;
303
+ }): Promise<any>;
304
+ /**
305
+ * 请求 result 的数据
306
+ * @param message
307
+ * @param ctx
308
+ * @returns
309
+ */
310
+ queryRoute(message: {
311
+ path: string;
312
+ key?: string;
313
+ payload?: any;
314
+ }, ctx?: RouteContext & {
315
+ [key: string]: any;
316
+ }): Promise<{
317
+ code: any;
318
+ data: any;
319
+ message: any;
320
+ }>;
321
+ setContext(ctx: RouteContext): Promise<void>;
322
+ getList(): RouteInfo[];
323
+ /**
324
+ * 获取handle函数, 这里会去执行parse函数
325
+ */
326
+ getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext): (msg: {
327
+ path: string;
328
+ key?: string;
329
+ [key: string]: any;
330
+ }, handleContext?: RouteContext) => Promise<{
331
+ [key: string]: any;
332
+ code: string;
333
+ data?: any;
334
+ message?: string;
335
+ } | {
336
+ code: any;
337
+ data: any;
338
+ message: any;
339
+ } | {
340
+ code: number;
341
+ message: any;
342
+ data?: undefined;
343
+ }>;
344
+ exportRoutes(): Route<{
345
+ [key: string]: any;
346
+ }>[];
347
+ importRoutes(routes: Route[]): void;
348
+ importRouter(router: QueryRouter): void;
349
+ throw(code?: number | string, message?: string, tips?: string): void;
350
+ hasRoute(path: string, key?: string): Route<{
351
+ [key: string]: any;
352
+ }>;
353
+ }
354
+ type QueryRouterServerOpts = {
355
+ handleFn?: HandleFn;
356
+ context?: RouteContext;
357
+ };
358
+ interface HandleFn<T = any> {
359
+ (msg: {
360
+ path: string;
361
+ [key: string]: any;
362
+ }, ctx?: any): {
363
+ code: string;
364
+ data?: any;
365
+ message?: string;
366
+ [key: string]: any;
367
+ };
368
+ (res: RouteContext<T>): any;
369
+ }
370
+ /**
371
+ * QueryRouterServer
372
+ * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
373
+ */
374
+ declare class QueryRouterServer extends QueryRouter {
375
+ handle: any;
376
+ constructor(opts?: QueryRouterServerOpts);
377
+ setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void;
378
+ use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void;
379
+ addRoute(route: Route): void;
380
+ Route: typeof Route;
381
+ route(opts: RouteOpts): Route<Required<RouteContext>>;
382
+ route(path: string, key?: string): Route<Required<RouteContext>>;
383
+ route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
384
+ route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
385
+ /**
386
+ * 等于queryRoute,但是调用了handle
387
+ * @param param0
388
+ * @returns
389
+ */
390
+ run({ path, key, payload }: {
391
+ path: string;
392
+ key?: string;
393
+ payload?: any;
394
+ }): Promise<any>;
395
+ }
396
+
397
+ type RouteObject = {
398
+ [key: string]: RouteOpts;
399
+ };
400
+ declare function define<T extends Record<string, RouteOpts>>(value: T): {
401
+ [K in keyof T]: T[K] & RouteOpts;
402
+ };
403
+ type RouteArray = RouteOpts[];
404
+ type ChainOptions = {
405
+ app: QueryRouterServer;
406
+ };
407
+ declare class Chain {
408
+ object: RouteOpts;
409
+ app?: QueryRouterServer;
410
+ constructor(object: RouteOpts, opts?: ChainOptions);
411
+ get key(): string;
412
+ get path(): string;
413
+ setDescription(desc: string): this;
414
+ setMeta(metadata: {
415
+ [key: string]: any;
416
+ }): this;
417
+ setPath(path: string): this;
418
+ setMiddleware(middleware: RouteMiddleware[]): this;
419
+ setKey(key: string): this;
420
+ setId(key: string): this;
421
+ setRun(run: Run): this;
422
+ define(run: Run): this;
423
+ createRoute(): this;
424
+ }
425
+ declare const util: {
426
+ getChain: (obj: RouteOpts, opts?: ChainOptions) => Chain;
427
+ };
428
+ declare class QueryUtil<T extends RouteObject = RouteObject> {
429
+ routeObject: T;
430
+ app: QueryRouterServer;
431
+ constructor(object: T, opts?: ChainOptions);
432
+ static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions): QueryUtil<U>;
433
+ static create<U extends Record<string, RouteOpts>>(value: U, opts?: ChainOptions): QueryUtil<U>;
434
+ get<K extends keyof T>(key: K): RouteOpts;
435
+ chain<K extends keyof T>(key: K, opts?: ChainOptions): Chain;
436
+ queryChain<K extends keyof T>(key: K): (queryData?: Record<string, any>) => {
437
+ path?: string;
438
+ key?: string;
439
+ id?: string;
440
+ run?: Run;
441
+ nextRoute?: NextRoute;
442
+ description?: string;
443
+ metadata?: {
444
+ [key: string]: any;
445
+ };
446
+ middleware?: RouteMiddleware[];
447
+ type?: "route" | "middleware";
448
+ validator?: {
449
+ [key: string]: Rule;
450
+ };
451
+ schema?: {
452
+ [key: string]: node_modules_zod_lib_types_js.ZodType<any>;
453
+ };
454
+ isVerify?: boolean;
455
+ verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
456
+ verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
457
+ idUsePath?: boolean;
458
+ delimiter?: string;
459
+ isDebug?: boolean;
460
+ };
461
+ }
462
+
463
+ export { QueryUtil, define, util };
464
+ export type { RouteArray, RouteObject, RouteOpts };
@@ -0,0 +1,92 @@
1
+ function define(value) {
2
+ return value;
3
+ }
4
+ class Chain {
5
+ object;
6
+ app;
7
+ constructor(object, opts) {
8
+ this.object = object;
9
+ this.app = opts?.app;
10
+ }
11
+ get key() {
12
+ return this.object.key;
13
+ }
14
+ get path() {
15
+ return this.object.path;
16
+ }
17
+ setDescription(desc) {
18
+ this.object.description = desc;
19
+ return this;
20
+ }
21
+ setMeta(metadata) {
22
+ this.object.metadata = metadata;
23
+ return this;
24
+ }
25
+ setPath(path) {
26
+ this.object.path = path;
27
+ return this;
28
+ }
29
+ setMiddleware(middleware) {
30
+ this.object.middleware = middleware;
31
+ return this;
32
+ }
33
+ setKey(key) {
34
+ this.object.key = key;
35
+ return this;
36
+ }
37
+ setId(key) {
38
+ this.object.id = key;
39
+ return this;
40
+ }
41
+ setRun(run) {
42
+ this.object.run = run;
43
+ return this;
44
+ }
45
+ define(run) {
46
+ this.object.run = run;
47
+ return this;
48
+ }
49
+ createRoute() {
50
+ this.app.route(this.object).addTo(this.app);
51
+ return this;
52
+ }
53
+ }
54
+ const util = {
55
+ getChain: (obj, opts) => {
56
+ return new Chain(obj, opts);
57
+ },
58
+ };
59
+ class QueryUtil {
60
+ routeObject;
61
+ app;
62
+ constructor(object, opts) {
63
+ this.routeObject = object;
64
+ this.app = opts?.app;
65
+ }
66
+ static createFormObj(object, opts) {
67
+ return new QueryUtil(object, opts);
68
+ }
69
+ static create(value, opts) {
70
+ const obj = value;
71
+ return new QueryUtil(obj, opts);
72
+ }
73
+ get(key) {
74
+ return this.routeObject[key];
75
+ }
76
+ chain(key, opts) {
77
+ const obj = this.routeObject[key];
78
+ let newOpts = { app: this.app, ...opts };
79
+ return new Chain(obj, newOpts);
80
+ }
81
+ queryChain(key) {
82
+ const value = this.routeObject[key];
83
+ return (queryData) => {
84
+ return {
85
+ ...value,
86
+ ...queryData,
87
+ };
88
+ };
89
+ }
90
+ }
91
+
92
+ export { QueryUtil, define, util };
@@ -1,6 +1,6 @@
1
1
  import * as querystring from 'querystring';
2
2
  import { Key } from 'path-to-regexp';
3
- import { IncomingMessage, ServerResponse } from 'http';
3
+ import { IncomingMessage, ServerResponse } from 'node:http';
4
4
 
5
5
  type Req = IncomingMessage & {
6
6
  params?: Record<string, string>;
package/dist/router.d.ts CHANGED
@@ -113,6 +113,11 @@ type RouteContext<T = {
113
113
  } & T;
114
114
  type Run<T = any> = (ctx: RouteContext<T>) => Promise<typeof ctx | null | void>;
115
115
  type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
116
+ type RouteMiddleware = {
117
+ path: string;
118
+ key?: string;
119
+ id?: string;
120
+ } | string;
116
121
  type RouteOpts = {
117
122
  path?: string;
118
123
  key?: string;
@@ -123,7 +128,7 @@ type RouteOpts = {
123
128
  metadata?: {
124
129
  [key: string]: any;
125
130
  };
126
- middleware?: Route[] | string[];
131
+ middleware?: RouteMiddleware[];
127
132
  type?: 'route' | 'middleware';
128
133
  /**
129
134
  * validator: {
@@ -146,6 +151,10 @@ type RouteOpts = {
146
151
  * $#$ will be used to split path and key
147
152
  */
148
153
  idUsePath?: boolean;
154
+ /**
155
+ * id 合并的分隔符,默认为 $#$
156
+ */
157
+ delimiter?: string;
149
158
  isDebug?: boolean;
150
159
  };
151
160
  type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -170,7 +179,7 @@ declare class Route<U = {
170
179
  metadata?: {
171
180
  [key: string]: any;
172
181
  };
173
- middleware?: (Route | string)[];
182
+ middleware?: RouteMiddleware[];
174
183
  type?: string;
175
184
  private _validator?;
176
185
  schema?: {
@@ -524,6 +533,12 @@ declare class CustomError extends Error {
524
533
  message: string;
525
534
  tips: string;
526
535
  };
536
+ /**
537
+ * 判断 throw 的错误是否不是当前这个错误
538
+ * @param err
539
+ * @returns
540
+ */
541
+ static isError(err: any): boolean;
527
542
  parse(e?: CustomError): {
528
543
  code: number;
529
544
  data: any;
@@ -633,4 +648,4 @@ declare class App<T = {}, U = AppReqRes> {
633
648
  }
634
649
 
635
650
  export { App, Connect, CustomError, QueryConnect, QueryRouter, QueryRouterServer, Route, Server, createSchema, handleServer };
636
- export type { RouteContext, RouteOpts, Rule, Run };
651
+ export type { RouteContext, RouteMiddleware, RouteOpts, Rule, Run };
package/dist/router.js CHANGED
@@ -73,11 +73,23 @@ class CustomError extends Error {
73
73
  tips: e?.tips,
74
74
  };
75
75
  }
76
+ /**
77
+ * 判断 throw 的错误是否不是当前这个错误
78
+ * @param err
79
+ * @returns
80
+ */
81
+ static isError(err) {
82
+ if (err instanceof CustomError || err?.code) {
83
+ return true;
84
+ }
85
+ return false;
86
+ }
76
87
  parse(e) {
77
88
  if (e) {
78
89
  return CustomError.parseError(e);
79
90
  }
80
91
  else {
92
+ const e = this;
81
93
  return {
82
94
  code: e?.code,
83
95
  data: e?.data,
@@ -5678,7 +5690,8 @@ class Route {
5678
5690
  if (opts) {
5679
5691
  this.id = opts.id || nanoid();
5680
5692
  if (!opts.id && opts.idUsePath) {
5681
- this.id = path + '$#$' + key;
5693
+ const delimiter = opts.delimiter ?? '$#$';
5694
+ this.id = path + delimiter + key;
5682
5695
  }
5683
5696
  this.run = opts.run;
5684
5697
  this.nextRoute = opts.nextRoute;
@@ -5920,7 +5933,15 @@ class QueryRouter {
5920
5933
  route = this.routes.find((r) => r.id === item);
5921
5934
  }
5922
5935
  else {
5923
- route = this.routes.find((r) => r.path === item.path && r.key === item.key);
5936
+ route = this.routes.find((r) => {
5937
+ if (item.id) {
5938
+ return r.id === item.id;
5939
+ }
5940
+ else {
5941
+ // key 可以是空,所以可以不严格验证
5942
+ return r.path === item.path && r.key == item.key;
5943
+ }
5944
+ });
5924
5945
  }
5925
5946
  if (!route) {
5926
5947
  if (isString) {
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.14",
4
+ "version": "0.0.16",
5
5
  "description": "",
6
6
  "type": "module",
7
7
  "main": "./dist/router.js",
@@ -74,6 +74,11 @@
74
74
  "require": "./dist/router-simple.js",
75
75
  "types": "./dist/router-simple.d.ts"
76
76
  },
77
+ "./define": {
78
+ "import": "./dist/router-define.js",
79
+ "require": "./dist/router-define.js",
80
+ "types": "./dist/router-define.d.ts"
81
+ },
77
82
  "./simple-lib": {
78
83
  "import": "./dist/router-simple-lib.js",
79
84
  "require": "./dist/router-simple-lib.js",
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { Route, QueryRouter, QueryRouterServer } from './route.ts';
2
2
  export { Connect, QueryConnect } from './connect.ts';
3
3
 
4
- export type { RouteContext, RouteOpts } from './route.ts';
4
+ export type { RouteContext, RouteOpts, RouteMiddleware } from './route.ts';
5
5
 
6
6
  export type { Run } from './route.ts';
7
7
 
@@ -35,10 +35,22 @@ export class CustomError extends Error {
35
35
  tips: e?.tips,
36
36
  };
37
37
  }
38
+ /**
39
+ * 判断 throw 的错误是否不是当前这个错误
40
+ * @param err
41
+ * @returns
42
+ */
43
+ static isError(err: any) {
44
+ if (err instanceof CustomError || err?.code) {
45
+ return true;
46
+ }
47
+ return false;
48
+ }
38
49
  parse(e?: CustomError) {
39
50
  if (e) {
40
51
  return CustomError.parseError(e);
41
52
  } else {
53
+ const e = this;
42
54
  return {
43
55
  code: e?.code,
44
56
  data: e?.data,
package/src/route.ts CHANGED
@@ -61,6 +61,13 @@ export type RouteContext<T = { code?: number }, S = any> = {
61
61
  export type Run<T = any> = (ctx: RouteContext<T>) => Promise<typeof ctx | null | void>;
62
62
 
63
63
  export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
64
+ export type RouteMiddleware =
65
+ | {
66
+ path: string;
67
+ key?: string;
68
+ id?: string;
69
+ }
70
+ | string;
64
71
  export type RouteOpts = {
65
72
  path?: string;
66
73
  key?: string;
@@ -69,7 +76,7 @@ export type RouteOpts = {
69
76
  nextRoute?: NextRoute; // route to run after this route
70
77
  description?: string;
71
78
  metadata?: { [key: string]: any };
72
- middleware?: Route[] | string[]; // middleware
79
+ middleware?: RouteMiddleware[]; // middleware
73
80
  type?: 'route' | 'middleware';
74
81
  /**
75
82
  * validator: {
@@ -88,6 +95,10 @@ export type RouteOpts = {
88
95
  * $#$ will be used to split path and key
89
96
  */
90
97
  idUsePath?: boolean;
98
+ /**
99
+ * id 合并的分隔符,默认为 $#$
100
+ */
101
+ delimiter?: string;
91
102
  isDebug?: boolean;
92
103
  };
93
104
  export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -108,7 +119,7 @@ export class Route<U = { [key: string]: any }> {
108
119
  nextRoute?: NextRoute; // route to run after this route
109
120
  description?: string;
110
121
  metadata?: { [key: string]: any };
111
- middleware?: (Route | string)[]; // middleware
122
+ middleware?: RouteMiddleware[]; // middleware
112
123
  type? = 'route';
113
124
  private _validator?: { [key: string]: Rule };
114
125
  schema?: { [key: string]: Schema<any> };
@@ -129,7 +140,8 @@ export class Route<U = { [key: string]: any }> {
129
140
  if (opts) {
130
141
  this.id = opts.id || nanoid();
131
142
  if (!opts.id && opts.idUsePath) {
132
- this.id = path + '$#$' + key;
143
+ const delimiter = opts.delimiter ?? '$#$';
144
+ this.id = path + delimiter + key;
133
145
  }
134
146
  this.run = opts.run;
135
147
  this.nextRoute = opts.nextRoute;
@@ -374,7 +386,14 @@ export class QueryRouter {
374
386
  if (isString) {
375
387
  route = this.routes.find((r) => r.id === item);
376
388
  } else {
377
- route = this.routes.find((r) => r.path === item.path && r.key === item.key);
389
+ route = this.routes.find((r) => {
390
+ if (item.id) {
391
+ return r.id === item.id;
392
+ } else {
393
+ // key 可以是空,所以可以不严格验证
394
+ return r.path === item.path && r.key == item.key;
395
+ }
396
+ });
378
397
  }
379
398
  if (!route) {
380
399
  if (isString) {
@@ -0,0 +1,111 @@
1
+ // import type { QueryRouterServer, Route, RouteOpts, Run } from '@kevisual/router';
2
+ import type { QueryRouterServer, RouteOpts, Run, RouteMiddleware } from './index.ts';
3
+
4
+ // export type RouteObject<T extends readonly string[]> = {
5
+ // [K in T[number]]: RouteOpts;
6
+ // };
7
+ export type { RouteOpts };
8
+ export type RouteObject = {
9
+ [key: string]: RouteOpts;
10
+ };
11
+
12
+ export function define<T extends Record<string, RouteOpts>>(
13
+ value: T,
14
+ ): {
15
+ [K in keyof T]: T[K] & RouteOpts;
16
+ } {
17
+ return value as { [K in keyof T]: T[K] & RouteOpts };
18
+ }
19
+
20
+ export type RouteArray = RouteOpts[];
21
+ type ChainOptions = {
22
+ app: QueryRouterServer;
23
+ };
24
+ class Chain {
25
+ object: RouteOpts;
26
+ app?: QueryRouterServer;
27
+ constructor(object: RouteOpts, opts?: ChainOptions) {
28
+ this.object = object;
29
+ this.app = opts?.app;
30
+ }
31
+ get key() {
32
+ return this.object.key;
33
+ }
34
+ get path() {
35
+ return this.object.path;
36
+ }
37
+ setDescription(desc: string) {
38
+ this.object.description = desc;
39
+ return this;
40
+ }
41
+ setMeta(metadata: { [key: string]: any }) {
42
+ this.object.metadata = metadata;
43
+ return this;
44
+ }
45
+ setPath(path: string) {
46
+ this.object.path = path;
47
+ return this;
48
+ }
49
+ setMiddleware(middleware: RouteMiddleware[]) {
50
+ this.object.middleware = middleware;
51
+ return this;
52
+ }
53
+ setKey(key: string) {
54
+ this.object.key = key;
55
+ return this;
56
+ }
57
+ setId(key: string) {
58
+ this.object.id = key;
59
+ return this;
60
+ }
61
+ setRun(run: Run) {
62
+ this.object.run = run;
63
+ return this;
64
+ }
65
+ define(run: Run) {
66
+ this.object.run = run;
67
+ return this;
68
+ }
69
+ createRoute() {
70
+ this.app.route(this.object).addTo(this.app);
71
+ return this;
72
+ }
73
+ }
74
+ export const util = {
75
+ getChain: (obj: RouteOpts, opts?: ChainOptions) => {
76
+ return new Chain(obj, opts);
77
+ },
78
+ };
79
+
80
+ export class QueryUtil<T extends RouteObject = RouteObject> {
81
+ routeObject: T;
82
+ app: QueryRouterServer;
83
+ constructor(object: T, opts?: ChainOptions) {
84
+ this.routeObject = object;
85
+ this.app = opts?.app;
86
+ }
87
+ static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions) {
88
+ return new QueryUtil<U>(object, opts);
89
+ }
90
+ static create<U extends Record<string, RouteOpts>>(value: U, opts?: ChainOptions) {
91
+ const obj = value as { [K in keyof U]: U[K] & RouteOpts };
92
+ return new QueryUtil<U>(obj, opts);
93
+ }
94
+ get<K extends keyof T>(key: K): RouteOpts {
95
+ return this.routeObject[key] as RouteOpts;
96
+ }
97
+ chain<K extends keyof T>(key: K, opts?: ChainOptions) {
98
+ const obj = this.routeObject[key];
99
+ let newOpts = { app: this.app, ...opts };
100
+ return new Chain(obj, newOpts);
101
+ }
102
+ queryChain<K extends keyof T>(key: K) {
103
+ const value = this.routeObject[key] as RouteOpts;
104
+ return (queryData?: Record<string, any>) => {
105
+ return {
106
+ ...value,
107
+ ...queryData,
108
+ };
109
+ };
110
+ }
111
+ }
@@ -1,5 +1,5 @@
1
1
  import { pathToRegexp, Key } from 'path-to-regexp';
2
- import type { IncomingMessage, ServerResponse } from 'http';
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
3
  import { parseBody, parseSearch } from './server/parse-body.ts';
4
4
 
5
5
  type Req = IncomingMessage & { params?: Record<string, string> };
@@ -0,0 +1,10 @@
1
+ import { App } from '@/app.ts';
2
+ import { QueryUtil } from '@/router-define.ts';
3
+ const v = QueryUtil.create({
4
+ a: {
5
+ path: 'a',
6
+ key: 'b',
7
+ },
8
+ });
9
+ const app = new App();
10
+ app.route(v.get('a'));