@kevisual/router 0.0.41 → 0.0.43
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.js +66 -48
- package/dist/router-sign.js +3 -1
- package/dist/router-simple.js +50 -30
- package/dist/router.d.ts +166 -80
- package/dist/router.js +5134 -4872
- package/package.json +5 -2
- package/src/app.ts +21 -16
- package/src/index.ts +5 -2
- package/src/router-simple.ts +1 -0
- package/src/server/handle-server.ts +1 -1
- package/src/server/index.ts +2 -1
- package/src/server/parse-body.ts +44 -33
- package/src/server/server-base.ts +265 -0
- package/src/server/server-bun.ts +244 -0
- package/src/server/server-type.ts +78 -0
- package/src/server/server.ts +25 -177
- package/src/server/ws-server.ts +35 -103
- package/src/test/listen-ip.ts +2 -2
- package/src/utils/is-engine.ts +5 -1
package/src/server/ws-server.ts
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
// @ts-type=ws
|
|
2
2
|
import { WebSocketServer } from 'ws';
|
|
3
3
|
import type { WebSocket } from 'ws';
|
|
4
|
-
import {
|
|
4
|
+
import { ServerType } from './server-type.ts'
|
|
5
5
|
import { parseIfJson } from '../utils/parse.ts';
|
|
6
|
+
import { isBun } from '../utils/is-engine.ts';
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
export const createWsServer = (server:
|
|
9
|
+
export const createWsServer = (server: ServerType) => {
|
|
9
10
|
// 将 WebSocket 服务器附加到 HTTP 服务器
|
|
10
11
|
const wss = new WebSocketServer({ server: server.server as any });
|
|
11
12
|
return wss;
|
|
12
13
|
};
|
|
13
14
|
type WsServerBaseOpts = {
|
|
14
|
-
wss?: WebSocketServer;
|
|
15
|
+
wss?: WebSocketServer | null;
|
|
15
16
|
path?: string;
|
|
16
17
|
};
|
|
17
18
|
export type ListenerFn = (message: { data: Record<string, any>; ws: WebSocket; end: (data: any) => any }) => Promise<any>;
|
|
18
19
|
export type Listener<T = 'router' | 'chat' | 'ai'> = {
|
|
19
20
|
type: T;
|
|
21
|
+
path?: string;
|
|
20
22
|
listener: ListenerFn;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
export class WsServerBase {
|
|
24
|
-
wss: WebSocketServer;
|
|
25
|
-
|
|
26
|
-
listeners: { type: string; listener: ListenerFn }[] = [];
|
|
26
|
+
wss: WebSocketServer | null;
|
|
27
|
+
listeners: Listener[] = [];
|
|
27
28
|
listening: boolean = false;
|
|
29
|
+
server: ServerType;
|
|
30
|
+
|
|
28
31
|
constructor(opts: WsServerBaseOpts) {
|
|
29
32
|
this.wss = opts.wss;
|
|
30
|
-
if (!this.wss) {
|
|
33
|
+
if (!this.wss && !isBun) {
|
|
31
34
|
throw new Error('wss is required');
|
|
32
35
|
}
|
|
33
|
-
this.path = opts.path || '';
|
|
34
|
-
}
|
|
35
|
-
setPath(path: string) {
|
|
36
|
-
this.path = path;
|
|
37
36
|
}
|
|
38
37
|
listen() {
|
|
39
38
|
if (this.listening) {
|
|
@@ -42,116 +41,49 @@ export class WsServerBase {
|
|
|
42
41
|
}
|
|
43
42
|
this.listening = true;
|
|
44
43
|
|
|
45
|
-
this.wss
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const cleanMessage = data.trim().replace(/^["']|["']$/g, '');
|
|
50
|
-
ws.emit('string', cleanMessage);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const { type, data: typeData, ...rest } = data;
|
|
54
|
-
if (!type) {
|
|
55
|
-
ws.send(JSON.stringify({ code: 500, message: 'type is required' }));
|
|
56
|
-
}
|
|
57
|
-
const listeners = this.listeners.find((item) => item.type === type);
|
|
58
|
-
const res = {
|
|
59
|
-
type,
|
|
60
|
-
data: {} as any,
|
|
61
|
-
...rest,
|
|
62
|
-
};
|
|
63
|
-
const end = (data: any, all?: Record<string, any>) => {
|
|
64
|
-
const result = {
|
|
65
|
-
...res,
|
|
66
|
-
data,
|
|
67
|
-
...all,
|
|
68
|
-
};
|
|
69
|
-
ws.send(JSON.stringify(result));
|
|
70
|
-
};
|
|
44
|
+
if (!this.wss) {
|
|
45
|
+
// Bun 环境下,wss 可能为 null
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
71
48
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
ws,
|
|
80
|
-
end: end,
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
ws.on('string', (message: string) => {
|
|
84
|
-
if (message === 'close') {
|
|
85
|
-
ws.close();
|
|
86
|
-
}
|
|
87
|
-
if (message == 'ping') {
|
|
88
|
-
ws.send('pong');
|
|
89
|
-
}
|
|
49
|
+
this.wss.on('connection', (ws, req) => {
|
|
50
|
+
const url = new URL(req.url, 'http://localhost');
|
|
51
|
+
const pathname = url.pathname;
|
|
52
|
+
const token = url.searchParams.get('token') || '';
|
|
53
|
+
const id = url.searchParams.get('id') || '';
|
|
54
|
+
ws.on('message', async (message: string | Buffer) => {
|
|
55
|
+
await this.server.onWebSocket({ ws, message, pathname, token, id });
|
|
90
56
|
});
|
|
91
57
|
ws.send('connected');
|
|
92
58
|
});
|
|
93
59
|
}
|
|
94
|
-
addListener(type: string, listener: ListenerFn) {
|
|
95
|
-
if (!type || !listener) {
|
|
96
|
-
throw new Error('type and listener is required');
|
|
97
|
-
}
|
|
98
|
-
const find = this.listeners.find((item) => item.type === type);
|
|
99
|
-
if (find) {
|
|
100
|
-
this.listeners = this.listeners.filter((item) => item.type !== type);
|
|
101
|
-
}
|
|
102
|
-
this.listeners.push({ type, listener });
|
|
103
|
-
}
|
|
104
|
-
removeListener(type: string) {
|
|
105
|
-
this.listeners = this.listeners.filter((item) => item.type !== type);
|
|
106
|
-
}
|
|
107
60
|
}
|
|
108
61
|
// TODO: ws handle and path and routerContext
|
|
109
62
|
export class WsServer extends WsServerBase {
|
|
110
|
-
server:
|
|
111
|
-
|
|
112
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
113
|
-
const path = server.path;
|
|
63
|
+
constructor(server: ServerType) {
|
|
64
|
+
const wss = isBun ? null : new WebSocketServer({ noServer: true });
|
|
114
65
|
super({ wss });
|
|
115
66
|
this.server = server;
|
|
116
|
-
this.setPath(opts?.path || path);
|
|
117
|
-
this.initListener();
|
|
118
|
-
}
|
|
119
|
-
initListener() {
|
|
120
|
-
const server = this.server;
|
|
121
|
-
const listener: Listener = {
|
|
122
|
-
type: 'router',
|
|
123
|
-
listener: async ({ data, ws, end }) => {
|
|
124
|
-
if (!server) {
|
|
125
|
-
end({ code: 500, message: 'server handle is error' });
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const handle = this.server.handle;
|
|
129
|
-
try {
|
|
130
|
-
const result = await handle(data as any);
|
|
131
|
-
end(result);
|
|
132
|
-
} catch (e) {
|
|
133
|
-
if (e.code && typeof e.code === 'number') {
|
|
134
|
-
end({
|
|
135
|
-
code: e.code,
|
|
136
|
-
message: e.message,
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
end({ code: 500, message: 'Router Server error' });
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
this.addListener(listener.type, listener.listener);
|
|
145
67
|
}
|
|
146
68
|
listen() {
|
|
69
|
+
if (isBun) {
|
|
70
|
+
// Bun 的 WebSocket 在 Bun.serve 中处理,这里不需要额外操作
|
|
71
|
+
// WebSocket 升级会在 listenWithBun 中处理
|
|
72
|
+
this.listening = true;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
147
75
|
super.listen();
|
|
148
76
|
const server = this.server;
|
|
149
77
|
const wss = this.wss;
|
|
78
|
+
|
|
150
79
|
// HTTP 服务器的 upgrade 事件
|
|
80
|
+
// @ts-ignore
|
|
151
81
|
server.server.on('upgrade', (req, socket, head) => {
|
|
152
|
-
|
|
82
|
+
const url = new URL(req.url, 'http://localhost');
|
|
83
|
+
const listenPath = this.server.listeners.map((item) => item.path).filter((item) => item);
|
|
84
|
+
if (listenPath.includes(url.pathname) || url.pathname === this.server.path) {
|
|
153
85
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
154
|
-
// 这里手动触发 connection
|
|
86
|
+
// 这里手动触发 connection事件
|
|
155
87
|
// @ts-ignore
|
|
156
88
|
wss.emit('connection', ws, req);
|
|
157
89
|
});
|
package/src/test/listen-ip.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// import { Server } from 'node:http';
|
|
2
|
-
import {
|
|
2
|
+
import { ServerNode } from '../server/server.ts'
|
|
3
3
|
|
|
4
|
-
const server = new
|
|
4
|
+
const server = new ServerNode({
|
|
5
5
|
path: '/',
|
|
6
6
|
handle: async (data, ctx) => {
|
|
7
7
|
console.log('ctx', ctx.req.url)
|
package/src/utils/is-engine.ts
CHANGED
|
@@ -2,9 +2,13 @@ export const isNode = typeof process !== 'undefined' && process.versions != null
|
|
|
2
2
|
export const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof document.createElement === 'function';
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
export const isDeno = typeof Deno !== 'undefined' && typeof Deno.version === 'object' && typeof Deno.version.deno === 'string';
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
export const isBun = typeof Bun !== 'undefined' && typeof Bun.version === 'string';
|
|
5
7
|
|
|
6
8
|
export const getEngine = () => {
|
|
7
|
-
if (
|
|
9
|
+
if (isBun) {
|
|
10
|
+
return 'bun';
|
|
11
|
+
} else if (isNode) {
|
|
8
12
|
return 'node';
|
|
9
13
|
} else if (isBrowser) {
|
|
10
14
|
return 'browser';
|