@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.
@@ -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
@@ -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
- const context = { ...ctx };
5906
- const res = await router.parse(msg, context);
5907
- if (wrapperFn) {
5908
- res.data = res.body;
5909
- return wrapperFn(res, context);
5910
- }
5911
- const { code, body, message } = res;
5912
- return { code, data: body, message };
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
- declare class App<T = {}> {
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 -= 0));
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
- const context = { ...ctx };
5926
- const res = await router.parse(msg, context);
5927
- if (wrapperFn) {
5928
- res.data = res.body;
5929
- return wrapperFn(res, context);
5930
- }
5931
- const { code, body, message } = res;
5932
- return { code, data: body, message };
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-2",
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",