@kevisual/router 0.0.6-alpha-2 → 0.0.6-alpha-4
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 +18 -10
- package/dist/router-browser.js +15 -10
- package/dist/router.d.ts +47 -16
- package/dist/router.js +308 -13
- 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;
|
|
@@ -312,10 +320,10 @@ declare class QueryRouterServer extends QueryRouter {
|
|
|
312
320
|
use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void;
|
|
313
321
|
addRoute(route: Route): void;
|
|
314
322
|
Route: typeof Route;
|
|
315
|
-
route(opts: RouteOpts): Route
|
|
316
|
-
route(path: string, key?: string): Route
|
|
317
|
-
route(path: string, opts?: RouteOpts): Route
|
|
318
|
-
route(path: string, key?: string, opts?: RouteOpts): Route
|
|
323
|
+
route(opts: RouteOpts): Route<Required<RouteContext>>;
|
|
324
|
+
route(path: string, key?: string): Route<Required<RouteContext>>;
|
|
325
|
+
route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
|
326
|
+
route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
|
319
327
|
/**
|
|
320
328
|
* 等于queryRoute,但是调用了handle
|
|
321
329
|
* @param param0
|
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
|
@@ -3,6 +3,7 @@ export { Schema } from 'zod';
|
|
|
3
3
|
import http, { IncomingMessage, ServerResponse } from 'http';
|
|
4
4
|
import https from 'https';
|
|
5
5
|
import http2 from 'http2';
|
|
6
|
+
import * as cookie from 'cookie';
|
|
6
7
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
7
8
|
|
|
8
9
|
type BaseRule = {
|
|
@@ -122,7 +123,9 @@ type RouteOpts = {
|
|
|
122
123
|
type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'verify' | 'verifyKey' | 'nextRoute'>;
|
|
123
124
|
declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"];
|
|
124
125
|
type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
|
|
125
|
-
declare class Route {
|
|
126
|
+
declare class Route<U = {
|
|
127
|
+
[key: string]: any;
|
|
128
|
+
}> {
|
|
126
129
|
path?: string;
|
|
127
130
|
key?: string;
|
|
128
131
|
id?: string;
|
|
@@ -184,13 +187,13 @@ declare class Route {
|
|
|
184
187
|
} = RouterContextT>(opts: DefineRouteOpts): this;
|
|
185
188
|
define<T extends {
|
|
186
189
|
[key: string]: any;
|
|
187
|
-
} = RouterContextT>(fn: Run<T>): this;
|
|
190
|
+
} = RouterContextT>(fn: Run<T & U>): this;
|
|
188
191
|
define<T extends {
|
|
189
192
|
[key: string]: any;
|
|
190
|
-
} = RouterContextT>(key: string, fn: Run<T>): this;
|
|
193
|
+
} = RouterContextT>(key: string, fn: Run<T & U>): this;
|
|
191
194
|
define<T extends {
|
|
192
195
|
[key: string]: any;
|
|
193
|
-
} = RouterContextT>(path: string, key: string, fn: Run<T>): this;
|
|
196
|
+
} = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
|
|
194
197
|
addTo(router: QueryRouter | {
|
|
195
198
|
add: (route: Route) => void;
|
|
196
199
|
[key: string]: any;
|
|
@@ -274,7 +277,7 @@ declare class QueryRouter {
|
|
|
274
277
|
path: string;
|
|
275
278
|
key?: string;
|
|
276
279
|
[key: string]: any;
|
|
277
|
-
}) => Promise<{
|
|
280
|
+
}, handleContext?: RouteContext) => Promise<{
|
|
278
281
|
[key: string]: any;
|
|
279
282
|
code: string;
|
|
280
283
|
data?: any;
|
|
@@ -283,8 +286,14 @@ declare class QueryRouter {
|
|
|
283
286
|
code: any;
|
|
284
287
|
data: any;
|
|
285
288
|
message: any;
|
|
289
|
+
} | {
|
|
290
|
+
code: number;
|
|
291
|
+
message: any;
|
|
292
|
+
data?: undefined;
|
|
286
293
|
}>;
|
|
287
|
-
exportRoutes(): Route
|
|
294
|
+
exportRoutes(): Route<{
|
|
295
|
+
[key: string]: any;
|
|
296
|
+
}>[];
|
|
288
297
|
importRoutes(routes: Route[]): void;
|
|
289
298
|
importRouter(router: QueryRouter): void;
|
|
290
299
|
throw(code?: number | string, message?: string, tips?: string): void;
|
|
@@ -316,10 +325,10 @@ declare class QueryRouterServer extends QueryRouter {
|
|
|
316
325
|
use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void;
|
|
317
326
|
addRoute(route: Route): void;
|
|
318
327
|
Route: typeof Route;
|
|
319
|
-
route(opts: RouteOpts): Route
|
|
320
|
-
route(path: string, key?: string): Route
|
|
321
|
-
route(path: string, opts?: RouteOpts): Route
|
|
322
|
-
route(path: string, key?: string, opts?: RouteOpts): Route
|
|
328
|
+
route(opts: RouteOpts): Route<Required<RouteContext>>;
|
|
329
|
+
route(path: string, key?: string): Route<Required<RouteContext>>;
|
|
330
|
+
route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
|
331
|
+
route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
|
|
323
332
|
/**
|
|
324
333
|
* 等于queryRoute,但是调用了handle
|
|
325
334
|
* @param param0
|
|
@@ -363,6 +372,18 @@ declare class QueryConnect {
|
|
|
363
372
|
}
|
|
364
373
|
|
|
365
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
|
+
};
|
|
366
387
|
type Cors = {
|
|
367
388
|
/**
|
|
368
389
|
* @default '*''
|
|
@@ -377,6 +398,9 @@ type ServerOpts = {
|
|
|
377
398
|
path: string;
|
|
378
399
|
key?: string;
|
|
379
400
|
[key: string]: any;
|
|
401
|
+
}, ctx?: {
|
|
402
|
+
req: http.IncomingMessage;
|
|
403
|
+
res: http.ServerResponse;
|
|
380
404
|
}) => any;
|
|
381
405
|
cors?: Cors;
|
|
382
406
|
httpType?: 'http' | 'https' | 'http2';
|
|
@@ -427,6 +451,7 @@ declare class Server {
|
|
|
427
451
|
* @returns
|
|
428
452
|
*/
|
|
429
453
|
declare const handleServer: (req: IncomingMessage, res: ServerResponse) => Promise<{
|
|
454
|
+
cookies: Record<string, string>;
|
|
430
455
|
token: string;
|
|
431
456
|
}>;
|
|
432
457
|
|
|
@@ -506,7 +531,11 @@ type AppOptions<T = {}> = {
|
|
|
506
531
|
path?: string;
|
|
507
532
|
};
|
|
508
533
|
};
|
|
509
|
-
|
|
534
|
+
type AppReqRes = HandleCtx;
|
|
535
|
+
/**
|
|
536
|
+
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
|
537
|
+
*/
|
|
538
|
+
declare class App<T = {}, U = AppReqRes> {
|
|
510
539
|
router: QueryRouter;
|
|
511
540
|
server: Server;
|
|
512
541
|
io: WsServer;
|
|
@@ -523,10 +552,10 @@ declare class App<T = {}> {
|
|
|
523
552
|
addRoute(route: Route): void;
|
|
524
553
|
add: (route: Route) => void;
|
|
525
554
|
Route: typeof Route;
|
|
526
|
-
route(opts: RouteOpts): Route
|
|
527
|
-
route(path: string, key?: string): Route
|
|
528
|
-
route(path: string, opts?: RouteOpts): Route
|
|
529
|
-
route(path: string, key?: string, opts?: RouteOpts): Route
|
|
555
|
+
route(opts: RouteOpts): Route<U>;
|
|
556
|
+
route(path: string, key?: string): Route<U>;
|
|
557
|
+
route(path: string, opts?: RouteOpts): Route<U>;
|
|
558
|
+
route(path: string, key?: string, opts?: RouteOpts): Route<U>;
|
|
530
559
|
call(message: {
|
|
531
560
|
path: string;
|
|
532
561
|
key?: string;
|
|
@@ -541,7 +570,9 @@ declare class App<T = {}> {
|
|
|
541
570
|
data: any;
|
|
542
571
|
message: any;
|
|
543
572
|
}>;
|
|
544
|
-
exportRoutes(): Route
|
|
573
|
+
exportRoutes(): Route<{
|
|
574
|
+
[key: string]: any;
|
|
575
|
+
}>[];
|
|
545
576
|
importRoutes(routes: any[]): void;
|
|
546
577
|
importApp(app: App): void;
|
|
547
578
|
throw(code?: number | string, message?: string, tips?: string): void;
|
package/dist/router.js
CHANGED
|
@@ -22,7 +22,7 @@ function fillPool(bytes) {
|
|
|
22
22
|
poolOffset += bytes;
|
|
23
23
|
}
|
|
24
24
|
function nanoid(size = 21) {
|
|
25
|
-
fillPool((size
|
|
25
|
+
fillPool((size |= 0));
|
|
26
26
|
let id = '';
|
|
27
27
|
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
28
28
|
id += urlAlphabet[pool[i] & 63];
|
|
@@ -5921,15 +5921,20 @@ class QueryRouter {
|
|
|
5921
5921
|
});
|
|
5922
5922
|
}
|
|
5923
5923
|
getHandle(router, wrapperFn, ctx) {
|
|
5924
|
-
return async (msg) => {
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
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
|
+
}
|
|
5933
5938
|
};
|
|
5934
5939
|
}
|
|
5935
5940
|
exportRoutes() {
|
|
@@ -6120,9 +6125,16 @@ const handleServer = async (req, res) => {
|
|
|
6120
6125
|
const parsedUrl = url.parse(req.url, true);
|
|
6121
6126
|
// 获取token
|
|
6122
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
|
+
}
|
|
6123
6133
|
if (token) {
|
|
6124
6134
|
token = token.replace('Bearer ', '');
|
|
6125
6135
|
}
|
|
6136
|
+
//@ts-ignore
|
|
6137
|
+
console.log('token', req.cookies, res.cookie);
|
|
6126
6138
|
// 获取查询参数
|
|
6127
6139
|
const param = parsedUrl.query;
|
|
6128
6140
|
let body;
|
|
@@ -6142,10 +6154,287 @@ const handleServer = async (req, res) => {
|
|
|
6142
6154
|
token,
|
|
6143
6155
|
...param,
|
|
6144
6156
|
...body,
|
|
6157
|
+
cookies,
|
|
6145
6158
|
};
|
|
6146
6159
|
return data;
|
|
6147
6160
|
};
|
|
6148
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
|
+
}
|
|
6149
6438
|
const resultError = (error, code = 500) => {
|
|
6150
6439
|
const r = {
|
|
6151
6440
|
code: code,
|
|
@@ -6250,19 +6539,22 @@ class Server {
|
|
|
6250
6539
|
return;
|
|
6251
6540
|
}
|
|
6252
6541
|
}
|
|
6253
|
-
res.writeHead(200); // 设置响应头,给予其他任何listen 知道headersSent,它已经被响应了
|
|
6542
|
+
// res.writeHead(200); // 设置响应头,给予其他任何listen 知道headersSent,它已经被响应了
|
|
6254
6543
|
const url = req.url;
|
|
6255
6544
|
if (!url.startsWith(path)) {
|
|
6256
6545
|
res.end(resultError(`not path:[${path}]`));
|
|
6257
6546
|
return;
|
|
6258
6547
|
}
|
|
6259
|
-
const messages = await handleServer(req);
|
|
6548
|
+
const messages = await handleServer(req, res);
|
|
6260
6549
|
if (!handle) {
|
|
6261
6550
|
res.end(resultError('no handle'));
|
|
6262
6551
|
return;
|
|
6263
6552
|
}
|
|
6264
6553
|
try {
|
|
6265
|
-
const end = await handle(messages);
|
|
6554
|
+
const end = await handle(messages, { req, res });
|
|
6555
|
+
if (res.writableEnded) {
|
|
6556
|
+
return;
|
|
6557
|
+
}
|
|
6266
6558
|
if (typeof end === 'string') {
|
|
6267
6559
|
res.end(end);
|
|
6268
6560
|
}
|
|
@@ -6468,6 +6760,9 @@ class WsServer extends WsServerBase {
|
|
|
6468
6760
|
}
|
|
6469
6761
|
}
|
|
6470
6762
|
|
|
6763
|
+
/**
|
|
6764
|
+
* 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理
|
|
6765
|
+
*/
|
|
6471
6766
|
class App {
|
|
6472
6767
|
router;
|
|
6473
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-4",
|
|
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",
|