@colyseus/bun-websockets 0.15.0-alpha.3 → 0.15.0
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/README.md +18 -4
- package/build/BunWebSockets.d.ts +6 -6
- package/build/BunWebSockets.js +62 -76
- package/build/BunWebSockets.js.map +3 -3
- package/build/BunWebSockets.mjs +63 -77
- package/build/BunWebSockets.mjs.map +2 -2
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
-
# @colyseus/bun-websockets
|
|
1
|
+
# @colyseus/bun-websockets
|
|
2
|
+
|
|
3
|
+
From your `app.config.ts`:
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import config from "@colyseus/tools";
|
|
7
|
+
import { BunWebSockets } from "@colyseus/bun-websockets";
|
|
8
|
+
|
|
9
|
+
export default config({
|
|
10
|
+
initializeTransport: () => new BunWebSockets(),
|
|
11
|
+
// ...
|
|
12
|
+
});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Alternatively, if you instantiate the `Server` yourself:
|
|
2
16
|
|
|
3
17
|
```typescript
|
|
4
|
-
import { Server } from "
|
|
5
|
-
import { BunWebsockets } from "@colyseus/
|
|
18
|
+
import { Server } from "colyseus";
|
|
19
|
+
import { BunWebsockets } from "@colyseus/bun-websockets";
|
|
6
20
|
|
|
7
21
|
const gameServer = new Server({
|
|
8
22
|
transport: new BunWebsockets(),
|
|
9
23
|
// ...
|
|
10
24
|
})
|
|
11
|
-
```
|
|
25
|
+
```
|
package/build/BunWebSockets.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/// <reference types="bun-types" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import Bun, {
|
|
3
|
+
import Bun, { ServerWebSocket, WebSocketHandler } from "bun";
|
|
4
4
|
import { Transport } from '@colyseus/core';
|
|
5
5
|
import { WebSocketWrapper } from './WebSocketClient';
|
|
6
|
+
import { Application, Request, Response } from "express";
|
|
6
7
|
export type TransportOptions = Partial<Omit<WebSocketHandler, "message" | "open" | "drain" | "close" | "ping" | "pong">>;
|
|
7
8
|
interface WebSocketData {
|
|
8
9
|
url: URL;
|
|
9
10
|
}
|
|
10
11
|
export declare class BunWebSockets extends Transport {
|
|
11
12
|
private options;
|
|
12
|
-
|
|
13
|
+
expressApp: Application;
|
|
13
14
|
protected clients: ServerWebSocket<WebSocketData>[];
|
|
14
15
|
protected clientWrappers: WeakMap<Bun.ServerWebSocket<WebSocketData>, WebSocketWrapper>;
|
|
16
|
+
private _listening;
|
|
15
17
|
constructor(options?: TransportOptions);
|
|
16
|
-
listen(port: number
|
|
18
|
+
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
|
|
17
19
|
shutdown(): void;
|
|
18
20
|
simulateLatency(milliseconds: number): void;
|
|
19
21
|
protected onConnection(rawClient: ServerWebSocket<WebSocketData>): Promise<void>;
|
|
20
|
-
protected handleMatchMakeRequest(req: Request,
|
|
21
|
-
[key: string]: string;
|
|
22
|
-
}]>;
|
|
22
|
+
protected handleMatchMakeRequest(req: Request, res: Response): Promise<void>;
|
|
23
23
|
}
|
|
24
24
|
export {};
|
package/build/BunWebSockets.js
CHANGED
|
@@ -26,53 +26,15 @@ __export(BunWebSockets_exports, {
|
|
|
26
26
|
BunWebSockets: () => BunWebSockets
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(BunWebSockets_exports);
|
|
29
|
-
var
|
|
29
|
+
var import_bun_serve_express = __toESM(require("bun-serve-express"));
|
|
30
30
|
var import_core = require("@colyseus/core");
|
|
31
31
|
var import_WebSocketClient = require("./WebSocketClient");
|
|
32
32
|
class BunWebSockets extends import_core.Transport {
|
|
33
33
|
constructor(options = {}) {
|
|
34
34
|
super();
|
|
35
35
|
this.options = options;
|
|
36
|
-
if (!this.server) {
|
|
37
|
-
this.server = new import_core.DummyServer();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
bunServer;
|
|
41
|
-
clients = [];
|
|
42
|
-
clientWrappers = /* @__PURE__ */ new WeakMap();
|
|
43
|
-
listen(port, hostname, backlog, listeningListener) {
|
|
44
36
|
const self = this;
|
|
45
|
-
this.
|
|
46
|
-
port,
|
|
47
|
-
hostname,
|
|
48
|
-
async fetch(req, server) {
|
|
49
|
-
const url = new URL(req.url);
|
|
50
|
-
if (url.pathname.startsWith(`/${import_core.matchMaker.controller.matchmakeRoute}`)) {
|
|
51
|
-
try {
|
|
52
|
-
const [code, response, headers] = await self.handleMatchMakeRequest(req, server, url);
|
|
53
|
-
return new Response(response, {
|
|
54
|
-
status: code,
|
|
55
|
-
headers: Object.assign(
|
|
56
|
-
headers,
|
|
57
|
-
import_core.matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
58
|
-
import_core.matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
59
|
-
)
|
|
60
|
-
});
|
|
61
|
-
} catch (e) {
|
|
62
|
-
return new Response(JSON.stringify({ code: e.code, error: e.message }), {
|
|
63
|
-
status: e.code || import_core.ErrorCode.MATCHMAKE_UNHANDLED,
|
|
64
|
-
headers: Object.assign(
|
|
65
|
-
{ "Content-Type": "application/json" },
|
|
66
|
-
import_core.matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
67
|
-
import_core.matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
68
|
-
)
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
server.upgrade(req, { data: { url } });
|
|
73
|
-
return void 0;
|
|
74
|
-
}
|
|
75
|
-
},
|
|
37
|
+
this.expressApp = (0, import_bun_serve_express.default)({
|
|
76
38
|
websocket: {
|
|
77
39
|
...this.options,
|
|
78
40
|
async open(ws) {
|
|
@@ -91,13 +53,32 @@ class BunWebSockets extends import_core.Transport {
|
|
|
91
53
|
}
|
|
92
54
|
}
|
|
93
55
|
});
|
|
94
|
-
|
|
56
|
+
if (!this.server) {
|
|
57
|
+
this.server = new import_core.DummyServer();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
expressApp;
|
|
61
|
+
clients = [];
|
|
62
|
+
clientWrappers = /* @__PURE__ */ new WeakMap();
|
|
63
|
+
_listening;
|
|
64
|
+
listen(port, hostname, backlog, listeningListener) {
|
|
65
|
+
this._listening = this.expressApp.listen(port, listeningListener);
|
|
66
|
+
this.expressApp.use(`/${import_core.matchMaker.controller.matchmakeRoute}`, async (req, res) => {
|
|
67
|
+
try {
|
|
68
|
+
await this.handleMatchMakeRequest(req, res);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
res.status(500).json({
|
|
71
|
+
code: e.code,
|
|
72
|
+
error: e.message
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
95
76
|
this.server.emit("listening");
|
|
96
77
|
return this;
|
|
97
78
|
}
|
|
98
79
|
shutdown() {
|
|
99
|
-
if (this.
|
|
100
|
-
this.
|
|
80
|
+
if (this._listening) {
|
|
81
|
+
this._listening.close();
|
|
101
82
|
this.server.emit("close");
|
|
102
83
|
}
|
|
103
84
|
}
|
|
@@ -127,43 +108,48 @@ class BunWebSockets extends import_core.Transport {
|
|
|
127
108
|
client.error(e.code, e.message, () => rawClient.close());
|
|
128
109
|
}
|
|
129
110
|
}
|
|
130
|
-
async handleMatchMakeRequest(req,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
"Content-Type": "application/json"
|
|
142
|
-
}
|
|
143
|
-
];
|
|
144
|
-
}
|
|
145
|
-
case "POST": {
|
|
146
|
-
if (import_core.matchMaker.isGracefullyShuttingDown) {
|
|
147
|
-
throw new import_core.ServerError(503, "server is shutting down");
|
|
111
|
+
async handleMatchMakeRequest(req, res) {
|
|
112
|
+
try {
|
|
113
|
+
switch (req.method) {
|
|
114
|
+
case "OPTIONS": {
|
|
115
|
+
res.set(Object.assign(
|
|
116
|
+
{},
|
|
117
|
+
import_core.matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
118
|
+
import_core.matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
119
|
+
));
|
|
120
|
+
res.status(200).end();
|
|
121
|
+
break;
|
|
148
122
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
123
|
+
case "GET": {
|
|
124
|
+
const matchedParams = req.path.match(import_core.matchMaker.controller.allowedRoomNameChars);
|
|
125
|
+
const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : "";
|
|
126
|
+
res.json(await import_core.matchMaker.controller.getAvailableRooms(roomName || ""));
|
|
127
|
+
break;
|
|
154
128
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
200,
|
|
159
|
-
JSON.stringify(await import_core.matchMaker.controller.invokeMethod(method, roomName, clientOptions)),
|
|
160
|
-
{
|
|
161
|
-
"Content-Type": "application/json"
|
|
129
|
+
case "POST": {
|
|
130
|
+
if (import_core.matchMaker.isGracefullyShuttingDown) {
|
|
131
|
+
throw new import_core.ServerError(503, "server is shutting down");
|
|
162
132
|
}
|
|
163
|
-
|
|
133
|
+
const matchedParams = req.path.match(import_core.matchMaker.controller.allowedRoomNameChars);
|
|
134
|
+
const matchmakeIndex = matchedParams.indexOf(import_core.matchMaker.controller.matchmakeRoute);
|
|
135
|
+
const clientOptions = req.body;
|
|
136
|
+
if (clientOptions === void 0) {
|
|
137
|
+
throw new import_core.ServerError(500, "invalid JSON input");
|
|
138
|
+
}
|
|
139
|
+
const method = matchedParams[matchmakeIndex + 1];
|
|
140
|
+
const roomName = matchedParams[matchmakeIndex + 2] || "";
|
|
141
|
+
res.json(await import_core.matchMaker.controller.invokeMethod(method, roomName, clientOptions));
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
default:
|
|
145
|
+
throw new import_core.ServerError(500, "invalid request method");
|
|
164
146
|
}
|
|
165
|
-
|
|
166
|
-
|
|
147
|
+
} catch (e) {
|
|
148
|
+
res.set(Object.assign(
|
|
149
|
+
{},
|
|
150
|
+
import_core.matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
151
|
+
import_core.matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
152
|
+
)).status(500).json({ code: e.code, error: e.message });
|
|
167
153
|
}
|
|
168
154
|
}
|
|
169
155
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/BunWebSockets.ts"],
|
|
4
|
-
"sourcesContent": ["/// <reference types=\"bun-types\" />\nimport Bun, {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["/// <reference types=\"bun-types\" />\nimport Bun, { ServerWebSocket, WebSocketHandler } from \"bun\";\n\nimport http from 'http';\nimport bunExpress from \"bun-serve-express\";\n\nimport { DummyServer, ErrorCode, matchMaker, Transport, debugAndPrintError, spliceOne, ServerError } from '@colyseus/core';\nimport { WebSocketClient, WebSocketWrapper } from './WebSocketClient';\nimport { Application, Request, Response } from \"express\";\n\nexport type TransportOptions = Partial<Omit<WebSocketHandler, \"message\" | \"open\" | \"drain\" | \"close\" | \"ping\" | \"pong\">>;\n\ninterface WebSocketData {\n url: URL;\n // query: string,\n // headers: { [key: string]: string },\n // connection: { remoteAddress: string },\n}\n\nexport class BunWebSockets extends Transport {\n public expressApp: Application;\n\n protected clients: ServerWebSocket<WebSocketData>[] = [];\n protected clientWrappers = new WeakMap<ServerWebSocket<WebSocketData>, WebSocketWrapper>();\n\n private _listening: any;\n\n constructor(private options: TransportOptions = {}) {\n super();\n\n const self = this;\n\n this.expressApp = bunExpress({\n websocket: {\n ...this.options,\n\n async open(ws) {\n await self.onConnection(ws);\n },\n\n message(ws, message) {\n // this.clientWrappers.get(ws)?.emit('message', Buffer.from(message.slice(0)));\n self.clientWrappers.get(ws)?.emit('message', message);\n },\n\n close(ws, code, reason) {\n // remove from client list\n spliceOne(self.clients, self.clients.indexOf(ws));\n\n const clientWrapper = self.clientWrappers.get(ws);\n if (clientWrapper) {\n self.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n }\n });\n\n // Adding a mock object for Transport.server\n if (!this.server) {\n this.server = new DummyServer();\n }\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n this._listening = this.expressApp.listen(port, listeningListener);\n\n this.expressApp.use(`/${matchMaker.controller.matchmakeRoute}`, async (req, res) => {\n try {\n await this.handleMatchMakeRequest(req, res);\n } catch (e) {\n res.status(500).json({\n code: e.code,\n error: e.message\n });\n }\n });\n\n // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n // @ts-ignore\n this.server.emit(\"listening\");\n\n return this;\n }\n\n public shutdown() {\n if (this._listening) {\n this._listening.close();\n\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n const originalRawSend = WebSocketClient.prototype.raw;\n WebSocketClient.prototype.raw = function () {\n setTimeout(() => originalRawSend.apply(this, arguments), milliseconds);\n }\n }\n\n protected async onConnection(rawClient: ServerWebSocket<WebSocketData>) {\n const wrapper = new WebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const parsedURL = new URL(rawClient.data.url);\n\n const sessionId = parsedURL.searchParams.get(\"sessionId\");\n const processAndRoomId = parsedURL.pathname.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getRoomById(roomId);\n const client = new WebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, parsedURL.searchParams.get(\"reconnectionToken\") as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient as unknown as http.IncomingMessage);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => rawClient.close());\n }\n }\n\n protected async handleMatchMakeRequest (req: Request, res: Response) {\n try {\n switch (req.method) {\n case 'OPTIONS': {\n res.set(Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n ));\n res.status(200).end();\n break;\n }\n\n case 'GET': {\n const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n res.json(await matchMaker.controller.getAvailableRooms(roomName || ''));\n break;\n }\n\n case 'POST': {\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.isGracefullyShuttingDown) {\n throw new ServerError(503, \"server is shutting down\");\n }\n\n const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchMaker.controller.matchmakeRoute);\n const clientOptions = req.body; // Bun.readableStreamToJSON(req.body);\n\n if (clientOptions === undefined) {\n throw new ServerError(500, \"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n res.json(await matchMaker.controller.invokeMethod(method, roomName, clientOptions));\n break;\n }\n\n default: throw new ServerError(500, \"invalid request method\");\n }\n\n } catch (e) {\n res\n .set(Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n ))\n .status(500)\n .json({ code: e.code, error: e.message });\n }\n\n }\n\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["bunExpress"]
|
|
7
7
|
}
|
package/build/BunWebSockets.mjs
CHANGED
|
@@ -1,50 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { DummyServer,
|
|
1
|
+
import bunExpress from "bun-serve-express";
|
|
2
|
+
import { DummyServer, matchMaker, Transport, debugAndPrintError, spliceOne, ServerError } from "@colyseus/core";
|
|
3
3
|
import { WebSocketClient, WebSocketWrapper } from "./WebSocketClient";
|
|
4
4
|
class BunWebSockets extends Transport {
|
|
5
5
|
constructor(options = {}) {
|
|
6
6
|
super();
|
|
7
7
|
this.options = options;
|
|
8
|
-
if (!this.server) {
|
|
9
|
-
this.server = new DummyServer();
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
bunServer;
|
|
13
|
-
clients = [];
|
|
14
|
-
clientWrappers = /* @__PURE__ */ new WeakMap();
|
|
15
|
-
listen(port, hostname, backlog, listeningListener) {
|
|
16
8
|
const self = this;
|
|
17
|
-
this.
|
|
18
|
-
port,
|
|
19
|
-
hostname,
|
|
20
|
-
async fetch(req, server) {
|
|
21
|
-
const url = new URL(req.url);
|
|
22
|
-
if (url.pathname.startsWith(`/${matchMaker.controller.matchmakeRoute}`)) {
|
|
23
|
-
try {
|
|
24
|
-
const [code, response, headers] = await self.handleMatchMakeRequest(req, server, url);
|
|
25
|
-
return new Response(response, {
|
|
26
|
-
status: code,
|
|
27
|
-
headers: Object.assign(
|
|
28
|
-
headers,
|
|
29
|
-
matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
30
|
-
matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
31
|
-
)
|
|
32
|
-
});
|
|
33
|
-
} catch (e) {
|
|
34
|
-
return new Response(JSON.stringify({ code: e.code, error: e.message }), {
|
|
35
|
-
status: e.code || ErrorCode.MATCHMAKE_UNHANDLED,
|
|
36
|
-
headers: Object.assign(
|
|
37
|
-
{ "Content-Type": "application/json" },
|
|
38
|
-
matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
39
|
-
matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
40
|
-
)
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
server.upgrade(req, { data: { url } });
|
|
45
|
-
return void 0;
|
|
46
|
-
}
|
|
47
|
-
},
|
|
9
|
+
this.expressApp = bunExpress({
|
|
48
10
|
websocket: {
|
|
49
11
|
...this.options,
|
|
50
12
|
async open(ws) {
|
|
@@ -63,13 +25,32 @@ class BunWebSockets extends Transport {
|
|
|
63
25
|
}
|
|
64
26
|
}
|
|
65
27
|
});
|
|
66
|
-
|
|
28
|
+
if (!this.server) {
|
|
29
|
+
this.server = new DummyServer();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
expressApp;
|
|
33
|
+
clients = [];
|
|
34
|
+
clientWrappers = /* @__PURE__ */ new WeakMap();
|
|
35
|
+
_listening;
|
|
36
|
+
listen(port, hostname, backlog, listeningListener) {
|
|
37
|
+
this._listening = this.expressApp.listen(port, listeningListener);
|
|
38
|
+
this.expressApp.use(`/${matchMaker.controller.matchmakeRoute}`, async (req, res) => {
|
|
39
|
+
try {
|
|
40
|
+
await this.handleMatchMakeRequest(req, res);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
res.status(500).json({
|
|
43
|
+
code: e.code,
|
|
44
|
+
error: e.message
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
67
48
|
this.server.emit("listening");
|
|
68
49
|
return this;
|
|
69
50
|
}
|
|
70
51
|
shutdown() {
|
|
71
|
-
if (this.
|
|
72
|
-
this.
|
|
52
|
+
if (this._listening) {
|
|
53
|
+
this._listening.close();
|
|
73
54
|
this.server.emit("close");
|
|
74
55
|
}
|
|
75
56
|
}
|
|
@@ -99,43 +80,48 @@ class BunWebSockets extends Transport {
|
|
|
99
80
|
client.error(e.code, e.message, () => rawClient.close());
|
|
100
81
|
}
|
|
101
82
|
}
|
|
102
|
-
async handleMatchMakeRequest(req,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"Content-Type": "application/json"
|
|
114
|
-
}
|
|
115
|
-
];
|
|
116
|
-
}
|
|
117
|
-
case "POST": {
|
|
118
|
-
if (matchMaker.isGracefullyShuttingDown) {
|
|
119
|
-
throw new ServerError(503, "server is shutting down");
|
|
83
|
+
async handleMatchMakeRequest(req, res) {
|
|
84
|
+
try {
|
|
85
|
+
switch (req.method) {
|
|
86
|
+
case "OPTIONS": {
|
|
87
|
+
res.set(Object.assign(
|
|
88
|
+
{},
|
|
89
|
+
matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
90
|
+
matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
91
|
+
));
|
|
92
|
+
res.status(200).end();
|
|
93
|
+
break;
|
|
120
94
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
95
|
+
case "GET": {
|
|
96
|
+
const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);
|
|
97
|
+
const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : "";
|
|
98
|
+
res.json(await matchMaker.controller.getAvailableRooms(roomName || ""));
|
|
99
|
+
break;
|
|
126
100
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
200,
|
|
131
|
-
JSON.stringify(await matchMaker.controller.invokeMethod(method, roomName, clientOptions)),
|
|
132
|
-
{
|
|
133
|
-
"Content-Type": "application/json"
|
|
101
|
+
case "POST": {
|
|
102
|
+
if (matchMaker.isGracefullyShuttingDown) {
|
|
103
|
+
throw new ServerError(503, "server is shutting down");
|
|
134
104
|
}
|
|
135
|
-
|
|
105
|
+
const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);
|
|
106
|
+
const matchmakeIndex = matchedParams.indexOf(matchMaker.controller.matchmakeRoute);
|
|
107
|
+
const clientOptions = req.body;
|
|
108
|
+
if (clientOptions === void 0) {
|
|
109
|
+
throw new ServerError(500, "invalid JSON input");
|
|
110
|
+
}
|
|
111
|
+
const method = matchedParams[matchmakeIndex + 1];
|
|
112
|
+
const roomName = matchedParams[matchmakeIndex + 2] || "";
|
|
113
|
+
res.json(await matchMaker.controller.invokeMethod(method, roomName, clientOptions));
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
default:
|
|
117
|
+
throw new ServerError(500, "invalid request method");
|
|
136
118
|
}
|
|
137
|
-
|
|
138
|
-
|
|
119
|
+
} catch (e) {
|
|
120
|
+
res.set(Object.assign(
|
|
121
|
+
{},
|
|
122
|
+
matchMaker.controller.DEFAULT_CORS_HEADERS,
|
|
123
|
+
matchMaker.controller.getCorsHeaders.call(void 0, req)
|
|
124
|
+
)).status(500).json({ code: e.code, error: e.message });
|
|
139
125
|
}
|
|
140
126
|
}
|
|
141
127
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/BunWebSockets.ts"],
|
|
4
|
-
"sourcesContent": ["/// <reference types=\"bun-types\" />\nimport Bun, {
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/// <reference types=\"bun-types\" />\nimport Bun, { ServerWebSocket, WebSocketHandler } from \"bun\";\n\nimport http from 'http';\nimport bunExpress from \"bun-serve-express\";\n\nimport { DummyServer, ErrorCode, matchMaker, Transport, debugAndPrintError, spliceOne, ServerError } from '@colyseus/core';\nimport { WebSocketClient, WebSocketWrapper } from './WebSocketClient';\nimport { Application, Request, Response } from \"express\";\n\nexport type TransportOptions = Partial<Omit<WebSocketHandler, \"message\" | \"open\" | \"drain\" | \"close\" | \"ping\" | \"pong\">>;\n\ninterface WebSocketData {\n url: URL;\n // query: string,\n // headers: { [key: string]: string },\n // connection: { remoteAddress: string },\n}\n\nexport class BunWebSockets extends Transport {\n public expressApp: Application;\n\n protected clients: ServerWebSocket<WebSocketData>[] = [];\n protected clientWrappers = new WeakMap<ServerWebSocket<WebSocketData>, WebSocketWrapper>();\n\n private _listening: any;\n\n constructor(private options: TransportOptions = {}) {\n super();\n\n const self = this;\n\n this.expressApp = bunExpress({\n websocket: {\n ...this.options,\n\n async open(ws) {\n await self.onConnection(ws);\n },\n\n message(ws, message) {\n // this.clientWrappers.get(ws)?.emit('message', Buffer.from(message.slice(0)));\n self.clientWrappers.get(ws)?.emit('message', message);\n },\n\n close(ws, code, reason) {\n // remove from client list\n spliceOne(self.clients, self.clients.indexOf(ws));\n\n const clientWrapper = self.clientWrappers.get(ws);\n if (clientWrapper) {\n self.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n }\n });\n\n // Adding a mock object for Transport.server\n if (!this.server) {\n this.server = new DummyServer();\n }\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n this._listening = this.expressApp.listen(port, listeningListener);\n\n this.expressApp.use(`/${matchMaker.controller.matchmakeRoute}`, async (req, res) => {\n try {\n await this.handleMatchMakeRequest(req, res);\n } catch (e) {\n res.status(500).json({\n code: e.code,\n error: e.message\n });\n }\n });\n\n // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n // @ts-ignore\n this.server.emit(\"listening\");\n\n return this;\n }\n\n public shutdown() {\n if (this._listening) {\n this._listening.close();\n\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n const originalRawSend = WebSocketClient.prototype.raw;\n WebSocketClient.prototype.raw = function () {\n setTimeout(() => originalRawSend.apply(this, arguments), milliseconds);\n }\n }\n\n protected async onConnection(rawClient: ServerWebSocket<WebSocketData>) {\n const wrapper = new WebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const parsedURL = new URL(rawClient.data.url);\n\n const sessionId = parsedURL.searchParams.get(\"sessionId\");\n const processAndRoomId = parsedURL.pathname.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getRoomById(roomId);\n const client = new WebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, parsedURL.searchParams.get(\"reconnectionToken\") as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient as unknown as http.IncomingMessage);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => rawClient.close());\n }\n }\n\n protected async handleMatchMakeRequest (req: Request, res: Response) {\n try {\n switch (req.method) {\n case 'OPTIONS': {\n res.set(Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n ));\n res.status(200).end();\n break;\n }\n\n case 'GET': {\n const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n res.json(await matchMaker.controller.getAvailableRooms(roomName || ''));\n break;\n }\n\n case 'POST': {\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.isGracefullyShuttingDown) {\n throw new ServerError(503, \"server is shutting down\");\n }\n\n const matchedParams = req.path.match(matchMaker.controller.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchMaker.controller.matchmakeRoute);\n const clientOptions = req.body; // Bun.readableStreamToJSON(req.body);\n\n if (clientOptions === undefined) {\n throw new ServerError(500, \"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n res.json(await matchMaker.controller.invokeMethod(method, roomName, clientOptions));\n break;\n }\n\n default: throw new ServerError(500, \"invalid request method\");\n }\n\n } catch (e) {\n res\n .set(Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n ))\n .status(500)\n .json({ code: e.code, error: e.message });\n }\n\n }\n\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/bun-websockets",
|
|
3
|
-
"version": "0.15.0
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"input": "./src/index.ts",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"module": "./build/index.mjs",
|
|
7
7
|
"typings": "./build/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@colyseus/core": "^0.15.0"
|
|
9
|
+
"@colyseus/core": "^0.15.0",
|
|
10
|
+
"bun-serve-express": "^1.0.2",
|
|
11
|
+
"express": "^4.17.1"
|
|
10
12
|
},
|
|
11
13
|
"devDependencies": {
|
|
12
14
|
"bun-types": "^1.0.1"
|
|
@@ -35,5 +37,5 @@
|
|
|
35
37
|
"publishConfig": {
|
|
36
38
|
"access": "public"
|
|
37
39
|
},
|
|
38
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "45e71fef81d12583a6e925982567aa4e7aca215f"
|
|
39
41
|
}
|