@kevisual/router 0.0.6-alpha-1 → 0.0.6-alpha-3
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/router-browser.d.ts +14 -6
- package/dist/router-browser.js +15 -10
- package/dist/router.d.ts +46 -21
- package/dist/router.js +327 -17
- package/package.json +2 -1
package/dist/router-browser.d.ts
CHANGED
|
@@ -118,7 +118,9 @@ type RouteOpts = {
|
|
|
118
118
|
type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
|
|
119
119
|
declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
|
|
120
120
|
type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
|
121
|
-
declare class Route {
|
|
121
|
+
declare class Route<U = {
|
|
122
|
+
[key: string]: any;
|
|
123
|
+
}> {
|
|
122
124
|
path?: string;
|
|
123
125
|
key?: string;
|
|
124
126
|
id?: string;
|
|
@@ -180,13 +182,13 @@ declare class Route {
|
|
|
180
182
|
} = RouterContextT>(opts: DefineRouteOpts): this;
|
|
181
183
|
define<T extends {
|
|
182
184
|
[key: string]: any;
|
|
183
|
-
} = RouterContextT>(fn: Run<T>): this;
|
|
185
|
+
} = RouterContextT>(fn: Run<T & U>): this;
|
|
184
186
|
define<T extends {
|
|
185
187
|
[key: string]: any;
|
|
186
|
-
} = RouterContextT>(key: string, fn: Run<T>): this;
|
|
188
|
+
} = RouterContextT>(key: string, fn: Run<T & U>): this;
|
|
187
189
|
define<T extends {
|
|
188
190
|
[key: string]: any;
|
|
189
|
-
} = RouterContextT>(path: string, key: string, fn: Run<T>): this;
|
|
191
|
+
} = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
|
|
190
192
|
addTo(router: QueryRouter | {
|
|
191
193
|
add: (route: Route) => void;
|
|
192
194
|
[key: string]: any;
|
|
@@ -270,7 +272,7 @@ declare class QueryRouter {
|
|
|
270
272
|
path: string;
|
|
271
273
|
key?: string;
|
|
272
274
|
[key: string]: any;
|
|
273
|
-
}) => Promise<{
|
|
275
|
+
}, handleContext?: RouteContext) => Promise<{
|
|
274
276
|
[key: string]: any;
|
|
275
277
|
code: string;
|
|
276
278
|
data?: any;
|
|
@@ -279,8 +281,14 @@ declare class QueryRouter {
|
|
|
279
281
|
code: any;
|
|
280
282
|
data: any;
|
|
281
283
|
message: any;
|
|
284
|
+
} | {
|
|
285
|
+
code: number;
|
|
286
|
+
message: any;
|
|
287
|
+
data?: undefined;
|
|
282
288
|
}>;
|
|
283
|
-
exportRoutes(): Route
|
|
289
|
+
exportRoutes(): Route<{
|
|
290
|
+
[key: string]: any;
|
|
291
|
+
}>[];
|
|
284
292
|
importRoutes(routes: Route[]): void;
|
|
285
293
|
importRouter(router: QueryRouter): void;
|
|
286
294
|
throw(code?: number | string, message?: string, tips?: string): void;
|
package/dist/router-browser.js
CHANGED
|
@@ -3,7 +3,7 @@ const urlAlphabet =
|
|
|
3
3
|
|
|
4
4
|
let nanoid = (size = 21) => {
|
|
5
5
|
let id = '';
|
|
6
|
-
let bytes = crypto.getRandomValues(new Uint8Array(size));
|
|
6
|
+
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)));
|
|
7
7
|
while (size--) {
|
|
8
8
|
id += urlAlphabet[bytes[size] & 63];
|
|
9
9
|
}
|
|
@@ -5901,15 +5901,20 @@ class QueryRouter {
|
|
|
5901
5901
|
});
|
|
5902
5902
|
}
|
|
5903
5903
|
getHandle(router, wrapperFn, ctx) {
|
|
5904
|
-
return async (msg) => {
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5904
|
+
return async (msg, handleContext) => {
|
|
5905
|
+
try {
|
|
5906
|
+
const context = { ...ctx, ...handleContext };
|
|
5907
|
+
const res = await router.parse(msg, context);
|
|
5908
|
+
if (wrapperFn) {
|
|
5909
|
+
res.data = res.body;
|
|
5910
|
+
return wrapperFn(res, context);
|
|
5911
|
+
}
|
|
5912
|
+
const { code, body, message } = res;
|
|
5913
|
+
return { code, data: body, message };
|
|
5914
|
+
}
|
|
5915
|
+
catch (e) {
|
|
5916
|
+
return { code: 500, message: e.message };
|
|
5917
|
+
}
|
|
5913
5918
|
};
|
|
5914
5919
|
}
|
|
5915
5920
|
exportRoutes() {
|
package/dist/router.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Schema } from 'zod';
|
|
|
2
2
|
export { Schema } from 'zod';
|
|
3
3
|
import http, { IncomingMessage, ServerResponse } from 'http';
|
|
4
4
|
import https from 'https';
|
|
5
|
+
import http2 from 'http2';
|
|
6
|
+
import * as cookie from 'cookie';
|
|
5
7
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
6
8
|
|
|
7
9
|
type BaseRule = {
|
|
@@ -121,7 +123,9 @@ type RouteOpts = {
|
|
|
121
123
|
type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
|
|
122
124
|
declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
|
|
123
125
|
type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
|
124
|
-
declare class Route {
|
|
126
|
+
declare class Route<U = {
|
|
127
|
+
[key: string]: any;
|
|
128
|
+
}> {
|
|
125
129
|
path?: string;
|
|
126
130
|
key?: string;
|
|
127
131
|
id?: string;
|
|
@@ -183,13 +187,13 @@ declare class Route {
|
|
|
183
187
|
} = RouterContextT>(opts: DefineRouteOpts): this;
|
|
184
188
|
define<T extends {
|
|
185
189
|
[key: string]: any;
|
|
186
|
-
} = RouterContextT>(fn: Run<T>): this;
|
|
190
|
+
} = RouterContextT>(fn: Run<T & U>): this;
|
|
187
191
|
define<T extends {
|
|
188
192
|
[key: string]: any;
|
|
189
|
-
} = RouterContextT>(key: string, fn: Run<T>): this;
|
|
193
|
+
} = RouterContextT>(key: string, fn: Run<T & U>): this;
|
|
190
194
|
define<T extends {
|
|
191
195
|
[key: string]: any;
|
|
192
|
-
} = RouterContextT>(path: string, key: string, fn: Run<T>): this;
|
|
196
|
+
} = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
|
|
193
197
|
addTo(router: QueryRouter | {
|
|
194
198
|
add: (route: Route) => void;
|
|
195
199
|
[key: string]: any;
|
|
@@ -273,7 +277,7 @@ declare class QueryRouter {
|
|
|
273
277
|
path: string;
|
|
274
278
|
key?: string;
|
|
275
279
|
[key: string]: any;
|
|
276
|
-
}) => Promise<{
|
|
280
|
+
}, handleContext?: RouteContext) => Promise<{
|
|
277
281
|
[key: string]: any;
|
|
278
282
|
code: string;
|
|
279
283
|
data?: any;
|
|
@@ -282,8 +286,14 @@ declare class QueryRouter {
|
|
|
282
286
|
code: any;
|
|
283
287
|
data: any;
|
|
284
288
|
message: any;
|
|
289
|
+
} | {
|
|
290
|
+
code: number;
|
|
291
|
+
message: any;
|
|
292
|
+
data?: undefined;
|
|
285
293
|
}>;
|
|
286
|
-
exportRoutes(): Route
|
|
294
|
+
exportRoutes(): Route<{
|
|
295
|
+
[key: string]: any;
|
|
296
|
+
}>[];
|
|
287
297
|
importRoutes(routes: Route[]): void;
|
|
288
298
|
importRouter(router: QueryRouter): void;
|
|
289
299
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
@@ -362,6 +372,18 @@ declare class QueryConnect {
|
|
|
362
372
|
}
|
|
363
373
|
|
|
364
374
|
type Listener = (...args: any[]) => void;
|
|
375
|
+
type CookieFn = (name: string, value: string, options?: cookie.SerializeOptions, end?: boolean) => void;
|
|
376
|
+
type HandleCtx = {
|
|
377
|
+
req: IncomingMessage & {
|
|
378
|
+
cookies: Record<string, string>;
|
|
379
|
+
};
|
|
380
|
+
res: ServerResponse & {
|
|
381
|
+
/**
|
|
382
|
+
* cookie 函数, end 参数用于设置是否立即设置到响应头,设置了后面的cookie再设置会覆盖前面的
|
|
383
|
+
*/
|
|
384
|
+
cookie: CookieFn;
|
|
385
|
+
};
|
|
386
|
+
};
|
|
365
387
|
type Cors = {
|
|
366
388
|
/**
|
|
367
389
|
* @default '*''
|
|
@@ -376,9 +398,12 @@ type ServerOpts = {
|
|
|
376
398
|
path: string;
|
|
377
399
|
key?: string;
|
|
378
400
|
[key: string]: any;
|
|
401
|
+
}, ctx?: {
|
|
402
|
+
req: http.IncomingMessage;
|
|
403
|
+
res: http.ServerResponse;
|
|
379
404
|
}) => any;
|
|
380
405
|
cors?: Cors;
|
|
381
|
-
|
|
406
|
+
httpType?: 'http' | 'https' | 'http2';
|
|
382
407
|
httpsKey?: string;
|
|
383
408
|
httpsCert?: string;
|
|
384
409
|
};
|
|
@@ -389,7 +414,7 @@ declare class Server {
|
|
|
389
414
|
private _callback;
|
|
390
415
|
private cors;
|
|
391
416
|
private hasOn;
|
|
392
|
-
private
|
|
417
|
+
private httpType;
|
|
393
418
|
private options;
|
|
394
419
|
constructor(opts?: ServerOpts);
|
|
395
420
|
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
|
|
@@ -400,7 +425,7 @@ declare class Server {
|
|
|
400
425
|
listen(path: string, listeningListener?: () => void): void;
|
|
401
426
|
listen(handle: any, backlog?: number, listeningListener?: () => void): void;
|
|
402
427
|
listen(handle: any, listeningListener?: () => void): void;
|
|
403
|
-
createServer(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
428
|
+
createServer(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | http2.Http2SecureServer<typeof http.IncomingMessage, typeof http.ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
|
|
404
429
|
setHandle(handle?: any): void;
|
|
405
430
|
/**
|
|
406
431
|
* get callback
|
|
@@ -416,7 +441,7 @@ declare class Server {
|
|
|
416
441
|
*/
|
|
417
442
|
on(listener: Listener | Listener[]): void;
|
|
418
443
|
get callback(): any;
|
|
419
|
-
get server(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
444
|
+
get server(): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | http2.Http2SecureServer<typeof http.IncomingMessage, typeof http.ServerResponse, typeof http2.Http2ServerRequest, typeof http2.Http2ServerResponse>;
|
|
420
445
|
}
|
|
421
446
|
|
|
422
447
|
/**
|
|
@@ -426,6 +451,7 @@ declare class Server {
|
|
|
426
451
|
* @returns
|
|
427
452
|
*/
|
|
428
453
|
declare const handleServer: (req: IncomingMessage, res: ServerResponse) => Promise<{
|
|
454
|
+
cookies: Record<string, string>;
|
|
429
455
|
token: string;
|
|
430
456
|
}>;
|
|
431
457
|
|
|
@@ -497,14 +523,7 @@ type AppOptions<T = {}> = {
|
|
|
497
523
|
/** handle msg 关联 */
|
|
498
524
|
routerHandle?: RouterHandle;
|
|
499
525
|
routerContext?: RouteContext<T>;
|
|
500
|
-
serverOptions?:
|
|
501
|
-
path?: string;
|
|
502
|
-
cors?: Cors;
|
|
503
|
-
handle?: any;
|
|
504
|
-
isHTTPS?: boolean;
|
|
505
|
-
httpsKey?: string;
|
|
506
|
-
httpsCert?: string;
|
|
507
|
-
};
|
|
526
|
+
serverOptions?: ServerOpts;
|
|
508
527
|
io?: boolean;
|
|
509
528
|
ioOpts?: {
|
|
510
529
|
routerHandle?: RouterHandle;
|
|
@@ -512,7 +531,11 @@ type AppOptions<T = {}> = {
|
|
|
512
531
|
path?: string;
|
|
513
532
|
};
|
|
514
533
|
};
|
|
515
|
-
|
|
534
|
+
type AppReqRes = HandleCtx;
|
|
535
|
+
/**
|
|
536
|
+
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
|
537
|
+
*/
|
|
538
|
+
declare class App<T = {}, U = AppReqRes> {
|
|
516
539
|
router: QueryRouter;
|
|
517
540
|
server: Server;
|
|
518
541
|
io: WsServer;
|
|
@@ -529,7 +552,7 @@ declare class App<T = {}> {
|
|
|
529
552
|
addRoute(route: Route): void;
|
|
530
553
|
add: (route: Route) => void;
|
|
531
554
|
Route: typeof Route;
|
|
532
|
-
route(opts: RouteOpts): Route
|
|
555
|
+
route(opts: RouteOpts): Route<U>;
|
|
533
556
|
route(path: string, key?: string): Route;
|
|
534
557
|
route(path: string, opts?: RouteOpts): Route;
|
|
535
558
|
route(path: string, key?: string, opts?: RouteOpts): Route;
|
|
@@ -547,7 +570,9 @@ declare class App<T = {}> {
|
|
|
547
570
|
data: any;
|
|
548
571
|
message: any;
|
|
549
572
|
}>;
|
|
550
|
-
exportRoutes(): Route
|
|
573
|
+
exportRoutes(): Route<{
|
|
574
|
+
[key: string]: any;
|
|
575
|
+
}>[];
|
|
551
576
|
importRoutes(routes: any[]): void;
|
|
552
577
|
importApp(app: App): void;
|
|
553
578
|
throw(code?: number | string, message?: string, tips?: string): void;
|
package/dist/router.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { webcrypto } from 'node:crypto';
|
|
2
2
|
import http from 'http';
|
|
3
3
|
import https from 'https';
|
|
4
|
+
import http2 from 'http2';
|
|
4
5
|
import url from 'url';
|
|
5
6
|
import { WebSocketServer } from 'ws';
|
|
6
7
|
|
|
@@ -21,7 +22,7 @@ function fillPool(bytes) {
|
|
|
21
22
|
poolOffset += bytes;
|
|
22
23
|
}
|
|
23
24
|
function nanoid(size = 21) {
|
|
24
|
-
fillPool((size
|
|
25
|
+
fillPool((size |= 0));
|
|
25
26
|
let id = '';
|
|
26
27
|
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
27
28
|
id += urlAlphabet[pool[i] & 63];
|
|
@@ -5920,15 +5921,20 @@ class QueryRouter {
|
|
|
5920
5921
|
});
|
|
5921
5922
|
}
|
|
5922
5923
|
getHandle(router, wrapperFn, ctx) {
|
|
5923
|
-
return async (msg) => {
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5924
|
+
return async (msg, handleContext) => {
|
|
5925
|
+
try {
|
|
5926
|
+
const context = { ...ctx, ...handleContext };
|
|
5927
|
+
const res = await router.parse(msg, context);
|
|
5928
|
+
if (wrapperFn) {
|
|
5929
|
+
res.data = res.body;
|
|
5930
|
+
return wrapperFn(res, context);
|
|
5931
|
+
}
|
|
5932
|
+
const { code, body, message } = res;
|
|
5933
|
+
return { code, data: body, message };
|
|
5934
|
+
}
|
|
5935
|
+
catch (e) {
|
|
5936
|
+
return { code: 500, message: e.message };
|
|
5937
|
+
}
|
|
5932
5938
|
};
|
|
5933
5939
|
}
|
|
5934
5940
|
exportRoutes() {
|
|
@@ -6119,9 +6125,16 @@ const handleServer = async (req, res) => {
|
|
|
6119
6125
|
const parsedUrl = url.parse(req.url, true);
|
|
6120
6126
|
// 获取token
|
|
6121
6127
|
let token = req.headers['authorization'] || '';
|
|
6128
|
+
const handle = createHandleCtx(req, res);
|
|
6129
|
+
const cookies = handle.req.cookies;
|
|
6130
|
+
if (!token) {
|
|
6131
|
+
token = cookies.token;
|
|
6132
|
+
}
|
|
6122
6133
|
if (token) {
|
|
6123
6134
|
token = token.replace('Bearer ', '');
|
|
6124
6135
|
}
|
|
6136
|
+
//@ts-ignore
|
|
6137
|
+
console.log('token', req.cookies, res.cookie);
|
|
6125
6138
|
// 获取查询参数
|
|
6126
6139
|
const param = parsedUrl.query;
|
|
6127
6140
|
let body;
|
|
@@ -6141,10 +6154,287 @@ const handleServer = async (req, res) => {
|
|
|
6141
6154
|
token,
|
|
6142
6155
|
...param,
|
|
6143
6156
|
...body,
|
|
6157
|
+
cookies,
|
|
6144
6158
|
};
|
|
6145
6159
|
return data;
|
|
6146
6160
|
};
|
|
6147
6161
|
|
|
6162
|
+
var dist = {};
|
|
6163
|
+
|
|
6164
|
+
var hasRequiredDist;
|
|
6165
|
+
|
|
6166
|
+
function requireDist () {
|
|
6167
|
+
if (hasRequiredDist) return dist;
|
|
6168
|
+
hasRequiredDist = 1;
|
|
6169
|
+
Object.defineProperty(dist, "__esModule", { value: true });
|
|
6170
|
+
dist.parse = parse;
|
|
6171
|
+
dist.serialize = serialize;
|
|
6172
|
+
/**
|
|
6173
|
+
* RegExp to match cookie-name in RFC 6265 sec 4.1.1
|
|
6174
|
+
* This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
|
|
6175
|
+
* which has been replaced by the token definition in RFC 7230 appendix B.
|
|
6176
|
+
*
|
|
6177
|
+
* cookie-name = token
|
|
6178
|
+
* token = 1*tchar
|
|
6179
|
+
* tchar = "!" / "#" / "$" / "%" / "&" / "'" /
|
|
6180
|
+
* "*" / "+" / "-" / "." / "^" / "_" /
|
|
6181
|
+
* "`" / "|" / "~" / DIGIT / ALPHA
|
|
6182
|
+
*
|
|
6183
|
+
* Note: Allowing more characters - https://github.com/jshttp/cookie/issues/191
|
|
6184
|
+
* Allow same range as cookie value, except `=`, which delimits end of name.
|
|
6185
|
+
*/
|
|
6186
|
+
const cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
|
|
6187
|
+
/**
|
|
6188
|
+
* RegExp to match cookie-value in RFC 6265 sec 4.1.1
|
|
6189
|
+
*
|
|
6190
|
+
* cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
|
|
6191
|
+
* cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
|
6192
|
+
* ; US-ASCII characters excluding CTLs,
|
|
6193
|
+
* ; whitespace DQUOTE, comma, semicolon,
|
|
6194
|
+
* ; and backslash
|
|
6195
|
+
*
|
|
6196
|
+
* Allowing more characters: https://github.com/jshttp/cookie/issues/191
|
|
6197
|
+
* Comma, backslash, and DQUOTE are not part of the parsing algorithm.
|
|
6198
|
+
*/
|
|
6199
|
+
const cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/;
|
|
6200
|
+
/**
|
|
6201
|
+
* RegExp to match domain-value in RFC 6265 sec 4.1.1
|
|
6202
|
+
*
|
|
6203
|
+
* domain-value = <subdomain>
|
|
6204
|
+
* ; defined in [RFC1034], Section 3.5, as
|
|
6205
|
+
* ; enhanced by [RFC1123], Section 2.1
|
|
6206
|
+
* <subdomain> = <label> | <subdomain> "." <label>
|
|
6207
|
+
* <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ]
|
|
6208
|
+
* Labels must be 63 characters or less.
|
|
6209
|
+
* 'let-dig' not 'letter' in the first char, per RFC1123
|
|
6210
|
+
* <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
|
6211
|
+
* <let-dig-hyp> = <let-dig> | "-"
|
|
6212
|
+
* <let-dig> = <letter> | <digit>
|
|
6213
|
+
* <letter> = any one of the 52 alphabetic characters A through Z in
|
|
6214
|
+
* upper case and a through z in lower case
|
|
6215
|
+
* <digit> = any one of the ten digits 0 through 9
|
|
6216
|
+
*
|
|
6217
|
+
* Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
|
|
6218
|
+
*
|
|
6219
|
+
* > (Note that a leading %x2E ("."), if present, is ignored even though that
|
|
6220
|
+
* character is not permitted, but a trailing %x2E ("."), if present, will
|
|
6221
|
+
* cause the user agent to ignore the attribute.)
|
|
6222
|
+
*/
|
|
6223
|
+
const domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
|
6224
|
+
/**
|
|
6225
|
+
* RegExp to match path-value in RFC 6265 sec 4.1.1
|
|
6226
|
+
*
|
|
6227
|
+
* path-value = <any CHAR except CTLs or ";">
|
|
6228
|
+
* CHAR = %x01-7F
|
|
6229
|
+
* ; defined in RFC 5234 appendix B.1
|
|
6230
|
+
*/
|
|
6231
|
+
const pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
|
|
6232
|
+
const __toString = Object.prototype.toString;
|
|
6233
|
+
const NullObject = /* @__PURE__ */ (() => {
|
|
6234
|
+
const C = function () { };
|
|
6235
|
+
C.prototype = Object.create(null);
|
|
6236
|
+
return C;
|
|
6237
|
+
})();
|
|
6238
|
+
/**
|
|
6239
|
+
* Parse a cookie header.
|
|
6240
|
+
*
|
|
6241
|
+
* Parse the given cookie header string into an object
|
|
6242
|
+
* The object has the various cookies as keys(names) => values
|
|
6243
|
+
*/
|
|
6244
|
+
function parse(str, options) {
|
|
6245
|
+
const obj = new NullObject();
|
|
6246
|
+
const len = str.length;
|
|
6247
|
+
// RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
|
|
6248
|
+
if (len < 2)
|
|
6249
|
+
return obj;
|
|
6250
|
+
const dec = options?.decode || decode;
|
|
6251
|
+
let index = 0;
|
|
6252
|
+
do {
|
|
6253
|
+
const eqIdx = str.indexOf("=", index);
|
|
6254
|
+
if (eqIdx === -1)
|
|
6255
|
+
break; // No more cookie pairs.
|
|
6256
|
+
const colonIdx = str.indexOf(";", index);
|
|
6257
|
+
const endIdx = colonIdx === -1 ? len : colonIdx;
|
|
6258
|
+
if (eqIdx > endIdx) {
|
|
6259
|
+
// backtrack on prior semicolon
|
|
6260
|
+
index = str.lastIndexOf(";", eqIdx - 1) + 1;
|
|
6261
|
+
continue;
|
|
6262
|
+
}
|
|
6263
|
+
const keyStartIdx = startIndex(str, index, eqIdx);
|
|
6264
|
+
const keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
|
|
6265
|
+
const key = str.slice(keyStartIdx, keyEndIdx);
|
|
6266
|
+
// only assign once
|
|
6267
|
+
if (obj[key] === undefined) {
|
|
6268
|
+
let valStartIdx = startIndex(str, eqIdx + 1, endIdx);
|
|
6269
|
+
let valEndIdx = endIndex(str, endIdx, valStartIdx);
|
|
6270
|
+
const value = dec(str.slice(valStartIdx, valEndIdx));
|
|
6271
|
+
obj[key] = value;
|
|
6272
|
+
}
|
|
6273
|
+
index = endIdx + 1;
|
|
6274
|
+
} while (index < len);
|
|
6275
|
+
return obj;
|
|
6276
|
+
}
|
|
6277
|
+
function startIndex(str, index, max) {
|
|
6278
|
+
do {
|
|
6279
|
+
const code = str.charCodeAt(index);
|
|
6280
|
+
if (code !== 0x20 /* */ && code !== 0x09 /* \t */)
|
|
6281
|
+
return index;
|
|
6282
|
+
} while (++index < max);
|
|
6283
|
+
return max;
|
|
6284
|
+
}
|
|
6285
|
+
function endIndex(str, index, min) {
|
|
6286
|
+
while (index > min) {
|
|
6287
|
+
const code = str.charCodeAt(--index);
|
|
6288
|
+
if (code !== 0x20 /* */ && code !== 0x09 /* \t */)
|
|
6289
|
+
return index + 1;
|
|
6290
|
+
}
|
|
6291
|
+
return min;
|
|
6292
|
+
}
|
|
6293
|
+
/**
|
|
6294
|
+
* Serialize data into a cookie header.
|
|
6295
|
+
*
|
|
6296
|
+
* Serialize a name value pair into a cookie string suitable for
|
|
6297
|
+
* http headers. An optional options object specifies cookie parameters.
|
|
6298
|
+
*
|
|
6299
|
+
* serialize('foo', 'bar', { httpOnly: true })
|
|
6300
|
+
* => "foo=bar; httpOnly"
|
|
6301
|
+
*/
|
|
6302
|
+
function serialize(name, val, options) {
|
|
6303
|
+
const enc = options?.encode || encodeURIComponent;
|
|
6304
|
+
if (!cookieNameRegExp.test(name)) {
|
|
6305
|
+
throw new TypeError(`argument name is invalid: ${name}`);
|
|
6306
|
+
}
|
|
6307
|
+
const value = enc(val);
|
|
6308
|
+
if (!cookieValueRegExp.test(value)) {
|
|
6309
|
+
throw new TypeError(`argument val is invalid: ${val}`);
|
|
6310
|
+
}
|
|
6311
|
+
let str = name + "=" + value;
|
|
6312
|
+
if (!options)
|
|
6313
|
+
return str;
|
|
6314
|
+
if (options.maxAge !== undefined) {
|
|
6315
|
+
if (!Number.isInteger(options.maxAge)) {
|
|
6316
|
+
throw new TypeError(`option maxAge is invalid: ${options.maxAge}`);
|
|
6317
|
+
}
|
|
6318
|
+
str += "; Max-Age=" + options.maxAge;
|
|
6319
|
+
}
|
|
6320
|
+
if (options.domain) {
|
|
6321
|
+
if (!domainValueRegExp.test(options.domain)) {
|
|
6322
|
+
throw new TypeError(`option domain is invalid: ${options.domain}`);
|
|
6323
|
+
}
|
|
6324
|
+
str += "; Domain=" + options.domain;
|
|
6325
|
+
}
|
|
6326
|
+
if (options.path) {
|
|
6327
|
+
if (!pathValueRegExp.test(options.path)) {
|
|
6328
|
+
throw new TypeError(`option path is invalid: ${options.path}`);
|
|
6329
|
+
}
|
|
6330
|
+
str += "; Path=" + options.path;
|
|
6331
|
+
}
|
|
6332
|
+
if (options.expires) {
|
|
6333
|
+
if (!isDate(options.expires) ||
|
|
6334
|
+
!Number.isFinite(options.expires.valueOf())) {
|
|
6335
|
+
throw new TypeError(`option expires is invalid: ${options.expires}`);
|
|
6336
|
+
}
|
|
6337
|
+
str += "; Expires=" + options.expires.toUTCString();
|
|
6338
|
+
}
|
|
6339
|
+
if (options.httpOnly) {
|
|
6340
|
+
str += "; HttpOnly";
|
|
6341
|
+
}
|
|
6342
|
+
if (options.secure) {
|
|
6343
|
+
str += "; Secure";
|
|
6344
|
+
}
|
|
6345
|
+
if (options.partitioned) {
|
|
6346
|
+
str += "; Partitioned";
|
|
6347
|
+
}
|
|
6348
|
+
if (options.priority) {
|
|
6349
|
+
const priority = typeof options.priority === "string"
|
|
6350
|
+
? options.priority.toLowerCase()
|
|
6351
|
+
: undefined;
|
|
6352
|
+
switch (priority) {
|
|
6353
|
+
case "low":
|
|
6354
|
+
str += "; Priority=Low";
|
|
6355
|
+
break;
|
|
6356
|
+
case "medium":
|
|
6357
|
+
str += "; Priority=Medium";
|
|
6358
|
+
break;
|
|
6359
|
+
case "high":
|
|
6360
|
+
str += "; Priority=High";
|
|
6361
|
+
break;
|
|
6362
|
+
default:
|
|
6363
|
+
throw new TypeError(`option priority is invalid: ${options.priority}`);
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
if (options.sameSite) {
|
|
6367
|
+
const sameSite = typeof options.sameSite === "string"
|
|
6368
|
+
? options.sameSite.toLowerCase()
|
|
6369
|
+
: options.sameSite;
|
|
6370
|
+
switch (sameSite) {
|
|
6371
|
+
case true:
|
|
6372
|
+
case "strict":
|
|
6373
|
+
str += "; SameSite=Strict";
|
|
6374
|
+
break;
|
|
6375
|
+
case "lax":
|
|
6376
|
+
str += "; SameSite=Lax";
|
|
6377
|
+
break;
|
|
6378
|
+
case "none":
|
|
6379
|
+
str += "; SameSite=None";
|
|
6380
|
+
break;
|
|
6381
|
+
default:
|
|
6382
|
+
throw new TypeError(`option sameSite is invalid: ${options.sameSite}`);
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6385
|
+
return str;
|
|
6386
|
+
}
|
|
6387
|
+
/**
|
|
6388
|
+
* URL-decode string value. Optimized to skip native call when no %.
|
|
6389
|
+
*/
|
|
6390
|
+
function decode(str) {
|
|
6391
|
+
if (str.indexOf("%") === -1)
|
|
6392
|
+
return str;
|
|
6393
|
+
try {
|
|
6394
|
+
return decodeURIComponent(str);
|
|
6395
|
+
}
|
|
6396
|
+
catch (e) {
|
|
6397
|
+
return str;
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
/**
|
|
6401
|
+
* Determine if value is a Date.
|
|
6402
|
+
*/
|
|
6403
|
+
function isDate(val) {
|
|
6404
|
+
return __toString.call(val) === "[object Date]";
|
|
6405
|
+
}
|
|
6406
|
+
|
|
6407
|
+
return dist;
|
|
6408
|
+
}
|
|
6409
|
+
|
|
6410
|
+
var distExports = requireDist();
|
|
6411
|
+
|
|
6412
|
+
// 实现函数
|
|
6413
|
+
function createHandleCtx(req, res) {
|
|
6414
|
+
// 用于存储所有的 Set-Cookie 字符串
|
|
6415
|
+
const cookies = [];
|
|
6416
|
+
let handReq = req;
|
|
6417
|
+
let handRes = res;
|
|
6418
|
+
// 扩展 res.cookie 方法
|
|
6419
|
+
const cookieFn = (name, value, options = {}, end = true) => {
|
|
6420
|
+
// 序列化新的 Cookie
|
|
6421
|
+
const serializedCookie = distExports.serialize(name, value, options);
|
|
6422
|
+
cookies.push(serializedCookie); // 将新的 Cookie 添加到数组
|
|
6423
|
+
if (end) {
|
|
6424
|
+
// 如果设置了 end 参数,则立即设置到响应头
|
|
6425
|
+
res.setHeader('Set-Cookie', cookies);
|
|
6426
|
+
}
|
|
6427
|
+
};
|
|
6428
|
+
// 解析请求中的现有 Cookie
|
|
6429
|
+
const parsedCookies = distExports.parse(req.headers.cookie || '');
|
|
6430
|
+
handReq.cookies = parsedCookies;
|
|
6431
|
+
handRes.cookie = cookieFn;
|
|
6432
|
+
// 返回扩展的上下文
|
|
6433
|
+
return {
|
|
6434
|
+
req: handReq,
|
|
6435
|
+
res: handRes,
|
|
6436
|
+
};
|
|
6437
|
+
}
|
|
6148
6438
|
const resultError = (error, code = 500) => {
|
|
6149
6439
|
const r = {
|
|
6150
6440
|
code: code,
|
|
@@ -6159,7 +6449,7 @@ class Server {
|
|
|
6159
6449
|
_callback;
|
|
6160
6450
|
cors;
|
|
6161
6451
|
hasOn = false;
|
|
6162
|
-
|
|
6452
|
+
httpType = 'http';
|
|
6163
6453
|
options = {
|
|
6164
6454
|
key: '',
|
|
6165
6455
|
cert: '',
|
|
@@ -6168,7 +6458,7 @@ class Server {
|
|
|
6168
6458
|
this.path = opts?.path || '/api/router';
|
|
6169
6459
|
this.handle = opts?.handle;
|
|
6170
6460
|
this.cors = opts?.cors;
|
|
6171
|
-
this.
|
|
6461
|
+
this.httpType = opts?.httpType || 'http';
|
|
6172
6462
|
this.options = {
|
|
6173
6463
|
key: opts?.httpsKey || '',
|
|
6174
6464
|
cert: opts?.httpsCert || '',
|
|
@@ -6182,13 +6472,26 @@ class Server {
|
|
|
6182
6472
|
}
|
|
6183
6473
|
createServer() {
|
|
6184
6474
|
let server;
|
|
6185
|
-
|
|
6475
|
+
const httpType = this.httpType;
|
|
6476
|
+
if (httpType === 'https') {
|
|
6186
6477
|
if (this.options.key && this.options.cert) {
|
|
6187
6478
|
server = https.createServer({
|
|
6188
6479
|
key: this.options.key,
|
|
6189
6480
|
cert: this.options.cert,
|
|
6190
6481
|
});
|
|
6191
|
-
|
|
6482
|
+
return server;
|
|
6483
|
+
}
|
|
6484
|
+
else {
|
|
6485
|
+
console.error('https key and cert is required');
|
|
6486
|
+
console.log('downgrade to http');
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6489
|
+
else if (httpType === 'http2') {
|
|
6490
|
+
if (this.options.key && this.options.cert) {
|
|
6491
|
+
server = http2.createSecureServer({
|
|
6492
|
+
key: this.options.key,
|
|
6493
|
+
cert: this.options.cert,
|
|
6494
|
+
});
|
|
6192
6495
|
return server;
|
|
6193
6496
|
}
|
|
6194
6497
|
else {
|
|
@@ -6211,6 +6514,7 @@ class Server {
|
|
|
6211
6514
|
const handle = this.handle;
|
|
6212
6515
|
const cors = this.cors;
|
|
6213
6516
|
const _callback = async (req, res) => {
|
|
6517
|
+
// only handle /api/router
|
|
6214
6518
|
if (req.url === '/favicon.ico') {
|
|
6215
6519
|
return;
|
|
6216
6520
|
}
|
|
@@ -6235,19 +6539,22 @@ class Server {
|
|
|
6235
6539
|
return;
|
|
6236
6540
|
}
|
|
6237
6541
|
}
|
|
6238
|
-
res.writeHead(200); //
|
|
6542
|
+
// res.writeHead(200); // 设置响应头,给予其他任何listen 知道headersSent,它已经被响应了
|
|
6239
6543
|
const url = req.url;
|
|
6240
6544
|
if (!url.startsWith(path)) {
|
|
6241
6545
|
res.end(resultError(`not path:[${path}]`));
|
|
6242
6546
|
return;
|
|
6243
6547
|
}
|
|
6244
|
-
const messages = await handleServer(req);
|
|
6548
|
+
const messages = await handleServer(req, res);
|
|
6245
6549
|
if (!handle) {
|
|
6246
6550
|
res.end(resultError('no handle'));
|
|
6247
6551
|
return;
|
|
6248
6552
|
}
|
|
6249
6553
|
try {
|
|
6250
|
-
const end = await handle(messages);
|
|
6554
|
+
const end = await handle(messages, { req, res });
|
|
6555
|
+
if (res.writableEnded) {
|
|
6556
|
+
return;
|
|
6557
|
+
}
|
|
6251
6558
|
if (typeof end === 'string') {
|
|
6252
6559
|
res.end(end);
|
|
6253
6560
|
}
|
|
@@ -6453,6 +6760,9 @@ class WsServer extends WsServerBase {
|
|
|
6453
6760
|
}
|
|
6454
6761
|
}
|
|
6455
6762
|
|
|
6763
|
+
/**
|
|
6764
|
+
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
|
6765
|
+
*/
|
|
6456
6766
|
class App {
|
|
6457
6767
|
router;
|
|
6458
6768
|
server;
|
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.6-alpha-
|
|
4
|
+
"version": "0.0.6-alpha-3",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@types/lodash-es": "^4.17.12",
|
|
27
27
|
"@types/node": "^22.8.6",
|
|
28
28
|
"@types/ws": "^8.5.13",
|
|
29
|
+
"cookie": "^1.0.2",
|
|
29
30
|
"lodash-es": "^4.17.21",
|
|
30
31
|
"nanoid": "^5.0.8",
|
|
31
32
|
"rollup": "^4.24.3",
|