@kevisual/router 0.0.13 → 0.0.15

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.
@@ -1,5 +1,7 @@
1
1
  import { Schema } from 'zod';
2
2
  export { Schema } from 'zod';
3
+ import * as querystring from 'querystring';
4
+ import { IncomingMessage } from 'node:http';
3
5
 
4
6
  type BaseRule = {
5
7
  value?: any;
@@ -141,6 +143,10 @@ type RouteOpts = {
141
143
  * $#$ will be used to split path and key
142
144
  */
143
145
  idUsePath?: boolean;
146
+ /**
147
+ * id 合并的分隔符,默认为 $#$
148
+ */
149
+ delimiter?: string;
144
150
  isDebug?: boolean;
145
151
  };
146
152
  type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -312,6 +318,9 @@ declare class QueryRouter {
312
318
  }>;
313
319
  setContext(ctx: RouteContext): Promise<void>;
314
320
  getList(): RouteInfo[];
321
+ /**
322
+ * 获取handle函数, 这里会去执行parse函数
323
+ */
315
324
  getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext): (msg: {
316
325
  path: string;
317
326
  key?: string;
@@ -398,6 +407,12 @@ declare class CustomError extends Error {
398
407
  message: string;
399
408
  tips: string;
400
409
  };
410
+ /**
411
+ * 判断 throw 的错误是否不是当前这个错误
412
+ * @param err
413
+ * @returns
414
+ */
415
+ static isError(err: any): boolean;
401
416
  parse(e?: CustomError): {
402
417
  code: number;
403
418
  data: any;
@@ -406,5 +421,15 @@ declare class CustomError extends Error {
406
421
  };
407
422
  }
408
423
 
409
- export { CustomError, QueryRouter, QueryRouterServer, Route, createSchema };
424
+ declare const parseBody: <T = Record<string, any>>(req: IncomingMessage) => Promise<T>;
425
+ declare const parseSearch: (req: IncomingMessage) => querystring.ParsedUrlQuery;
426
+ /**
427
+ * 把url当个key 的 value 的字符串转成json
428
+ * @param value
429
+ */
430
+ declare const parseSearchValue: (value?: string, opts?: {
431
+ decode?: boolean;
432
+ }) => any;
433
+
434
+ export { CustomError, QueryRouter, QueryRouterServer, Route, createSchema, parseBody, parseSearch, parseSearchValue };
410
435
  export type { RouteContext, RouteOpts, Rule, Run };
@@ -1,3 +1,5 @@
1
+ import url from 'node:url';
2
+
1
3
  const urlAlphabet =
2
4
  'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
3
5
 
@@ -49,11 +51,23 @@ class CustomError extends Error {
49
51
  tips: e?.tips,
50
52
  };
51
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
+ }
52
65
  parse(e) {
53
66
  if (e) {
54
67
  return CustomError.parseError(e);
55
68
  }
56
69
  else {
70
+ const e = this;
57
71
  return {
58
72
  code: e?.code,
59
73
  data: e?.data,
@@ -5654,7 +5668,8 @@ class Route {
5654
5668
  if (opts) {
5655
5669
  this.id = opts.id || nanoid();
5656
5670
  if (!opts.id && opts.idUsePath) {
5657
- this.id = path + '$#$' + key;
5671
+ const delimiter = opts.delimiter ?? '$#$';
5672
+ this.id = path + delimiter + key;
5658
5673
  }
5659
5674
  this.run = opts.run;
5660
5675
  this.nextRoute = opts.nextRoute;
@@ -6125,6 +6140,9 @@ class QueryRouter {
6125
6140
  return pick(r, pickValue);
6126
6141
  });
6127
6142
  }
6143
+ /**
6144
+ * 获取handle函数, 这里会去执行parse函数
6145
+ */
6128
6146
  getHandle(router, wrapperFn, ctx) {
6129
6147
  return async (msg, handleContext) => {
6130
6148
  try {
@@ -6233,4 +6251,44 @@ class QueryRouterServer extends QueryRouter {
6233
6251
  }
6234
6252
  }
6235
6253
 
6236
- export { CustomError, QueryRouter, QueryRouterServer, Route, ZodType as Schema, createSchema };
6254
+ const parseBody = async (req) => {
6255
+ return new Promise((resolve, reject) => {
6256
+ const arr = [];
6257
+ req.on('data', (chunk) => {
6258
+ arr.push(chunk);
6259
+ });
6260
+ req.on('end', () => {
6261
+ try {
6262
+ const body = Buffer.concat(arr).toString();
6263
+ resolve(JSON.parse(body));
6264
+ }
6265
+ catch (e) {
6266
+ resolve({});
6267
+ }
6268
+ });
6269
+ });
6270
+ };
6271
+ const parseSearch = (req) => {
6272
+ const parsedUrl = url.parse(req.url, true);
6273
+ return parsedUrl.query;
6274
+ };
6275
+ /**
6276
+ * 把url当个key 的 value 的字符串转成json
6277
+ * @param value
6278
+ */
6279
+ const parseSearchValue = (value, opts) => {
6280
+ if (!value)
6281
+ return {};
6282
+ const decode = opts?.decode ?? false;
6283
+ if (decode) {
6284
+ value = decodeURIComponent(value);
6285
+ }
6286
+ try {
6287
+ return JSON.parse(value);
6288
+ }
6289
+ catch (e) {
6290
+ return {};
6291
+ }
6292
+ };
6293
+
6294
+ export { CustomError, QueryRouter, QueryRouterServer, Route, ZodType as Schema, createSchema, parseBody, parseSearch, parseSearchValue };
@@ -0,0 +1,459 @@
1
+ import * as zod from 'zod';
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 RouteOpts = {
111
+ path?: string;
112
+ key?: string;
113
+ id?: string;
114
+ run?: Run;
115
+ nextRoute?: NextRoute;
116
+ description?: string;
117
+ metadata?: {
118
+ [key: string]: any;
119
+ };
120
+ middleware?: Route[] | string[];
121
+ type?: 'route' | 'middleware';
122
+ /**
123
+ * validator: {
124
+ * packageName: {
125
+ * type: 'string',
126
+ * required: true,
127
+ * },
128
+ * }
129
+ */
130
+ validator?: {
131
+ [key: string]: Rule;
132
+ };
133
+ schema?: {
134
+ [key: string]: Schema<any>;
135
+ };
136
+ isVerify?: boolean;
137
+ verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
138
+ verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
139
+ /**
140
+ * $#$ will be used to split path and key
141
+ */
142
+ idUsePath?: boolean;
143
+ /**
144
+ * id 合并的分隔符,默认为 $#$
145
+ */
146
+ delimiter?: string;
147
+ isDebug?: boolean;
148
+ };
149
+ type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
150
+ declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
151
+ type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
152
+ declare class Route<U = {
153
+ [key: string]: any;
154
+ }> {
155
+ /**
156
+ * 一级路径
157
+ */
158
+ path?: string;
159
+ /**
160
+ * 二级路径
161
+ */
162
+ key?: string;
163
+ id?: string;
164
+ share?: boolean;
165
+ run?: Run;
166
+ nextRoute?: NextRoute;
167
+ description?: string;
168
+ metadata?: {
169
+ [key: string]: any;
170
+ };
171
+ middleware?: (Route | string)[];
172
+ type?: string;
173
+ private _validator?;
174
+ schema?: {
175
+ [key: string]: Schema<any>;
176
+ };
177
+ data?: any;
178
+ /**
179
+ * 是否需要验证
180
+ */
181
+ isVerify?: boolean;
182
+ /**
183
+ * 是否开启debug,开启后会打印错误信息
184
+ */
185
+ isDebug?: boolean;
186
+ constructor(path: string, key?: string, opts?: RouteOpts);
187
+ private createSchema;
188
+ /**
189
+ * set validator and create schema
190
+ * @param validator
191
+ */
192
+ set validator(validator: {
193
+ [key: string]: Rule;
194
+ });
195
+ get validator(): {
196
+ [key: string]: Rule;
197
+ };
198
+ /**
199
+ * has code, body, message in ctx, return ctx if has error
200
+ * @param ctx
201
+ * @param dev
202
+ * @returns
203
+ */
204
+ verify(ctx: RouteContext, dev?: boolean): void;
205
+ /**
206
+ * Need to manully call return ctx fn and configure body, code, message
207
+ * @param key
208
+ * @param ctx
209
+ * @param dev
210
+ * @returns
211
+ */
212
+ verifyKey(key: string, ctx: RouteContext, dev?: boolean): {
213
+ message: string;
214
+ path: string;
215
+ key: string;
216
+ error: any;
217
+ } | {
218
+ message: string;
219
+ path: string;
220
+ key: string;
221
+ error?: undefined;
222
+ };
223
+ setValidator(validator: {
224
+ [key: string]: Rule;
225
+ }): this;
226
+ define<T extends {
227
+ [key: string]: any;
228
+ } = RouterContextT>(opts: DefineRouteOpts): this;
229
+ define<T extends {
230
+ [key: string]: any;
231
+ } = RouterContextT>(fn: Run<T & U>): this;
232
+ define<T extends {
233
+ [key: string]: any;
234
+ } = RouterContextT>(key: string, fn: Run<T & U>): this;
235
+ define<T extends {
236
+ [key: string]: any;
237
+ } = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
238
+ addTo(router: QueryRouter | {
239
+ add: (route: Route) => void;
240
+ [key: string]: any;
241
+ }): void;
242
+ setData(data: any): this;
243
+ throw(code?: number | string, message?: string, tips?: string): void;
244
+ }
245
+ declare class QueryRouter {
246
+ routes: Route[];
247
+ maxNextRoute: number;
248
+ context?: RouteContext;
249
+ constructor();
250
+ add(route: Route): void;
251
+ /**
252
+ * remove route by path and key
253
+ * @param route
254
+ */
255
+ remove(route: Route | {
256
+ path: string;
257
+ key?: string;
258
+ }): void;
259
+ /**
260
+ * remove route by id
261
+ * @param uniqueId
262
+ */
263
+ removeById(unique: string): void;
264
+ /**
265
+ * 执行route
266
+ * @param path
267
+ * @param key
268
+ * @param ctx
269
+ * @returns
270
+ */
271
+ runRoute(path: string, key: string, ctx?: RouteContext): any;
272
+ /**
273
+ * 第一次执行
274
+ * @param message
275
+ * @param ctx
276
+ * @returns
277
+ */
278
+ parse(message: {
279
+ path: string;
280
+ key?: string;
281
+ payload?: any;
282
+ }, ctx?: RouteContext & {
283
+ [key: string]: any;
284
+ }): Promise<any>;
285
+ /**
286
+ * 返回的数据包含所有的context的请求返回的内容,可做其他处理
287
+ * @param message
288
+ * @param ctx
289
+ * @returns
290
+ */
291
+ call(message: {
292
+ id?: string;
293
+ path?: string;
294
+ key?: string;
295
+ payload?: any;
296
+ }, ctx?: RouteContext & {
297
+ [key: string]: any;
298
+ }): Promise<any>;
299
+ /**
300
+ * 请求 result 的数据
301
+ * @param message
302
+ * @param ctx
303
+ * @returns
304
+ */
305
+ queryRoute(message: {
306
+ path: string;
307
+ key?: string;
308
+ payload?: any;
309
+ }, ctx?: RouteContext & {
310
+ [key: string]: any;
311
+ }): Promise<{
312
+ code: any;
313
+ data: any;
314
+ message: any;
315
+ }>;
316
+ setContext(ctx: RouteContext): Promise<void>;
317
+ getList(): RouteInfo[];
318
+ /**
319
+ * 获取handle函数, 这里会去执行parse函数
320
+ */
321
+ getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext): (msg: {
322
+ path: string;
323
+ key?: string;
324
+ [key: string]: any;
325
+ }, handleContext?: RouteContext) => Promise<{
326
+ [key: string]: any;
327
+ code: string;
328
+ data?: any;
329
+ message?: string;
330
+ } | {
331
+ code: any;
332
+ data: any;
333
+ message: any;
334
+ } | {
335
+ code: number;
336
+ message: any;
337
+ data?: undefined;
338
+ }>;
339
+ exportRoutes(): Route<{
340
+ [key: string]: any;
341
+ }>[];
342
+ importRoutes(routes: Route[]): void;
343
+ importRouter(router: QueryRouter): void;
344
+ throw(code?: number | string, message?: string, tips?: string): void;
345
+ hasRoute(path: string, key?: string): Route<{
346
+ [key: string]: any;
347
+ }>;
348
+ }
349
+ type QueryRouterServerOpts = {
350
+ handleFn?: HandleFn;
351
+ context?: RouteContext;
352
+ };
353
+ interface HandleFn<T = any> {
354
+ (msg: {
355
+ path: string;
356
+ [key: string]: any;
357
+ }, ctx?: any): {
358
+ code: string;
359
+ data?: any;
360
+ message?: string;
361
+ [key: string]: any;
362
+ };
363
+ (res: RouteContext<T>): any;
364
+ }
365
+ /**
366
+ * QueryRouterServer
367
+ * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
368
+ */
369
+ declare class QueryRouterServer extends QueryRouter {
370
+ handle: any;
371
+ constructor(opts?: QueryRouterServerOpts);
372
+ setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void;
373
+ use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void;
374
+ addRoute(route: Route): void;
375
+ Route: typeof Route;
376
+ route(opts: RouteOpts): Route<Required<RouteContext>>;
377
+ route(path: string, key?: string): Route<Required<RouteContext>>;
378
+ route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
379
+ route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
380
+ /**
381
+ * 等于queryRoute,但是调用了handle
382
+ * @param param0
383
+ * @returns
384
+ */
385
+ run({ path, key, payload }: {
386
+ path: string;
387
+ key?: string;
388
+ payload?: any;
389
+ }): Promise<any>;
390
+ }
391
+
392
+ type RouteObject = {
393
+ [key: string]: RouteOpts;
394
+ };
395
+ declare function define<T extends Record<string, RouteOpts>>(value: T): {
396
+ [K in keyof T]: T[K] & RouteOpts;
397
+ };
398
+ type RouteArray = RouteOpts[];
399
+ type ChainOptions = {
400
+ app: QueryRouterServer;
401
+ };
402
+ declare class Chain {
403
+ object: RouteOpts;
404
+ app?: QueryRouterServer;
405
+ constructor(object: RouteOpts, opts?: ChainOptions);
406
+ get key(): string;
407
+ get path(): string;
408
+ setDescription(desc: string): this;
409
+ setMeta(metadata: {
410
+ [key: string]: any;
411
+ }): this;
412
+ setPath(path: string): this;
413
+ setMiddleware(middleware: string[] | Route[]): this;
414
+ setKey(key: string): this;
415
+ setId(key: string): this;
416
+ setRun(run: Run): this;
417
+ define(run: Run): this;
418
+ createRoute(): this;
419
+ }
420
+ declare const util: {
421
+ getChain: (obj: RouteOpts, opts?: ChainOptions) => Chain;
422
+ };
423
+ declare class QueryUtil<T extends RouteObject = RouteObject> {
424
+ routeObject: T;
425
+ app: QueryRouterServer;
426
+ constructor(object: T, opts?: ChainOptions);
427
+ static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions): QueryUtil<U>;
428
+ static create<U extends Record<string, RouteOpts>>(value: U, opts?: ChainOptions): QueryUtil<U>;
429
+ get<K extends keyof T>(key: K): RouteOpts;
430
+ chain<K extends keyof T>(key: K, opts?: ChainOptions): Chain;
431
+ queryChain<K extends keyof T>(key: K): (queryData?: Record<string, any>) => {
432
+ path?: string;
433
+ key?: string;
434
+ id?: string;
435
+ run?: Run;
436
+ nextRoute?: NextRoute;
437
+ description?: string;
438
+ metadata?: {
439
+ [key: string]: any;
440
+ };
441
+ middleware?: Route[] | string[];
442
+ type?: "route" | "middleware";
443
+ validator?: {
444
+ [key: string]: Rule;
445
+ };
446
+ schema?: {
447
+ [key: string]: zod.ZodType<any>;
448
+ };
449
+ isVerify?: boolean;
450
+ verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
451
+ verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
452
+ idUsePath?: boolean;
453
+ delimiter?: string;
454
+ isDebug?: boolean;
455
+ };
456
+ }
457
+
458
+ export { QueryUtil, define, util };
459
+ 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
@@ -146,6 +146,10 @@ type RouteOpts = {
146
146
  * $#$ will be used to split path and key
147
147
  */
148
148
  idUsePath?: boolean;
149
+ /**
150
+ * id 合并的分隔符,默认为 $#$
151
+ */
152
+ delimiter?: string;
149
153
  isDebug?: boolean;
150
154
  };
151
155
  type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -317,6 +321,9 @@ declare class QueryRouter {
317
321
  }>;
318
322
  setContext(ctx: RouteContext): Promise<void>;
319
323
  getList(): RouteInfo[];
324
+ /**
325
+ * 获取handle函数, 这里会去执行parse函数
326
+ */
320
327
  getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext): (msg: {
321
328
  path: string;
322
329
  key?: string;
@@ -521,6 +528,12 @@ declare class CustomError extends Error {
521
528
  message: string;
522
529
  tips: string;
523
530
  };
531
+ /**
532
+ * 判断 throw 的错误是否不是当前这个错误
533
+ * @param err
534
+ * @returns
535
+ */
536
+ static isError(err: any): boolean;
524
537
  parse(e?: CustomError): {
525
538
  code: number;
526
539
  data: any;
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;
@@ -6149,6 +6162,9 @@ class QueryRouter {
6149
6162
  return pick(r, pickValue);
6150
6163
  });
6151
6164
  }
6165
+ /**
6166
+ * 获取handle函数, 这里会去执行parse函数
6167
+ */
6152
6168
  getHandle(router, wrapperFn, ctx) {
6153
6169
  return async (msg, handleContext) => {
6154
6170
  try {
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.13",
4
+ "version": "0.0.15",
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/browser.ts CHANGED
@@ -7,3 +7,5 @@ export type { RouteContext, RouteOpts } from './route.ts';
7
7
  export type { Run } from './route.ts';
8
8
 
9
9
  export { CustomError } from './result/error.ts';
10
+
11
+ export * from './server/parse-body.ts';
@@ -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
@@ -88,6 +88,10 @@ export type RouteOpts = {
88
88
  * $#$ will be used to split path and key
89
89
  */
90
90
  idUsePath?: boolean;
91
+ /**
92
+ * id 合并的分隔符,默认为 $#$
93
+ */
94
+ delimiter?: string;
91
95
  isDebug?: boolean;
92
96
  };
93
97
  export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
@@ -129,7 +133,8 @@ export class Route<U = { [key: string]: any }> {
129
133
  if (opts) {
130
134
  this.id = opts.id || nanoid();
131
135
  if (!opts.id && opts.idUsePath) {
132
- this.id = path + '$#$' + key;
136
+ const delimiter = opts.delimiter ?? '$#$';
137
+ this.id = path + delimiter + key;
133
138
  }
134
139
  this.run = opts.run;
135
140
  this.nextRoute = opts.nextRoute;
@@ -592,6 +597,9 @@ export class QueryRouter {
592
597
  return pick(r, pickValue as any);
593
598
  });
594
599
  }
600
+ /**
601
+ * 获取handle函数, 这里会去执行parse函数
602
+ */
595
603
  getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext) {
596
604
  return async (msg: { path: string; key?: string; [key: string]: any }, handleContext?: RouteContext) => {
597
605
  try {
@@ -0,0 +1,110 @@
1
+ import type { QueryRouterServer, Route, RouteOpts, Run } from './route.ts';
2
+
3
+ // export type RouteObject<T extends readonly string[]> = {
4
+ // [K in T[number]]: RouteOpts;
5
+ // };
6
+ export type { RouteOpts };
7
+ export type RouteObject = {
8
+ [key: string]: RouteOpts;
9
+ };
10
+
11
+ export function define<T extends Record<string, RouteOpts>>(
12
+ value: T,
13
+ ): {
14
+ [K in keyof T]: T[K] & RouteOpts;
15
+ } {
16
+ return value as { [K in keyof T]: T[K] & RouteOpts };
17
+ }
18
+
19
+ export type RouteArray = RouteOpts[];
20
+ type ChainOptions = {
21
+ app: QueryRouterServer;
22
+ };
23
+ class Chain {
24
+ object: RouteOpts;
25
+ app?: QueryRouterServer;
26
+ constructor(object: RouteOpts, opts?: ChainOptions) {
27
+ this.object = object;
28
+ this.app = opts?.app;
29
+ }
30
+ get key() {
31
+ return this.object.key;
32
+ }
33
+ get path() {
34
+ return this.object.path;
35
+ }
36
+ setDescription(desc: string) {
37
+ this.object.description = desc;
38
+ return this;
39
+ }
40
+ setMeta(metadata: { [key: string]: any }) {
41
+ this.object.metadata = metadata;
42
+ return this;
43
+ }
44
+ setPath(path: string) {
45
+ this.object.path = path;
46
+ return this;
47
+ }
48
+ setMiddleware(middleware: string[] | Route[]) {
49
+ this.object.middleware = middleware;
50
+ return this;
51
+ }
52
+ setKey(key: string) {
53
+ this.object.key = key;
54
+ return this;
55
+ }
56
+ setId(key: string) {
57
+ this.object.id = key;
58
+ return this;
59
+ }
60
+ setRun(run: Run) {
61
+ this.object.run = run;
62
+ return this;
63
+ }
64
+ define(run: Run) {
65
+ this.object.run = run;
66
+ return this;
67
+ }
68
+ createRoute() {
69
+ this.app.route(this.object).addTo(this.app);
70
+ return this;
71
+ }
72
+ }
73
+ export const util = {
74
+ getChain: (obj: RouteOpts, opts?: ChainOptions) => {
75
+ return new Chain(obj, opts);
76
+ },
77
+ };
78
+
79
+ export class QueryUtil<T extends RouteObject = RouteObject> {
80
+ routeObject: T;
81
+ app: QueryRouterServer;
82
+ constructor(object: T, opts?: ChainOptions) {
83
+ this.routeObject = object;
84
+ this.app = opts?.app;
85
+ }
86
+ static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions) {
87
+ return new QueryUtil<U>(object, opts);
88
+ }
89
+ static create<U extends Record<string, RouteOpts>>(value: U, opts?: ChainOptions) {
90
+ const obj = value as { [K in keyof U]: U[K] & RouteOpts };
91
+ return new QueryUtil<U>(obj, opts);
92
+ }
93
+ get<K extends keyof T>(key: K): RouteOpts {
94
+ return this.routeObject[key] as RouteOpts;
95
+ }
96
+ chain<K extends keyof T>(key: K, opts?: ChainOptions) {
97
+ const obj = this.routeObject[key];
98
+ let newOpts = { app: this.app, ...opts };
99
+ return new Chain(obj, newOpts);
100
+ }
101
+ queryChain<K extends keyof T>(key: K) {
102
+ const value = this.routeObject[key] as RouteOpts;
103
+ return (queryData?: Record<string, any>) => {
104
+ return {
105
+ ...value,
106
+ ...queryData,
107
+ };
108
+ };
109
+ }
110
+ }
@@ -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> };
@@ -22,3 +22,20 @@ export const parseSearch = (req: IncomingMessage) => {
22
22
  const parsedUrl = url.parse(req.url, true);
23
23
  return parsedUrl.query;
24
24
  };
25
+
26
+ /**
27
+ * 把url当个key 的 value 的字符串转成json
28
+ * @param value
29
+ */
30
+ export const parseSearchValue = (value?: string, opts?: { decode?: boolean }) => {
31
+ if (!value) return {};
32
+ const decode = opts?.decode ?? false;
33
+ if (decode) {
34
+ value = decodeURIComponent(value);
35
+ }
36
+ try {
37
+ return JSON.parse(value);
38
+ } catch (e) {
39
+ return {};
40
+ }
41
+ };