@kevisual/router 0.0.10 → 0.0.12

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/src/route.ts ADDED
@@ -0,0 +1,714 @@
1
+ import { nanoid } from 'nanoid';
2
+ import { CustomError } from './result/error.ts';
3
+ import { Schema, Rule, createSchema } from './validator/index.ts';
4
+ import { pick } from './utils/pick.ts';
5
+ import { get } from 'lodash-es';
6
+
7
+ export type RouterContextT = { code?: number; [key: string]: any };
8
+ export type RouteContext<T = { code?: number }, S = any> = {
9
+ // run first
10
+ query?: { [key: string]: any };
11
+ // response body
12
+ /** return body */
13
+ body?: number | string | Object;
14
+ /** return code */
15
+ code?: number;
16
+ /** return msg */
17
+ message?: string;
18
+ // 传递状态
19
+ state?: S;
20
+ // transfer data
21
+ /**
22
+ * 当前路径
23
+ */
24
+ currentPath?: string;
25
+ /**
26
+ * 当前key
27
+ */
28
+ currentKey?: string;
29
+ /**
30
+ * 当前route
31
+ */
32
+ currentRoute?: Route;
33
+ /**
34
+ * 进度
35
+ */
36
+ progress?: [string, string][];
37
+ // onlyForNextRoute will be clear after next route
38
+ nextQuery?: { [key: string]: any };
39
+ // end
40
+ end?: boolean;
41
+ // 处理router manager
42
+ // TODO:
43
+ /**
44
+ * 请求 route的返回结果,包函ctx
45
+ */
46
+ queryRouter?: QueryRouter;
47
+ error?: any;
48
+ /** 请求 route的返回结果,包函ctx */
49
+ call?: (
50
+ message: { path: string; key?: string; payload?: any; [key: string]: any } | { id: string; apyload?: any; [key: string]: any },
51
+ ctx?: RouteContext & { [key: string]: any },
52
+ ) => Promise<any>;
53
+ /** 请求 route的返回结果,不包函ctx */
54
+ queryRoute?: (message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) => Promise<any>;
55
+ index?: number;
56
+ throw?: (code?: number | string, message?: string, tips?: string) => void;
57
+ /** 是否需要序列化 */
58
+ needSerialize?: boolean;
59
+ } & T;
60
+
61
+ export type Run<T = any> = (ctx: RouteContext<T>) => Promise<typeof ctx | null | void>;
62
+
63
+ export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
64
+ export type RouteOpts = {
65
+ path?: string;
66
+ key?: string;
67
+ id?: string;
68
+ run?: Run;
69
+ nextRoute?: NextRoute; // route to run after this route
70
+ description?: string;
71
+ metadata?: { [key: string]: any };
72
+ middleware?: Route[] | string[]; // middleware
73
+ type?: 'route' | 'middleware';
74
+ /**
75
+ * validator: {
76
+ * packageName: {
77
+ * type: 'string',
78
+ * required: true,
79
+ * },
80
+ * }
81
+ */
82
+ validator?: { [key: string]: Rule };
83
+ schema?: { [key: string]: Schema<any> };
84
+ isVerify?: boolean;
85
+ verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
86
+ verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
87
+ /**
88
+ * $#$ will be used to split path and key
89
+ */
90
+ idUsePath?: boolean;
91
+ isDebug?: boolean;
92
+ };
93
+ export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
94
+ const pickValue = ['path', 'key', 'id', 'description', 'type', 'validator', 'middleware'] as const;
95
+ export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
96
+ export class Route<U = { [key: string]: any }> {
97
+ /**
98
+ * 一级路径
99
+ */
100
+ path?: string;
101
+ /**
102
+ * 二级路径
103
+ */
104
+ key?: string;
105
+ id?: string;
106
+ share? = false;
107
+ run?: Run;
108
+ nextRoute?: NextRoute; // route to run after this route
109
+ description?: string;
110
+ metadata?: { [key: string]: any };
111
+ middleware?: (Route | string)[]; // middleware
112
+ type? = 'route';
113
+ private _validator?: { [key: string]: Rule };
114
+ schema?: { [key: string]: Schema<any> };
115
+ data?: any;
116
+ /**
117
+ * 是否需要验证
118
+ */
119
+ isVerify?: boolean;
120
+ /**
121
+ * 是否开启debug,开启后会打印错误信息
122
+ */
123
+ isDebug?: boolean;
124
+ constructor(path: string, key: string = '', opts?: RouteOpts) {
125
+ path = path.trim();
126
+ key = key.trim();
127
+ this.path = path;
128
+ this.key = key;
129
+ if (opts) {
130
+ this.id = opts.id || nanoid();
131
+ if (!opts.id && opts.idUsePath) {
132
+ this.id = path + '$#$' + key;
133
+ }
134
+ this.run = opts.run;
135
+ this.nextRoute = opts.nextRoute;
136
+ this.description = opts.description;
137
+ this.metadata = opts.metadata;
138
+ this.type = opts.type || 'route';
139
+ this.validator = opts.validator;
140
+ this.middleware = opts.middleware || [];
141
+ this.key = opts.key || key;
142
+ this.path = opts.path || path;
143
+ this.isVerify = opts.isVerify ?? true;
144
+ this.createSchema();
145
+ } else {
146
+ this.isVerify = true;
147
+ this.middleware = [];
148
+ this.id = nanoid();
149
+ }
150
+ this.isDebug = opts?.isDebug ?? false;
151
+ }
152
+ private createSchema() {
153
+ try {
154
+ const validator = this.validator;
155
+ const keys = Object.keys(validator || {});
156
+ const schemaList = keys.map((key) => {
157
+ return { [key]: createSchema(validator[key]) };
158
+ });
159
+ const schema = schemaList.reduce((prev, current) => {
160
+ return { ...prev, ...current };
161
+ }, {});
162
+ this.schema = schema;
163
+ } catch (e) {
164
+ console.error('createSchema error:', e);
165
+ }
166
+ }
167
+
168
+ /**
169
+ * set validator and create schema
170
+ * @param validator
171
+ */
172
+ set validator(validator: { [key: string]: Rule }) {
173
+ this._validator = validator;
174
+ this.createSchema();
175
+ }
176
+ get validator() {
177
+ return this._validator || {};
178
+ }
179
+ /**
180
+ * has code, body, message in ctx, return ctx if has error
181
+ * @param ctx
182
+ * @param dev
183
+ * @returns
184
+ */
185
+ verify(ctx: RouteContext, dev = false) {
186
+ const query = ctx.query || {};
187
+ const schema = this.schema || {};
188
+ const validator = this.validator;
189
+ const check = () => {
190
+ const queryKeys = Object.keys(validator);
191
+ for (let i = 0; i < queryKeys.length; i++) {
192
+ const key = queryKeys[i];
193
+ const value = query[key];
194
+ if (schema[key]) {
195
+ const result = schema[key].safeParse(value);
196
+ if (!result.success) {
197
+ const path = result.error.errors[0]?.path?.join?.('.properties.');
198
+ let message = 'Invalid params';
199
+ if (path) {
200
+ const keyS = `${key}.properties.${path}.message`;
201
+ message = get(validator, keyS, 'Invalid params') as any;
202
+ }
203
+ throw new CustomError(500, message);
204
+ }
205
+ }
206
+ }
207
+ };
208
+ check();
209
+ }
210
+
211
+ /**
212
+ * Need to manully call return ctx fn and configure body, code, message
213
+ * @param key
214
+ * @param ctx
215
+ * @param dev
216
+ * @returns
217
+ */
218
+ verifyKey(key: string, ctx: RouteContext, dev = false) {
219
+ const query = ctx.query || {};
220
+ const schema = this.schema || {};
221
+ const validator = this.validator;
222
+ const check = () => {
223
+ const value = query[key];
224
+ if (schema[key]) {
225
+ try {
226
+ schema[key].parse(value);
227
+ } catch (e) {
228
+ if (dev) {
229
+ return {
230
+ message: validator[key].message || 'Invalid params',
231
+ path: this.path,
232
+ key: this.key,
233
+ error: e.message.toString(),
234
+ };
235
+ }
236
+ return {
237
+ message: validator[key].message || 'Invalid params',
238
+ path: this.path,
239
+ key: this.key,
240
+ };
241
+ }
242
+ }
243
+ };
244
+ const checkRes = check();
245
+ return checkRes;
246
+ }
247
+ setValidator(validator: { [key: string]: Rule }) {
248
+ this.validator = validator;
249
+ return this;
250
+ }
251
+ define<T extends { [key: string]: any } = RouterContextT>(opts: DefineRouteOpts): this;
252
+ define<T extends { [key: string]: any } = RouterContextT>(fn: Run<T & U>): this;
253
+ define<T extends { [key: string]: any } = RouterContextT>(key: string, fn: Run<T & U>): this;
254
+ define<T extends { [key: string]: any } = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
255
+ define(...args: any[]) {
256
+ const [path, key, opts] = args;
257
+ // 全覆盖,所以opts需要准确,不能由idUsePath 需要check的变量
258
+ const setOpts = (opts: DefineRouteOpts) => {
259
+ const keys = Object.keys(opts);
260
+ const checkList = ['path', 'key', 'run', 'nextRoute', 'description', 'metadata', 'middleware', 'type', 'validator', 'isVerify', 'isDebug'];
261
+ for (let item of keys) {
262
+ if (!checkList.includes(item)) {
263
+ continue;
264
+ }
265
+ if (item === 'validator') {
266
+ this.validator = opts[item];
267
+ continue;
268
+ }
269
+ if (item === 'middleware') {
270
+ this.middleware = this.middleware.concat(opts[item]);
271
+ continue;
272
+ }
273
+ this[item] = opts[item];
274
+ }
275
+ };
276
+ if (typeof path === 'object') {
277
+ setOpts(path);
278
+ return this;
279
+ }
280
+ if (typeof path === 'function') {
281
+ this.run = path;
282
+ return this;
283
+ }
284
+ if (typeof path === 'string' && typeof key === 'function') {
285
+ setOpts({ path, run: key });
286
+ return this;
287
+ }
288
+ if (typeof path === 'string' && typeof key === 'string' && typeof opts === 'function') {
289
+ setOpts({ path, key, run: opts });
290
+ return this;
291
+ }
292
+ return this;
293
+ }
294
+ addTo(router: QueryRouter | { add: (route: Route) => void; [key: string]: any }) {
295
+ router.add(this);
296
+ }
297
+ setData(data: any) {
298
+ this.data = data;
299
+ return this;
300
+ }
301
+ throw(code?: number | string, message?: string, tips?: string): void;
302
+ throw(...args: any[]) {
303
+ throw new CustomError(...args);
304
+ }
305
+ }
306
+
307
+ export class QueryRouter {
308
+ routes: Route[];
309
+ maxNextRoute = 40;
310
+ context?: RouteContext = {}; // default context for call
311
+ constructor() {
312
+ this.routes = [];
313
+ }
314
+
315
+ add(route: Route) {
316
+ const has = this.routes.find((r) => r.path === route.path && r.key === route.key);
317
+ if (has) {
318
+ // remove the old route
319
+ this.routes = this.routes.filter((r) => r.id !== has.id);
320
+ }
321
+ this.routes.push(route);
322
+ }
323
+ /**
324
+ * remove route by path and key
325
+ * @param route
326
+ */
327
+ remove(route: Route | { path: string; key?: string }) {
328
+ this.routes = this.routes.filter((r) => r.path === route.path && r.key == route.key);
329
+ }
330
+ /**
331
+ * remove route by id
332
+ * @param uniqueId
333
+ */
334
+ removeById(unique: string) {
335
+ this.routes = this.routes.filter((r) => r.id !== unique);
336
+ }
337
+ /**
338
+ * 执行route
339
+ * @param path
340
+ * @param key
341
+ * @param ctx
342
+ * @returns
343
+ */
344
+ async runRoute(path: string, key: string, ctx?: RouteContext) {
345
+ const route = this.routes.find((r) => r.path === path && r.key === key);
346
+ const maxNextRoute = this.maxNextRoute;
347
+ ctx = (ctx || {}) as RouteContext;
348
+ ctx.currentPath = path;
349
+ ctx.currentKey = key;
350
+ ctx.currentRoute = route;
351
+ ctx.index = (ctx.index || 0) + 1;
352
+ const progress = [path, key] as [string, string];
353
+ if (ctx.progress) {
354
+ ctx.progress.push(progress);
355
+ } else {
356
+ ctx.progress = [progress];
357
+ }
358
+ if (ctx.index > maxNextRoute) {
359
+ ctx.code = 500;
360
+ ctx.message = 'Too many nextRoute';
361
+ ctx.body = null;
362
+ return;
363
+ }
364
+ // run middleware
365
+ if (route && route.middleware && route.middleware.length > 0) {
366
+ const errorMiddleware: { path?: string; key?: string; id?: string }[] = [];
367
+ const getMiddleware = (m: Route) => {
368
+ if (!m.middleware || m.middleware.length === 0) return [];
369
+ const routeMiddleware: Route[] = [];
370
+ for (let i = 0; i < m.middleware.length; i++) {
371
+ const item = m.middleware[i];
372
+ let route: Route | undefined;
373
+ const isString = typeof item === 'string';
374
+ if (isString) {
375
+ route = this.routes.find((r) => r.id === item);
376
+ } else {
377
+ route = this.routes.find((r) => r.path === item.path && r.key === item.key);
378
+ }
379
+ if (!route) {
380
+ if (isString) {
381
+ errorMiddleware.push({
382
+ id: item as string,
383
+ });
384
+ } else
385
+ errorMiddleware.push({
386
+ path: m?.path,
387
+ key: m?.key,
388
+ });
389
+ }
390
+ const routeMiddlewarePrevious = getMiddleware(route);
391
+ if (routeMiddlewarePrevious.length > 0) {
392
+ routeMiddleware.push(...routeMiddlewarePrevious);
393
+ }
394
+ routeMiddleware.push(route);
395
+ }
396
+ return routeMiddleware;
397
+ };
398
+ const routeMiddleware = getMiddleware(route);
399
+ if (errorMiddleware.length > 0) {
400
+ console.error('middleware not found');
401
+ ctx.body = errorMiddleware;
402
+ ctx.message = 'middleware not found';
403
+ ctx.code = 404;
404
+ return ctx;
405
+ }
406
+ for (let i = 0; i < routeMiddleware.length; i++) {
407
+ const middleware = routeMiddleware[i];
408
+ if (middleware) {
409
+ if (middleware?.isVerify) {
410
+ try {
411
+ middleware.verify(ctx);
412
+ } catch (e) {
413
+ if (middleware?.isDebug) {
414
+ console.error('=====debug====:', 'middleware verify error:', e.message);
415
+ }
416
+ ctx.message = e.message;
417
+ ctx.code = 500;
418
+ ctx.body = null;
419
+ return ctx;
420
+ }
421
+ }
422
+ try {
423
+ await middleware.run(ctx);
424
+ } catch (e) {
425
+ if (route?.isDebug) {
426
+ console.error('=====debug====:middlerware error');
427
+ console.error('=====debug====:', e);
428
+ console.error('=====debug====:[path:key]:', `${route.path}-${route.key}`);
429
+ console.error('=====debug====:', e.message);
430
+ }
431
+ if (e instanceof CustomError || e?.code) {
432
+ ctx.code = e.code;
433
+ ctx.message = e.message;
434
+ ctx.body = null;
435
+ } else {
436
+ console.error(`fn:${route.path}-${route.key}:${route.id}`);
437
+ console.error(`middleware:${middleware.path}-${middleware.key}:${middleware.id}`);
438
+ ctx.code = 500;
439
+ ctx.message = 'Internal Server Error';
440
+ ctx.body = null;
441
+ }
442
+ return ctx;
443
+ }
444
+ if (ctx.end) {
445
+ }
446
+ }
447
+ }
448
+ }
449
+ // run route
450
+ if (route) {
451
+ if (route.run) {
452
+ if (route?.isVerify) {
453
+ try {
454
+ route.verify(ctx);
455
+ } catch (e) {
456
+ if (route?.isDebug) {
457
+ console.error('=====debug====:', 'verify error:', e.message);
458
+ }
459
+ ctx.message = e.message;
460
+ ctx.code = 500;
461
+ ctx.body = null;
462
+ return ctx;
463
+ }
464
+ }
465
+ try {
466
+ await route.run(ctx);
467
+ } catch (e) {
468
+ if (route?.isDebug) {
469
+ console.error('=====debug====:', 'router run error:', e.message);
470
+ }
471
+ if (e instanceof CustomError) {
472
+ ctx.code = e.code;
473
+ ctx.message = e.message;
474
+ } else {
475
+ console.error(`[error]fn:${route.path}-${route.key}:${route.id}`);
476
+ console.error('error', e.message);
477
+ ctx.code = 500;
478
+ ctx.message = 'Internal Server Error';
479
+ }
480
+ ctx.body = null;
481
+ return ctx;
482
+ }
483
+ if (ctx.end) {
484
+ // TODO: 提前结束, 以及错误情况
485
+ return;
486
+ }
487
+ if (route.nextRoute) {
488
+ let path: string, key: string;
489
+ if (route.nextRoute.path || route.nextRoute.key) {
490
+ path = route.nextRoute.path;
491
+ key = route.nextRoute.key;
492
+ } else if (route.nextRoute.id) {
493
+ const nextRoute = this.routes.find((r) => r.id === route.nextRoute.id);
494
+ if (nextRoute) {
495
+ path = nextRoute.path;
496
+ key = nextRoute.key;
497
+ }
498
+ }
499
+ if (!path || !key) {
500
+ ctx.message = 'nextRoute not found';
501
+ ctx.code = 404;
502
+ ctx.body = null;
503
+ return ctx;
504
+ }
505
+ ctx.query = { ...ctx.query, ...ctx.nextQuery };
506
+ ctx.nextQuery = {};
507
+ return await this.runRoute(path, key, ctx);
508
+ }
509
+ if (!ctx.code) ctx.code = 200;
510
+ return ctx;
511
+ } else {
512
+ // return Promise.resolve({ code: 404, body: 'Not found runing' });
513
+ // 可以不需要run的route,因为不一定是错误
514
+ return ctx;
515
+ }
516
+ }
517
+ // 如果没有找到route,返回404,这是因为出现了错误
518
+ return Promise.resolve({ code: 404, body: 'Not found' });
519
+ }
520
+ /**
521
+ * 第一次执行
522
+ * @param message
523
+ * @param ctx
524
+ * @returns
525
+ */
526
+ async parse(message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
527
+ if (!message?.path) {
528
+ return Promise.resolve({ code: 404, body: null, message: 'Not found path' });
529
+ }
530
+ const { path, key = '', payload = {}, ...query } = message;
531
+ ctx = ctx || {};
532
+ ctx.query = { ...ctx.query, ...query, ...payload };
533
+ ctx.state = { ...ctx?.state };
534
+ ctx.throw = this.throw;
535
+ // put queryRouter to ctx
536
+ // TODO: 是否需要queryRouter,函数内部处理router路由执行,这应该是避免去内部去包含的功能过
537
+ ctx.queryRouter = this;
538
+ ctx.call = this.call.bind(this);
539
+ ctx.queryRoute = this.queryRoute.bind(this);
540
+ ctx.index = 0;
541
+ ctx.progress = ctx.progress || [];
542
+ const res = await this.runRoute(path, key, ctx);
543
+ const serialize = ctx.needSerialize ?? true; // 是否需要序列化
544
+ if (serialize) {
545
+ res.body = JSON.parse(JSON.stringify(res.body || ''));
546
+ }
547
+ return res;
548
+ }
549
+ /**
550
+ * 返回的数据包含所有的context的请求返回的内容,可做其他处理
551
+ * @param message
552
+ * @param ctx
553
+ * @returns
554
+ */
555
+ async call(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
556
+ let path = message.path;
557
+ let key = message.key;
558
+ if (message.id) {
559
+ const route = this.routes.find((r) => r.id === message.id);
560
+ if (route) {
561
+ path = route.path;
562
+ key = route.key;
563
+ } else {
564
+ return { code: 404, body: null, message: 'Not found route' };
565
+ }
566
+ } else if (path) {
567
+ return await this.parse({ ...message, path }, { ...this.context, ...ctx });
568
+ } else {
569
+ return { code: 404, body: null, message: 'Not found path' };
570
+ }
571
+ }
572
+
573
+ /**
574
+ * 请求 result 的数据
575
+ * @param message
576
+ * @param ctx
577
+ * @returns
578
+ */
579
+ async queryRoute(message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
580
+ const res = await this.parse(message, { ...this.context, ...ctx });
581
+ return {
582
+ code: res.code,
583
+ data: res.body,
584
+ message: res.message,
585
+ };
586
+ }
587
+ async setContext(ctx: RouteContext) {
588
+ this.context = ctx;
589
+ }
590
+ getList(): RouteInfo[] {
591
+ return this.routes.map((r) => {
592
+ return pick(r, pickValue as any);
593
+ });
594
+ }
595
+ getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext) {
596
+ return async (msg: { path: string; key?: string; [key: string]: any }, handleContext?: RouteContext) => {
597
+ try {
598
+ const context = { ...ctx, ...handleContext };
599
+ const res = await router.parse(msg, context);
600
+ if (wrapperFn) {
601
+ res.data = res.body;
602
+ return wrapperFn(res, context);
603
+ }
604
+ const { code, body, message } = res;
605
+ return { code, data: body, message };
606
+ } catch (e) {
607
+ return { code: 500, message: e.message };
608
+ }
609
+ };
610
+ }
611
+ exportRoutes() {
612
+ return this.routes.map((r) => {
613
+ return r;
614
+ });
615
+ }
616
+ importRoutes(routes: Route[]) {
617
+ for (let route of routes) {
618
+ this.add(route);
619
+ }
620
+ }
621
+ importRouter(router: QueryRouter) {
622
+ this.importRoutes(router.routes);
623
+ }
624
+ throw(code?: number | string, message?: string, tips?: string): void;
625
+ throw(...args: any[]) {
626
+ throw new CustomError(...args);
627
+ }
628
+ hasRoute(path: string, key?: string) {
629
+ return this.routes.find((r) => r.path === path && r.key === key);
630
+ }
631
+ }
632
+
633
+ type QueryRouterServerOpts = {
634
+ handleFn?: HandleFn;
635
+ context?: RouteContext;
636
+ };
637
+ interface HandleFn<T = any> {
638
+ (msg: { path: string; [key: string]: any }, ctx?: any): { code: string; data?: any; message?: string; [key: string]: any };
639
+ (res: RouteContext<T>): any;
640
+ }
641
+ /**
642
+ * QueryRouterServer
643
+ * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
644
+ */
645
+ export class QueryRouterServer extends QueryRouter {
646
+ handle: any;
647
+ constructor(opts?: QueryRouterServerOpts) {
648
+ super();
649
+ this.handle = this.getHandle(this, opts?.handleFn, opts?.context);
650
+ this.setContext({ needSerialize: false, ...opts?.context });
651
+ }
652
+ setHandle(wrapperFn?: HandleFn, ctx?: RouteContext) {
653
+ this.handle = this.getHandle(this, wrapperFn, ctx);
654
+ }
655
+ use(path: string, fn: (ctx: any) => any, opts?: RouteOpts) {
656
+ const route = new Route(path, '', opts);
657
+ route.run = fn;
658
+ this.add(route);
659
+ }
660
+ addRoute(route: Route) {
661
+ this.add(route);
662
+ }
663
+
664
+ Route = Route;
665
+ route(opts: RouteOpts): Route<Required<RouteContext>>;
666
+ route(path: string, key?: string): Route<Required<RouteContext>>;
667
+ route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
668
+ route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
669
+ route(...args: any[]) {
670
+ const [path, key, opts] = args;
671
+ if (typeof path === 'object') {
672
+ return new Route(path.path, path.key, path);
673
+ }
674
+ if (typeof path === 'string') {
675
+ if (opts) {
676
+ return new Route(path, key, opts);
677
+ }
678
+ if (key && typeof key === 'object') {
679
+ return new Route(path, key?.key || '', key);
680
+ }
681
+ return new Route(path, key);
682
+ }
683
+ return new Route(path, key, opts);
684
+ }
685
+
686
+ /**
687
+ * 等于queryRoute,但是调用了handle
688
+ * @param param0
689
+ * @returns
690
+ */
691
+ async run({ path, key, payload }: { path: string; key?: string; payload?: any }) {
692
+ const handle = this.handle;
693
+ const resultError = (error: string, code = 500) => {
694
+ const r = {
695
+ code: code,
696
+ message: error,
697
+ };
698
+ return r;
699
+ };
700
+ try {
701
+ const end = handle({ path, key, ...payload });
702
+ return end;
703
+ } catch (e) {
704
+ if (e.code && typeof e.code === 'number') {
705
+ return {
706
+ code: e.code,
707
+ message: e.message,
708
+ };
709
+ } else {
710
+ return resultError('Router Server error');
711
+ }
712
+ }
713
+ }
714
+ }
@@ -0,0 +1,3 @@
1
+ import { parseXml } from './server/parse-xml.ts';
2
+
3
+ export { parseXml };