@kevisual/router 0.0.2
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/app.d.ts +60 -0
- package/dist/connect.d.ts +30 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +6416 -0
- package/dist/io.d.ts +3 -0
- package/dist/result/error.d.ts +22 -0
- package/dist/result/index.d.ts +27 -0
- package/dist/route.d.ts +234 -0
- package/dist/server/handle-server.d.ts +10 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/parse-body.d.ts +2 -0
- package/dist/server/server.d.ts +54 -0
- package/dist/server/ws-server.d.ts +37 -0
- package/dist/static.d.ts +1 -0
- package/dist/utils/parse.d.ts +3 -0
- package/dist/utils/pick.d.ts +1 -0
- package/dist/validator/index.d.ts +1 -0
- package/dist/validator/rule.d.ts +40 -0
- package/package.json +47 -0
- package/readme.md +31 -0
package/dist/io.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** 自定义错误 */
|
|
2
|
+
export declare class CustomError extends Error {
|
|
3
|
+
code?: number;
|
|
4
|
+
data?: any;
|
|
5
|
+
message: string;
|
|
6
|
+
tips?: string;
|
|
7
|
+
constructor(code?: number | string, message?: string, tips?: string);
|
|
8
|
+
static fromCode(code?: number): CustomError;
|
|
9
|
+
static fromErrorData(code?: number, data?: any): CustomError;
|
|
10
|
+
static parseError(e: CustomError): {
|
|
11
|
+
code: number;
|
|
12
|
+
data: any;
|
|
13
|
+
message: string;
|
|
14
|
+
tips: string;
|
|
15
|
+
};
|
|
16
|
+
parse(e?: CustomError): {
|
|
17
|
+
code: number;
|
|
18
|
+
data: any;
|
|
19
|
+
message: string;
|
|
20
|
+
tips: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const Code400: {
|
|
2
|
+
code: number;
|
|
3
|
+
msg: string;
|
|
4
|
+
zn: string;
|
|
5
|
+
}[];
|
|
6
|
+
export declare const ResultCode: {
|
|
7
|
+
code: number;
|
|
8
|
+
msg: string;
|
|
9
|
+
zn: string;
|
|
10
|
+
}[];
|
|
11
|
+
type ResultProps = {
|
|
12
|
+
code?: number;
|
|
13
|
+
msg?: string;
|
|
14
|
+
userTip?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const Result: {
|
|
17
|
+
({ code, msg, userTip, ...other }: ResultProps): {
|
|
18
|
+
code: number;
|
|
19
|
+
msg: string;
|
|
20
|
+
userTip: any;
|
|
21
|
+
};
|
|
22
|
+
success(data?: any): {
|
|
23
|
+
code: number;
|
|
24
|
+
data: any;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export {};
|
package/dist/route.d.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { Schema, Rule } from './validator/index.ts';
|
|
2
|
+
export type RouterContextT = {
|
|
3
|
+
code?: number;
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
};
|
|
6
|
+
export type RouteContext<T = {
|
|
7
|
+
code?: number;
|
|
8
|
+
}, S = any> = {
|
|
9
|
+
query?: {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
};
|
|
12
|
+
/** return body */
|
|
13
|
+
body?: number | string | Object;
|
|
14
|
+
/** return code */
|
|
15
|
+
code?: number;
|
|
16
|
+
/** return msg */
|
|
17
|
+
message?: string;
|
|
18
|
+
state?: S;
|
|
19
|
+
currentPath?: string;
|
|
20
|
+
currentKey?: string;
|
|
21
|
+
currentRoute?: Route;
|
|
22
|
+
progress?: [[string, string]][];
|
|
23
|
+
nextQuery?: {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
};
|
|
26
|
+
end?: boolean;
|
|
27
|
+
queryRouter?: QueryRouter;
|
|
28
|
+
error?: any;
|
|
29
|
+
call?: (message: {
|
|
30
|
+
path: string;
|
|
31
|
+
key: string;
|
|
32
|
+
payload?: any;
|
|
33
|
+
}, ctx?: RouteContext & {
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
}) => Promise<any>;
|
|
36
|
+
index?: number;
|
|
37
|
+
} & T;
|
|
38
|
+
export type Run<T = any> = (ctx?: RouteContext<T>) => Promise<typeof ctx | null | void>;
|
|
39
|
+
export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
|
|
40
|
+
export type RouteOpts = {
|
|
41
|
+
path?: string;
|
|
42
|
+
key?: string;
|
|
43
|
+
id?: string;
|
|
44
|
+
run?: Run;
|
|
45
|
+
nextRoute?: NextRoute;
|
|
46
|
+
description?: string;
|
|
47
|
+
middleware?: Route[] | string[];
|
|
48
|
+
type?: 'route' | 'middleware';
|
|
49
|
+
/**
|
|
50
|
+
* validator: {
|
|
51
|
+
* packageName: {
|
|
52
|
+
* type: 'string',
|
|
53
|
+
* required: true,
|
|
54
|
+
* },
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
validator?: {
|
|
58
|
+
[key: string]: Rule;
|
|
59
|
+
};
|
|
60
|
+
schema?: {
|
|
61
|
+
[key: string]: Schema<any>;
|
|
62
|
+
};
|
|
63
|
+
isVerify?: boolean;
|
|
64
|
+
verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
|
|
65
|
+
verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean;
|
|
66
|
+
idUsePath?: boolean;
|
|
67
|
+
isDebug?: boolean;
|
|
68
|
+
};
|
|
69
|
+
export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
|
|
70
|
+
declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
|
|
71
|
+
export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
|
72
|
+
export declare class Route {
|
|
73
|
+
path?: string;
|
|
74
|
+
key?: string;
|
|
75
|
+
id?: string;
|
|
76
|
+
share?: boolean;
|
|
77
|
+
run?: Run;
|
|
78
|
+
nextRoute?: NextRoute;
|
|
79
|
+
description?: string;
|
|
80
|
+
middleware?: (Route | string)[];
|
|
81
|
+
type?: string;
|
|
82
|
+
private _validator?;
|
|
83
|
+
schema?: {
|
|
84
|
+
[key: string]: Schema<any>;
|
|
85
|
+
};
|
|
86
|
+
data?: any;
|
|
87
|
+
isVerify?: boolean;
|
|
88
|
+
isDebug?: boolean;
|
|
89
|
+
constructor(path: string, key?: string, opts?: RouteOpts);
|
|
90
|
+
private createSchema;
|
|
91
|
+
/**
|
|
92
|
+
* set validator and create schema
|
|
93
|
+
* @param validator
|
|
94
|
+
*/
|
|
95
|
+
set validator(validator: {
|
|
96
|
+
[key: string]: Rule;
|
|
97
|
+
});
|
|
98
|
+
get validator(): {
|
|
99
|
+
[key: string]: Rule;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* has code, body, message in ctx, return ctx if has error
|
|
103
|
+
* @param ctx
|
|
104
|
+
* @param dev
|
|
105
|
+
* @returns
|
|
106
|
+
*/
|
|
107
|
+
verify(ctx: RouteContext, dev?: boolean): void;
|
|
108
|
+
/**
|
|
109
|
+
* Need to manully call return ctx fn and configure body, code, message
|
|
110
|
+
* @param key
|
|
111
|
+
* @param ctx
|
|
112
|
+
* @param dev
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
verifyKey(key: string, ctx: RouteContext, dev?: boolean): {
|
|
116
|
+
message: string;
|
|
117
|
+
path: string;
|
|
118
|
+
key: string;
|
|
119
|
+
error: any;
|
|
120
|
+
} | {
|
|
121
|
+
message: string;
|
|
122
|
+
path: string;
|
|
123
|
+
key: string;
|
|
124
|
+
error?: undefined;
|
|
125
|
+
};
|
|
126
|
+
setValidator(validator: {
|
|
127
|
+
[key: string]: Rule;
|
|
128
|
+
}): this;
|
|
129
|
+
define<T extends {
|
|
130
|
+
[key: string]: any;
|
|
131
|
+
} = RouterContextT>(opts: DefineRouteOpts): this;
|
|
132
|
+
define<T extends {
|
|
133
|
+
[key: string]: any;
|
|
134
|
+
} = RouterContextT>(fn: Run<T>): this;
|
|
135
|
+
define<T extends {
|
|
136
|
+
[key: string]: any;
|
|
137
|
+
} = RouterContextT>(key: string, fn: Run<T>): this;
|
|
138
|
+
define<T extends {
|
|
139
|
+
[key: string]: any;
|
|
140
|
+
} = RouterContextT>(path: string, key: string, fn: Run<T>): this;
|
|
141
|
+
addTo(router: QueryRouter | {
|
|
142
|
+
add: (route: Route) => void;
|
|
143
|
+
[key: string]: any;
|
|
144
|
+
}): void;
|
|
145
|
+
setData(data: any): this;
|
|
146
|
+
}
|
|
147
|
+
export declare class QueryRouter {
|
|
148
|
+
routes: Route[];
|
|
149
|
+
maxNextRoute: number;
|
|
150
|
+
constructor();
|
|
151
|
+
add(route: Route): void;
|
|
152
|
+
/**
|
|
153
|
+
* remove route by path and key
|
|
154
|
+
* @param route
|
|
155
|
+
*/
|
|
156
|
+
remove(route: Route | {
|
|
157
|
+
path: string;
|
|
158
|
+
key: string;
|
|
159
|
+
}): void;
|
|
160
|
+
/**
|
|
161
|
+
* remove route by id
|
|
162
|
+
* @param uniqueId
|
|
163
|
+
*/
|
|
164
|
+
removeById(unique: string): void;
|
|
165
|
+
/**
|
|
166
|
+
* 执行route
|
|
167
|
+
* @param path
|
|
168
|
+
* @param key
|
|
169
|
+
* @param ctx
|
|
170
|
+
* @returns
|
|
171
|
+
*/
|
|
172
|
+
runRoute(path: string, key: string, ctx?: RouteContext): any;
|
|
173
|
+
/**
|
|
174
|
+
* 第一次执行
|
|
175
|
+
* @param message
|
|
176
|
+
* @param ctx
|
|
177
|
+
* @returns
|
|
178
|
+
*/
|
|
179
|
+
parse(message: {
|
|
180
|
+
path: string;
|
|
181
|
+
key?: string;
|
|
182
|
+
payload?: any;
|
|
183
|
+
}, ctx?: RouteContext & {
|
|
184
|
+
[key: string]: any;
|
|
185
|
+
}): Promise<any>;
|
|
186
|
+
call(message: {
|
|
187
|
+
path: string;
|
|
188
|
+
key: string;
|
|
189
|
+
payload?: any;
|
|
190
|
+
}, ctx?: RouteContext & {
|
|
191
|
+
[key: string]: any;
|
|
192
|
+
}): Promise<any>;
|
|
193
|
+
getList(): RouteInfo[];
|
|
194
|
+
getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext): (msg: {
|
|
195
|
+
path: string;
|
|
196
|
+
key?: string;
|
|
197
|
+
[key: string]: any;
|
|
198
|
+
}) => Promise<{
|
|
199
|
+
[key: string]: any;
|
|
200
|
+
code: string;
|
|
201
|
+
data?: any;
|
|
202
|
+
message?: string;
|
|
203
|
+
} | {
|
|
204
|
+
code: any;
|
|
205
|
+
data: any;
|
|
206
|
+
message: any;
|
|
207
|
+
}>;
|
|
208
|
+
}
|
|
209
|
+
type QueryRouterServerOpts = {
|
|
210
|
+
handleFn?: HandleFn;
|
|
211
|
+
context?: RouteContext;
|
|
212
|
+
};
|
|
213
|
+
interface HandleFn<T = any> {
|
|
214
|
+
(msg: {
|
|
215
|
+
path: string;
|
|
216
|
+
[key: string]: any;
|
|
217
|
+
}, ctx?: any): {
|
|
218
|
+
code: string;
|
|
219
|
+
data?: any;
|
|
220
|
+
message?: string;
|
|
221
|
+
[key: string]: any;
|
|
222
|
+
};
|
|
223
|
+
(res: RouteContext<T>): any;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* QueryRouterServer
|
|
227
|
+
* @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
|
|
228
|
+
*/
|
|
229
|
+
export declare class QueryRouterServer extends QueryRouter {
|
|
230
|
+
handle: any;
|
|
231
|
+
constructor(opts?: QueryRouterServerOpts);
|
|
232
|
+
setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void;
|
|
233
|
+
}
|
|
234
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import http, { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
export type Listener = (...args: any[]) => void;
|
|
3
|
+
export type Cors = {
|
|
4
|
+
/**
|
|
5
|
+
* @default '*''
|
|
6
|
+
*/
|
|
7
|
+
origin?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
type ServerOpts = {
|
|
10
|
+
/**path default `/api/router` */
|
|
11
|
+
path?: string;
|
|
12
|
+
/**handle Fn */
|
|
13
|
+
handle?: (msg?: {
|
|
14
|
+
path: string;
|
|
15
|
+
key?: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}) => any;
|
|
18
|
+
cors?: Cors;
|
|
19
|
+
};
|
|
20
|
+
export declare const resultError: (error: string, code?: number) => string;
|
|
21
|
+
export declare class Server {
|
|
22
|
+
path: string;
|
|
23
|
+
private _server;
|
|
24
|
+
handle: ServerOpts['handle'];
|
|
25
|
+
private _callback;
|
|
26
|
+
private cors;
|
|
27
|
+
private hasOn;
|
|
28
|
+
constructor(opts?: ServerOpts);
|
|
29
|
+
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
|
|
30
|
+
listen(port: number, hostname?: string, listeningListener?: () => void): void;
|
|
31
|
+
listen(port: number, backlog?: number, listeningListener?: () => void): void;
|
|
32
|
+
listen(port: number, listeningListener?: () => void): void;
|
|
33
|
+
listen(path: string, backlog?: number, listeningListener?: () => void): void;
|
|
34
|
+
listen(path: string, listeningListener?: () => void): void;
|
|
35
|
+
listen(handle: any, backlog?: number, listeningListener?: () => void): void;
|
|
36
|
+
listen(handle: any, listeningListener?: () => void): void;
|
|
37
|
+
setHandle(handle?: any): void;
|
|
38
|
+
/**
|
|
39
|
+
* get callback
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
createCallback(): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
43
|
+
get handleServer(): any;
|
|
44
|
+
set handleServer(fn: any);
|
|
45
|
+
/**
|
|
46
|
+
* 兜底监听,当除开 `/api/router` 之外的请求,框架只监听一个api,所以有其他的请求都执行其他的监听
|
|
47
|
+
* @description 主要是为了兼容其他的监听
|
|
48
|
+
* @param listener
|
|
49
|
+
*/
|
|
50
|
+
on(listener: Listener | Listener[]): void;
|
|
51
|
+
get callback(): any;
|
|
52
|
+
get server(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
2
|
+
import { Server } from './server.ts';
|
|
3
|
+
export declare const createWsServer: (server: Server) => import("ws").Server<typeof import("ws"), typeof import("http").IncomingMessage>;
|
|
4
|
+
type WsServerBaseOpts = {
|
|
5
|
+
wss?: WebSocketServer;
|
|
6
|
+
path?: string;
|
|
7
|
+
};
|
|
8
|
+
export type ListenerFn = (message: {
|
|
9
|
+
data: Record<string, any>;
|
|
10
|
+
ws: WebSocket;
|
|
11
|
+
end: (data: any) => any;
|
|
12
|
+
}) => Promise<any>;
|
|
13
|
+
export type Listener<T = 'router' | 'chat' | 'ai'> = {
|
|
14
|
+
type: T;
|
|
15
|
+
listener: ListenerFn;
|
|
16
|
+
};
|
|
17
|
+
export declare class WsServerBase {
|
|
18
|
+
wss: WebSocketServer;
|
|
19
|
+
path: string;
|
|
20
|
+
listeners: {
|
|
21
|
+
type: string;
|
|
22
|
+
listener: ListenerFn;
|
|
23
|
+
}[];
|
|
24
|
+
listening: boolean;
|
|
25
|
+
constructor(opts: WsServerBaseOpts);
|
|
26
|
+
setPath(path: string): void;
|
|
27
|
+
listen(): void;
|
|
28
|
+
addListener(type: string, listener: ListenerFn): void;
|
|
29
|
+
removeListener(type: string): void;
|
|
30
|
+
}
|
|
31
|
+
export declare class WsServer extends WsServerBase {
|
|
32
|
+
server: Server;
|
|
33
|
+
constructor(server: Server, opts?: any);
|
|
34
|
+
initListener(): void;
|
|
35
|
+
listen(): void;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
package/dist/static.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './rule.ts';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z, Schema } from 'zod';
|
|
2
|
+
export { Schema };
|
|
3
|
+
type BaseRule = {
|
|
4
|
+
value?: any;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
message?: string;
|
|
7
|
+
};
|
|
8
|
+
type RuleString = {
|
|
9
|
+
type: 'string';
|
|
10
|
+
minLength?: number;
|
|
11
|
+
maxLength?: number;
|
|
12
|
+
regex?: string;
|
|
13
|
+
} & BaseRule;
|
|
14
|
+
type RuleNumber = {
|
|
15
|
+
type: 'number';
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
} & BaseRule;
|
|
19
|
+
type RuleBoolean = {
|
|
20
|
+
type: 'boolean';
|
|
21
|
+
} & BaseRule;
|
|
22
|
+
type RuleArray = {
|
|
23
|
+
type: 'array';
|
|
24
|
+
items: Rule;
|
|
25
|
+
minItems?: number;
|
|
26
|
+
maxItems?: number;
|
|
27
|
+
} & BaseRule;
|
|
28
|
+
type RuleObject = {
|
|
29
|
+
type: 'object';
|
|
30
|
+
properties: {
|
|
31
|
+
[key: string]: Rule;
|
|
32
|
+
};
|
|
33
|
+
} & BaseRule;
|
|
34
|
+
type RuleAny = {
|
|
35
|
+
type: 'any';
|
|
36
|
+
} & BaseRule;
|
|
37
|
+
export type Rule = RuleString | RuleNumber | RuleBoolean | RuleArray | RuleObject | RuleAny;
|
|
38
|
+
export declare const schemaFormRule: (rule: Rule) => z.ZodType<any, any, any>;
|
|
39
|
+
export declare const createSchema: (rule: Rule) => Schema;
|
|
40
|
+
export declare const createSchemaList: (rules: Rule[]) => z.ZodType<any, z.ZodTypeDef, any>[];
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
3
|
+
"name": "@kevisual/router",
|
|
4
|
+
"version": "0.0.2",
|
|
5
|
+
"description": "",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "npm run clean && rollup -c",
|
|
12
|
+
"watch": "rollup -c -w",
|
|
13
|
+
"clean": "rm -rf dist"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@rollup/plugin-commonjs": "^26.0.1",
|
|
23
|
+
"@rollup/plugin-node-resolve": "^15.2.4",
|
|
24
|
+
"@rollup/plugin-typescript": "^12.1.0",
|
|
25
|
+
"@types/lodash-es": "^4.17.12",
|
|
26
|
+
"@types/node": "^22.5.5",
|
|
27
|
+
"@types/ws": "^8.5.12",
|
|
28
|
+
"lodash-es": "^4.17.21",
|
|
29
|
+
"nanoid": "^5.0.7",
|
|
30
|
+
"rollup": "^4.22.4",
|
|
31
|
+
"ts-loader": "^9.5.1",
|
|
32
|
+
"ts-node": "^10.9.2",
|
|
33
|
+
"tslib": "^2.7.0",
|
|
34
|
+
"typescript": "^5.6.2",
|
|
35
|
+
"zod": "^3.23.8"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/abearxiong/kevisual-router.git"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"ws": "^8.18.0"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# router
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import { App } from '@kevisual/router';
|
|
5
|
+
|
|
6
|
+
const app = new App();
|
|
7
|
+
app.listen(4002);
|
|
8
|
+
|
|
9
|
+
new app.Route('demo', '01')
|
|
10
|
+
.define(async (ctx) => {
|
|
11
|
+
ctx.body = '01';
|
|
12
|
+
return ctx;
|
|
13
|
+
})
|
|
14
|
+
.addTo(app);
|
|
15
|
+
|
|
16
|
+
app
|
|
17
|
+
.route({path:'demo', key: '02})
|
|
18
|
+
.define(async (ctx) => {
|
|
19
|
+
ctx.body = '02';
|
|
20
|
+
return ctx;
|
|
21
|
+
})
|
|
22
|
+
.addTo(app);
|
|
23
|
+
|
|
24
|
+
app
|
|
25
|
+
.route('demo', '03')
|
|
26
|
+
.define(async (ctx) => {
|
|
27
|
+
ctx.body = '03';
|
|
28
|
+
return ctx;
|
|
29
|
+
})
|
|
30
|
+
.addTo(app);
|
|
31
|
+
```
|