@kevisual/router 0.0.45 → 0.0.47
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.d.ts +22 -21
- package/dist/router.js +29 -17
- package/package.json +1 -1
- package/src/index.ts +12 -1
- package/src/server/server-base.ts +18 -7
- package/src/server/server-bun.ts +1 -9
- package/src/server/server-type.ts +15 -4
- package/src/server/ws-server.ts +12 -2
package/dist/router.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import https from 'node:https';
|
|
|
4
4
|
import http2 from 'node:http2';
|
|
5
5
|
import EventEmitter from 'node:events';
|
|
6
6
|
import { EventEmitter as EventEmitter$1 } from 'events';
|
|
7
|
-
import { WebSocketServer
|
|
7
|
+
import { WebSocketServer } from 'ws';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import { IncomingMessage as IncomingMessage$1, ServerResponse as ServerResponse$1 } from 'http';
|
|
10
10
|
import { RouteOpts as RouteOpts$1, QueryRouterServer as QueryRouterServer$1, RouteMiddleware as RouteMiddleware$1, Run as Run$1 } from '@kevisual/router';
|
|
@@ -411,7 +411,7 @@ interface ServerType {
|
|
|
411
411
|
server?: any;
|
|
412
412
|
handle: ServerOpts['handle'];
|
|
413
413
|
setHandle(handle?: any): void;
|
|
414
|
-
listeners: Listener
|
|
414
|
+
listeners: Listener[];
|
|
415
415
|
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
|
|
416
416
|
listen(port: number, hostname?: string, listeningListener?: () => void): void;
|
|
417
417
|
listen(port: number, backlog?: number, listeningListener?: () => void): void;
|
|
@@ -427,6 +427,7 @@ interface ServerType {
|
|
|
427
427
|
*/
|
|
428
428
|
on(listener: OnListener): void;
|
|
429
429
|
onWebSocket({ ws, message, pathname, token, id }: OnWebSocketOptions): void;
|
|
430
|
+
onWsClose(ws: WS): void;
|
|
430
431
|
}
|
|
431
432
|
type OnWebSocketOptions = {
|
|
432
433
|
ws: WS;
|
|
@@ -439,14 +440,24 @@ type OnWebSocketFn = (options: OnWebSocketOptions) => Promise<void> | void;
|
|
|
439
440
|
type WS = {
|
|
440
441
|
send: (data: any) => void;
|
|
441
442
|
close: (code?: number, reason?: string) => void;
|
|
443
|
+
data?: {
|
|
444
|
+
url: URL;
|
|
445
|
+
pathname: string;
|
|
446
|
+
token?: string;
|
|
447
|
+
id?: string;
|
|
448
|
+
/**
|
|
449
|
+
* 鉴权后的获取的信息
|
|
450
|
+
*/
|
|
451
|
+
userApp?: string;
|
|
452
|
+
};
|
|
442
453
|
};
|
|
443
|
-
type Listener
|
|
454
|
+
type Listener = {
|
|
444
455
|
id?: string;
|
|
445
456
|
io?: boolean;
|
|
446
457
|
path?: string;
|
|
447
|
-
|
|
458
|
+
func: WebSocketListenerFun | HttpListenerFun;
|
|
448
459
|
};
|
|
449
|
-
type
|
|
460
|
+
type WebSocketListenerFun = (req: WebSocketReq, res: WebSocketRes) => Promise<void> | void;
|
|
450
461
|
type HttpListenerFun = (req: RouterReq, res: RouterRes) => Promise<void> | void;
|
|
451
462
|
type WebSocketReq = {
|
|
452
463
|
emitter?: EventEmitter;
|
|
@@ -459,8 +470,8 @@ type WebSocketReq = {
|
|
|
459
470
|
type WebSocketRes = {
|
|
460
471
|
end: (data: any) => void;
|
|
461
472
|
};
|
|
462
|
-
type ListenerFun =
|
|
463
|
-
type OnListener = Listener
|
|
473
|
+
type ListenerFun = WebSocketListenerFun | HttpListenerFun;
|
|
474
|
+
type OnListener = Listener | ListenerFun | (Listener | ListenerFun)[];
|
|
464
475
|
type RouterReq<T = {}> = {
|
|
465
476
|
url: string;
|
|
466
477
|
method: string;
|
|
@@ -604,7 +615,7 @@ declare class ServerBase implements ServerType {
|
|
|
604
615
|
handle: ServerOpts['handle'];
|
|
605
616
|
_callback: any;
|
|
606
617
|
cors: Cors$1;
|
|
607
|
-
listeners: Listener
|
|
618
|
+
listeners: Listener[];
|
|
608
619
|
emitter: EventEmitter$1<any>;
|
|
609
620
|
constructor(opts?: ServerOpts);
|
|
610
621
|
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
|
|
@@ -632,25 +643,15 @@ declare class ServerBase implements ServerType {
|
|
|
632
643
|
createCallback(): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
633
644
|
on(listener: OnListener): void;
|
|
634
645
|
onWebSocket({ ws, message, pathname, token, id }: OnWebSocketOptions): Promise<void>;
|
|
646
|
+
onWsClose(ws: WS): Promise<void>;
|
|
635
647
|
}
|
|
636
648
|
|
|
637
649
|
type WsServerBaseOpts = {
|
|
638
650
|
wss?: WebSocketServer | null;
|
|
639
651
|
path?: string;
|
|
640
652
|
};
|
|
641
|
-
type ListenerFn = (message: {
|
|
642
|
-
data: Record<string, any>;
|
|
643
|
-
ws: WebSocket;
|
|
644
|
-
end: (data: any) => any;
|
|
645
|
-
}) => Promise<any>;
|
|
646
|
-
type Listener<T = 'router' | 'chat' | 'ai'> = {
|
|
647
|
-
type: T;
|
|
648
|
-
path?: string;
|
|
649
|
-
listener: ListenerFn;
|
|
650
|
-
};
|
|
651
653
|
declare class WsServerBase {
|
|
652
654
|
wss: WebSocketServer | null;
|
|
653
|
-
listeners: Listener[];
|
|
654
655
|
listening: boolean;
|
|
655
656
|
server: ServerType;
|
|
656
657
|
constructor(opts: WsServerBaseOpts);
|
|
@@ -677,7 +678,7 @@ declare class ServerNode extends ServerBase implements ServerType {
|
|
|
677
678
|
_callback: any;
|
|
678
679
|
cors: Cors;
|
|
679
680
|
private httpType;
|
|
680
|
-
listeners: Listener
|
|
681
|
+
listeners: Listener[];
|
|
681
682
|
private options;
|
|
682
683
|
io: WsServer | undefined;
|
|
683
684
|
constructor(opts?: ServerNodeOpts);
|
|
@@ -924,4 +925,4 @@ declare class App<U = {}> {
|
|
|
924
925
|
}
|
|
925
926
|
|
|
926
927
|
export { App, Connect, CustomError, Mini, QueryConnect, QueryRouter, QueryRouterServer, QueryUtil, Route, ServerNode, createSchema, define, handleServer, util };
|
|
927
|
-
export type { OnWebSocketFn, RouteArray, RouteContext, RouteMiddleware, RouteObject, RouteOpts, RouterReq, RouterRes, Rule, Run, Schema };
|
|
928
|
+
export type { HttpListenerFun, Listener, OnListener, OnWebSocketFn, RouteArray, RouteContext, RouteMiddleware, RouteObject, RouteOpts, RouterReq, RouterRes, Rule, Run, Schema, WS, WebSocketListenerFun, WebSocketReq, WebSocketRes };
|
package/dist/router.js
CHANGED
|
@@ -1261,9 +1261,9 @@ class ServerBase {
|
|
|
1261
1261
|
}
|
|
1262
1262
|
const listeners = that.listeners || [];
|
|
1263
1263
|
for (const item of listeners) {
|
|
1264
|
-
const
|
|
1265
|
-
if (typeof
|
|
1266
|
-
await
|
|
1264
|
+
const func = item.func;
|
|
1265
|
+
if (typeof func === 'function' && !item.io) {
|
|
1266
|
+
await func(req, res);
|
|
1267
1267
|
}
|
|
1268
1268
|
}
|
|
1269
1269
|
if (res.headersSent) {
|
|
@@ -1324,13 +1324,13 @@ class ServerBase {
|
|
|
1324
1324
|
on(listener) {
|
|
1325
1325
|
this.listeners = [];
|
|
1326
1326
|
if (typeof listener === 'function') {
|
|
1327
|
-
this.listeners.push({
|
|
1327
|
+
this.listeners.push({ func: listener });
|
|
1328
1328
|
return;
|
|
1329
1329
|
}
|
|
1330
1330
|
if (Array.isArray(listener)) {
|
|
1331
1331
|
for (const item of listener) {
|
|
1332
1332
|
if (typeof item === 'function') {
|
|
1333
|
-
this.listeners.push({
|
|
1333
|
+
this.listeners.push({ func: item });
|
|
1334
1334
|
}
|
|
1335
1335
|
else {
|
|
1336
1336
|
this.listeners.push(item);
|
|
@@ -1348,7 +1348,7 @@ class ServerBase {
|
|
|
1348
1348
|
const end = (data) => {
|
|
1349
1349
|
ws.send(JSON.stringify(data));
|
|
1350
1350
|
};
|
|
1351
|
-
listener.
|
|
1351
|
+
listener.func({
|
|
1352
1352
|
emitter: this.emitter,
|
|
1353
1353
|
data,
|
|
1354
1354
|
token,
|
|
@@ -1408,6 +1408,17 @@ class ServerBase {
|
|
|
1408
1408
|
end({ code: 500, message: `${type} server is error` });
|
|
1409
1409
|
}
|
|
1410
1410
|
}
|
|
1411
|
+
async onWsClose(ws) {
|
|
1412
|
+
const id = ws?.data?.id || '';
|
|
1413
|
+
if (id) {
|
|
1414
|
+
this.emitter.emit('close--' + id, { type: 'close', ws, id });
|
|
1415
|
+
setTimeout(() => {
|
|
1416
|
+
// 关闭后 5 秒清理监听器, 避免内存泄漏, 理论上原本的自己就应该被清理掉了,这里是保险起见
|
|
1417
|
+
this.emitter.removeAllListeners('close--' + id);
|
|
1418
|
+
this.emitter.removeAllListeners(id);
|
|
1419
|
+
}, 5000);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1411
1422
|
}
|
|
1412
1423
|
|
|
1413
1424
|
function getDefaultExportFromCjs (x) {
|
|
@@ -6329,7 +6340,6 @@ var WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServerExport
|
|
|
6329
6340
|
// @ts-type=ws
|
|
6330
6341
|
class WsServerBase {
|
|
6331
6342
|
wss;
|
|
6332
|
-
listeners = [];
|
|
6333
6343
|
listening = false;
|
|
6334
6344
|
server;
|
|
6335
6345
|
constructor(opts) {
|
|
@@ -6353,10 +6363,20 @@ class WsServerBase {
|
|
|
6353
6363
|
const pathname = url.pathname;
|
|
6354
6364
|
const token = url.searchParams.get('token') || '';
|
|
6355
6365
|
const id = url.searchParams.get('id') || '';
|
|
6366
|
+
// @ts-ignore
|
|
6367
|
+
ws.data = {
|
|
6368
|
+
url: url,
|
|
6369
|
+
pathname,
|
|
6370
|
+
token,
|
|
6371
|
+
id,
|
|
6372
|
+
};
|
|
6356
6373
|
ws.on('message', async (message) => {
|
|
6357
6374
|
await this.server.onWebSocket({ ws, message, pathname, token, id });
|
|
6358
6375
|
});
|
|
6359
|
-
ws.send('connected');
|
|
6376
|
+
ws.send(JSON.stringify({ type: 'connected' }));
|
|
6377
|
+
this.wss.on('close', () => {
|
|
6378
|
+
this.server.onWsClose(ws);
|
|
6379
|
+
});
|
|
6360
6380
|
});
|
|
6361
6381
|
}
|
|
6362
6382
|
}
|
|
@@ -6674,15 +6694,7 @@ class BunServer extends ServerBase {
|
|
|
6674
6694
|
},
|
|
6675
6695
|
close: (ws) => {
|
|
6676
6696
|
// WebSocket 连接关闭
|
|
6677
|
-
|
|
6678
|
-
if (id) {
|
|
6679
|
-
this.emitter.emit('close--' + id, { type: 'close', ws, id });
|
|
6680
|
-
setTimeout(() => {
|
|
6681
|
-
// 关闭后 5 秒清理监听器, 避免内存泄漏, 理论上原本的自己就应该被清理掉了,这里是保险起见
|
|
6682
|
-
this.emitter.removeAllListeners('close--' + id);
|
|
6683
|
-
this.emitter.removeAllListeners(id);
|
|
6684
|
-
}, 5000);
|
|
6685
|
-
}
|
|
6697
|
+
this.onWsClose(ws);
|
|
6686
6698
|
},
|
|
6687
6699
|
},
|
|
6688
6700
|
});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -20,4 +20,15 @@ export { App } from './app.ts';
|
|
|
20
20
|
export * from './router-define.ts';
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
export {
|
|
23
|
+
export {
|
|
24
|
+
RouterReq,
|
|
25
|
+
RouterRes,
|
|
26
|
+
OnWebSocketFn,
|
|
27
|
+
WS,
|
|
28
|
+
WebSocketReq,
|
|
29
|
+
WebSocketRes,
|
|
30
|
+
Listener,
|
|
31
|
+
WebSocketListenerFun,
|
|
32
|
+
HttpListenerFun,
|
|
33
|
+
OnListener,
|
|
34
|
+
} from './server/server-type.ts';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
import { handleServer } from './handle-server.ts';
|
|
3
3
|
import * as cookie from './cookie.ts';
|
|
4
|
-
import { ServerType, Listener, OnListener, ServerOpts, OnWebSocketOptions, OnWebSocketFn, WebScoketListenerFun, ListenerFun, HttpListenerFun } from './server-type.ts';
|
|
4
|
+
import { ServerType, Listener, OnListener, ServerOpts, OnWebSocketOptions, OnWebSocketFn, WebScoketListenerFun, ListenerFun, HttpListenerFun, WS } from './server-type.ts';
|
|
5
5
|
import { parseIfJson } from '../utils/parse.ts';
|
|
6
6
|
import { EventEmitter } from 'events';
|
|
7
7
|
type CookieFn = (name: string, value: string, options?: cookie.SerializeOptions, end?: boolean) => void;
|
|
@@ -119,9 +119,9 @@ export class ServerBase implements ServerType {
|
|
|
119
119
|
}
|
|
120
120
|
const listeners = that.listeners || [];
|
|
121
121
|
for (const item of listeners) {
|
|
122
|
-
const
|
|
123
|
-
if (typeof
|
|
124
|
-
await
|
|
122
|
+
const func = item.func as any;
|
|
123
|
+
if (typeof func === 'function' && !item.io) {
|
|
124
|
+
await func(req, res);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
if (res.headersSent) {
|
|
@@ -179,13 +179,13 @@ export class ServerBase implements ServerType {
|
|
|
179
179
|
on(listener: OnListener) {
|
|
180
180
|
this.listeners = [];
|
|
181
181
|
if (typeof listener === 'function') {
|
|
182
|
-
this.listeners.push({
|
|
182
|
+
this.listeners.push({ func: listener });
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
if (Array.isArray(listener)) {
|
|
186
186
|
for (const item of listener) {
|
|
187
187
|
if (typeof item === 'function') {
|
|
188
|
-
this.listeners.push({
|
|
188
|
+
this.listeners.push({ func: item });
|
|
189
189
|
} else {
|
|
190
190
|
this.listeners.push(item);
|
|
191
191
|
}
|
|
@@ -202,7 +202,7 @@ export class ServerBase implements ServerType {
|
|
|
202
202
|
const end = (data: any) => {
|
|
203
203
|
ws.send(JSON.stringify(data));
|
|
204
204
|
}
|
|
205
|
-
(listener.
|
|
205
|
+
(listener.func as WebScoketListenerFun)({
|
|
206
206
|
emitter: this.emitter,
|
|
207
207
|
data,
|
|
208
208
|
token,
|
|
@@ -264,4 +264,15 @@ export class ServerBase implements ServerType {
|
|
|
264
264
|
end({ code: 500, message: `${type} server is error` });
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
|
+
async onWsClose(ws: WS) {
|
|
268
|
+
const id = ws?.data?.id || '';
|
|
269
|
+
if (id) {
|
|
270
|
+
this.emitter.emit('close--' + id, { type: 'close', ws, id });
|
|
271
|
+
setTimeout(() => {
|
|
272
|
+
// 关闭后 5 秒清理监听器, 避免内存泄漏, 理论上原本的自己就应该被清理掉了,这里是保险起见
|
|
273
|
+
this.emitter.removeAllListeners('close--' + id);
|
|
274
|
+
this.emitter.removeAllListeners(id);
|
|
275
|
+
}, 5000);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
267
278
|
}
|
package/src/server/server-bun.ts
CHANGED
|
@@ -233,15 +233,7 @@ export class BunServer extends ServerBase implements ServerType {
|
|
|
233
233
|
},
|
|
234
234
|
close: (ws: any) => {
|
|
235
235
|
// WebSocket 连接关闭
|
|
236
|
-
|
|
237
|
-
if (id) {
|
|
238
|
-
this.emitter.emit('close--' + id, { type: 'close', ws, id });
|
|
239
|
-
setTimeout(() => {
|
|
240
|
-
// 关闭后 5 秒清理监听器, 避免内存泄漏, 理论上原本的自己就应该被清理掉了,这里是保险起见
|
|
241
|
-
this.emitter.removeAllListeners('close--' + id);
|
|
242
|
-
this.emitter.removeAllListeners(id);
|
|
243
|
-
}, 5000);
|
|
244
|
-
}
|
|
236
|
+
this.onWsClose(ws);
|
|
245
237
|
},
|
|
246
238
|
},
|
|
247
239
|
});
|
|
@@ -39,22 +39,33 @@ export interface ServerType {
|
|
|
39
39
|
*/
|
|
40
40
|
on(listener: OnListener): void;
|
|
41
41
|
onWebSocket({ ws, message, pathname, token, id }: OnWebSocketOptions): void;
|
|
42
|
+
onWsClose(ws: WS): void;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
export type OnWebSocketOptions = { ws: WS; message: string | Buffer; pathname: string, token?: string, id?: string }
|
|
45
46
|
export type OnWebSocketFn = (options: OnWebSocketOptions) => Promise<void> | void;
|
|
46
|
-
type WS = {
|
|
47
|
+
export type WS = {
|
|
47
48
|
send: (data: any) => void;
|
|
48
49
|
close: (code?: number, reason?: string) => void;
|
|
50
|
+
data?: {
|
|
51
|
+
url: URL;
|
|
52
|
+
pathname: string;
|
|
53
|
+
token?: string;
|
|
54
|
+
id?: string;
|
|
55
|
+
/**
|
|
56
|
+
* 鉴权后的获取的信息
|
|
57
|
+
*/
|
|
58
|
+
userApp?: string;
|
|
59
|
+
}
|
|
49
60
|
}
|
|
50
61
|
export type Listener = {
|
|
51
62
|
id?: string;
|
|
52
63
|
io?: boolean;
|
|
53
64
|
path?: string;
|
|
54
|
-
|
|
65
|
+
func: WebSocketListenerFun | HttpListenerFun;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
export type
|
|
68
|
+
export type WebSocketListenerFun = (req: WebSocketReq, res: WebSocketRes) => Promise<void> | void;
|
|
58
69
|
export type HttpListenerFun = (req: RouterReq, res: RouterRes) => Promise<void> | void;
|
|
59
70
|
|
|
60
71
|
export type WebSocketReq = {
|
|
@@ -68,7 +79,7 @@ export type WebSocketReq = {
|
|
|
68
79
|
export type WebSocketRes = {
|
|
69
80
|
end: (data: any) => void;
|
|
70
81
|
}
|
|
71
|
-
export type ListenerFun =
|
|
82
|
+
export type ListenerFun = WebSocketListenerFun | HttpListenerFun;;
|
|
72
83
|
export type OnListener = Listener | ListenerFun | (Listener | ListenerFun)[];
|
|
73
84
|
export type RouterReq<T = {}> = {
|
|
74
85
|
url: string;
|
package/src/server/ws-server.ts
CHANGED
|
@@ -24,7 +24,6 @@ export type Listener<T = 'router' | 'chat' | 'ai'> = {
|
|
|
24
24
|
|
|
25
25
|
export class WsServerBase {
|
|
26
26
|
wss: WebSocketServer | null;
|
|
27
|
-
listeners: Listener[] = [];
|
|
28
27
|
listening: boolean = false;
|
|
29
28
|
server: ServerType;
|
|
30
29
|
|
|
@@ -51,11 +50,22 @@ export class WsServerBase {
|
|
|
51
50
|
const pathname = url.pathname;
|
|
52
51
|
const token = url.searchParams.get('token') || '';
|
|
53
52
|
const id = url.searchParams.get('id') || '';
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
ws.data = {
|
|
55
|
+
url: url,
|
|
56
|
+
pathname,
|
|
57
|
+
token,
|
|
58
|
+
id,
|
|
59
|
+
}
|
|
54
60
|
ws.on('message', async (message: string | Buffer) => {
|
|
55
61
|
await this.server.onWebSocket({ ws, message, pathname, token, id });
|
|
56
62
|
});
|
|
57
|
-
ws.send('connected');
|
|
63
|
+
ws.send(JSON.stringify({ type: 'connected' }));
|
|
64
|
+
this.wss.on('close', () => {
|
|
65
|
+
this.server.onWsClose(ws);
|
|
66
|
+
});
|
|
58
67
|
});
|
|
68
|
+
|
|
59
69
|
}
|
|
60
70
|
}
|
|
61
71
|
// TODO: ws handle and path and routerContext
|