crossws 0.0.1 → 0.1.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 +155 -56
- package/adapters/bun.d.ts +1 -0
- package/adapters/cloudflare.d.ts +1 -0
- package/adapters/deno.d.ts +1 -0
- package/adapters/node.d.ts +1 -0
- package/dist/adapters/bun.cjs +44 -29
- package/dist/adapters/bun.d.cts +5 -35
- package/dist/adapters/bun.d.mts +5 -35
- package/dist/adapters/bun.d.ts +5 -35
- package/dist/adapters/bun.mjs +44 -26
- package/dist/adapters/cloudflare.cjs +52 -0
- package/dist/adapters/cloudflare.d.cts +12 -0
- package/dist/adapters/cloudflare.d.mts +12 -0
- package/dist/adapters/cloudflare.d.ts +12 -0
- package/dist/adapters/cloudflare.mjs +50 -0
- package/dist/adapters/deno.cjs +20 -29
- package/dist/adapters/deno.d.cts +2 -10
- package/dist/adapters/deno.d.mts +2 -10
- package/dist/adapters/deno.d.ts +2 -10
- package/dist/adapters/deno.mjs +20 -26
- package/dist/adapters/node.cjs +57 -3891
- package/dist/adapters/node.d.cts +36 -37
- package/dist/adapters/node.d.mts +36 -37
- package/dist/adapters/node.d.ts +36 -37
- package/dist/adapters/node.mjs +48 -3872
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +40 -10
- package/dist/index.d.mts +40 -10
- package/dist/index.d.ts +40 -10
- package/dist/index.mjs +4 -4
- package/dist/shared/{crossws.002417e5.cjs → crossws.21e14e0d.cjs} +7 -4
- package/dist/shared/crossws.2ed26345.cjs +3931 -0
- package/dist/shared/{crossws.08866fa6.mjs → crossws.9536f626.mjs} +7 -4
- package/dist/shared/crossws.a5db571c.mjs +3910 -0
- package/dist/websocket/index.cjs +5 -0
- package/dist/websocket/index.d.cts +10 -0
- package/dist/websocket/index.d.mts +10 -0
- package/dist/websocket/index.d.ts +10 -0
- package/dist/websocket/index.mjs +3 -0
- package/dist/websocket/node.cjs +17 -0
- package/dist/websocket/node.d.cts +10 -0
- package/dist/websocket/node.d.mts +10 -0
- package/dist/websocket/node.d.ts +10 -0
- package/dist/websocket/node.mjs +15 -0
- package/package.json +44 -17
- package/websocket.d.ts +1 -0
package/README.md
CHANGED
|
@@ -7,17 +7,20 @@
|
|
|
7
7
|
|
|
8
8
|
<!-- [![Codecov][codecov-src]][codecov-href] -->
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
👉 Elegant, typed, and simple interface to implement platform-agnostic WebSocket servers
|
|
11
|
+
|
|
12
|
+
🧩 Seamlessly integrates with, [Node.js](https://nodejs.org/en), [Bun](https://bun.sh/), [Deno](https://deno.com/) and [Cloudflare Workers](https://workers.cloudflare.com/)!
|
|
13
|
+
|
|
14
|
+
🚀 High-performance server hooks, avoiding heavy per-connection events API ([why](https://bun.sh/docs/api/websockets#lcYFjkFYJC-summary))
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
📦 No external dependencies, includes [ws](https://github.com/websockets/ws) for Node.js support
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
💡 Extremely lightweight and tree-shakable packaging with ESM and CJS support
|
|
19
|
+
|
|
20
|
+
🔍 Developer-friendly object logging
|
|
21
|
+
|
|
22
|
+
> [!WARNING]
|
|
23
|
+
> This project and API are under development.
|
|
21
24
|
|
|
22
25
|
## Install
|
|
23
26
|
|
|
@@ -35,9 +38,91 @@ pnpm install crossws
|
|
|
35
38
|
bun install crossws
|
|
36
39
|
```
|
|
37
40
|
|
|
38
|
-
##
|
|
41
|
+
## Unified Hooks
|
|
42
|
+
|
|
43
|
+
CrossWS provides a cross-platform API to define WebSocket servers. An implementation with these hooks works across runtimes without needing you to go into details of any of them (while you always have the power to control low-level hooks). You can only define the life-cycle hooks that you only need and only those will be called run runtime.
|
|
44
|
+
|
|
45
|
+
> [!NOTE]
|
|
46
|
+
> For type support and IDE auto-completion, you can use `defineWebSocketHooks` utility or `WebSocketHooks` type export from the main.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { defineWebSocketHooks } from "crossws";
|
|
50
|
+
|
|
51
|
+
const websocketHooks = defineWebSocketHooks({
|
|
52
|
+
open(peer) {
|
|
53
|
+
console.log("[ws] open", peer);
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
message(peer, message) {
|
|
57
|
+
console.log("[ws] message", peer, message);
|
|
58
|
+
if (message.text().includes("ping")) {
|
|
59
|
+
peer.send("pong");
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
close(peer, event) {
|
|
64
|
+
console.log("[ws] close", peer, event);
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
error(peer, error) {
|
|
68
|
+
console.log("[ws] error", peer, error);
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// ... platform hooks such as bun:drain ...
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Peer Object
|
|
76
|
+
|
|
77
|
+
Websocket hooks always accept a peer instance as the first argument. `peer`, keeps the state of the connected client.
|
|
78
|
+
|
|
79
|
+
**Properties:**
|
|
80
|
+
|
|
81
|
+
- `peer.id?`: The peer address or unique id (might be `undefined`)
|
|
82
|
+
- `peer.readyState`: The connection status ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState))
|
|
83
|
+
- `peer.ctx[name]`: Keeps the state of native client connection
|
|
84
|
+
|
|
85
|
+
**Methods:**
|
|
86
|
+
|
|
87
|
+
- `send(message, compress)`: Send a message to the connected client
|
|
88
|
+
|
|
89
|
+
> [!TIP]
|
|
90
|
+
> You can safely log a peer instance to the console using `console.log` it will be automatically stringified with useful information including the remote address and connection status!
|
|
91
|
+
|
|
92
|
+
### Message Object
|
|
93
|
+
|
|
94
|
+
on `message` hook, you receive a message object containing an incoming message from the client.
|
|
95
|
+
|
|
96
|
+
**Properties:**
|
|
97
|
+
|
|
98
|
+
- `message.rawData`: Raw message data
|
|
99
|
+
- `message.isBinary`: Indicates if the message is binary (might be `undefined`)
|
|
100
|
+
|
|
101
|
+
**Methods:**
|
|
102
|
+
|
|
103
|
+
- `message.text()`: Get stringified version of the message
|
|
104
|
+
|
|
105
|
+
> [!TIP]
|
|
106
|
+
> You can safely log `message` object to the console using `console.log` it will be automatically stringified!
|
|
107
|
+
|
|
108
|
+
## Error handling
|
|
109
|
+
|
|
110
|
+
You can catch errors using `error` hook. The second argument is error wrapped into a `WebSocketError` class.
|
|
111
|
+
|
|
112
|
+
## Universal WebSocket client
|
|
113
|
+
|
|
114
|
+
CrossWS also exposes a universal way to use [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) API in order to connect to the server. For all runtimes, except Node.js, native implementation is used, and for Node.js, a bundled version of [`ws.WebSocket`](https://www.npmjs.com/package/ws) is bundled.
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
import WebSocket from "crossws/websocket";
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
> [!NOTE]
|
|
121
|
+
> Using export conditions, the correct version will be always used so you don't have to worry about picking the right build!
|
|
122
|
+
|
|
123
|
+
## Integrations
|
|
39
124
|
|
|
40
|
-
CrossWS allows integrating your WebSocket
|
|
125
|
+
CrossWS allows integrating your WebSocket hooks with different runtimes and platforms using built-in adapters. Each runtime has a specific method of integrating WebSocket. Once integrated, your custom hooks (such as `message` and `close`) will work consistently even if you change the runtime!
|
|
41
126
|
|
|
42
127
|
### Integration with **Node.js**
|
|
43
128
|
|
|
@@ -53,26 +138,38 @@ const server = createServer((req, res) => {
|
|
|
53
138
|
);
|
|
54
139
|
}).listen(3000);
|
|
55
140
|
|
|
56
|
-
// Initialize WebSocket
|
|
141
|
+
// Initialize WebSocket Hooks
|
|
57
142
|
import nodeWSAdapter from "crossws/adapters/node";
|
|
58
143
|
|
|
59
|
-
const { handleUpgrade } = nodeWSAdapter({
|
|
144
|
+
const { handleUpgrade } = nodeWSAdapter({ message: console.log });
|
|
60
145
|
server.on("upgrade", handleUpgrade);
|
|
61
146
|
```
|
|
62
147
|
|
|
148
|
+
**Node-specific hooks:**
|
|
149
|
+
|
|
150
|
+
- `node:open (peer)`
|
|
151
|
+
- `node:message (peer, data, isBinary)`
|
|
152
|
+
- `node:close (peer, code, reason)`
|
|
153
|
+
- `node:error (peer, error)`
|
|
154
|
+
- `node:ping (peer)`
|
|
155
|
+
- `node:pong (peer)`
|
|
156
|
+
- `node:unexpected-response (peer, req, res)`
|
|
157
|
+
- `node:upgrade (peer, req)`
|
|
158
|
+
|
|
63
159
|
See [playground/node.ts](./playground/node.ts) for demo and [src/adapters/node.ts](./src/adapters/node.ts) for implementation.
|
|
64
160
|
|
|
65
|
-
|
|
161
|
+
### Integration with **Bun**
|
|
66
162
|
|
|
67
|
-
To integrate
|
|
163
|
+
To integrate CrossWS with your Bun server, you need to check for `server.upgrade` and also pass the `websocket` object returned from the adapter to server options. CrossWS leverages native Bun WebSocket API.
|
|
68
164
|
|
|
69
165
|
```ts
|
|
70
166
|
import bunAdapter from "./dist/adapters/bun";
|
|
71
167
|
|
|
72
|
-
const { websocket } = bunAdapter({
|
|
168
|
+
const { websocket } = bunAdapter({ message: console.log });
|
|
73
169
|
|
|
74
170
|
Bun.serve({
|
|
75
171
|
port: 3000,
|
|
172
|
+
websocket,
|
|
76
173
|
fetch(req, server) {
|
|
77
174
|
if (server.upgrade(req)) {
|
|
78
175
|
return;
|
|
@@ -82,20 +179,29 @@ Bun.serve({
|
|
|
82
179
|
{ headers: { "content-type": "text/html" } },
|
|
83
180
|
);
|
|
84
181
|
},
|
|
85
|
-
websocket,
|
|
86
182
|
});
|
|
87
183
|
```
|
|
88
184
|
|
|
185
|
+
**Bun-specific hooks:**
|
|
186
|
+
|
|
187
|
+
- `bun:message (peer, ws,message)`
|
|
188
|
+
- `bun:open (peer, ws)`
|
|
189
|
+
- `bun:close (peer, ws)`
|
|
190
|
+
- `bun:drain (peer)`
|
|
191
|
+
- `bun:error (peer, ws, error)`
|
|
192
|
+
- `bun:ping (peer, ws, data)`
|
|
193
|
+
- `bun:pong (peer, ws, data)`
|
|
194
|
+
|
|
89
195
|
See [playground/bun.ts](./playground/bun.ts) for demo and [src/adapters/bun.ts](./src/adapters/bun.ts) for implementation.
|
|
90
196
|
|
|
91
|
-
|
|
197
|
+
### Integration with **Deno**
|
|
92
198
|
|
|
93
199
|
To integrate CrossWS with your Deno server, you need to check for the `upgrade` header and then call `handleUpgrade` method from the adapter passing the incoming request object. The returned value is the server upgrade response.
|
|
94
200
|
|
|
95
201
|
```ts
|
|
96
202
|
import denoAdapter from "crossws/adapters/deno";
|
|
97
203
|
|
|
98
|
-
const { handleUpgrade } = denoAdapter({
|
|
204
|
+
const { handleUpgrade } = denoAdapter({ message: console.log });
|
|
99
205
|
|
|
100
206
|
Deno.serve({ port: 3000 }, (req) => {
|
|
101
207
|
if (req.headers.get("upgrade") === "websocket") {
|
|
@@ -108,63 +214,56 @@ Deno.serve({ port: 3000 }, (req) => {
|
|
|
108
214
|
});
|
|
109
215
|
```
|
|
110
216
|
|
|
111
|
-
|
|
217
|
+
**Deno-specific hooks:**
|
|
112
218
|
|
|
113
|
-
|
|
219
|
+
- `deno:open (peer)`
|
|
220
|
+
- `deno:message (peer, event)`
|
|
221
|
+
- `deno:close (peer)`
|
|
222
|
+
- `deno:error (peer, error)`
|
|
114
223
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
See other adapter implementations in [./src/adapters](./src/adapters/) to get and idea how adapters can be implemented and feel free to directly make a Pull Request to support your environment in CrossWS!
|
|
118
|
-
|
|
119
|
-
## Handler API
|
|
120
|
-
|
|
121
|
-
Previously you saw in the adapter examples that we pass `onMessage` option.
|
|
224
|
+
See [playground/deno.ts](./playground/deno.ts) for demo and [src/adapters/deno.ts](./src/adapters/deno.ts) for implementation.
|
|
122
225
|
|
|
123
|
-
|
|
226
|
+
### Integration with **Cloudflare Workers**
|
|
124
227
|
|
|
125
|
-
|
|
228
|
+
To integrate CrossWS with your Cloudflare Workers, you need to check for the `upgrade` header
|
|
126
229
|
|
|
127
230
|
```ts
|
|
128
|
-
import
|
|
231
|
+
import cloudflareAdapter from "crossws/adapters/cloudflare";
|
|
129
232
|
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
233
|
+
const { handleUpgrade } = cloudflareAdapter({ message: console.log });
|
|
234
|
+
|
|
235
|
+
export default {
|
|
236
|
+
async fetch(request, env, context) {
|
|
237
|
+
if (request.headers.get("upgrade") === "websocket") {
|
|
238
|
+
return handleUpgrade(request, env, context);
|
|
135
239
|
}
|
|
240
|
+
return new Response(
|
|
241
|
+
`<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
|
|
242
|
+
{ headers: { "content-type": "text/html" } },
|
|
243
|
+
);
|
|
136
244
|
},
|
|
137
|
-
|
|
138
|
-
console.log("error", peer, error);
|
|
139
|
-
},
|
|
140
|
-
onOpen: (peer) => {
|
|
141
|
-
console.log("open", peer);
|
|
142
|
-
},
|
|
143
|
-
onClose: (peer, code, reason) => {
|
|
144
|
-
console.log("close", peer, code, reason);
|
|
145
|
-
},
|
|
146
|
-
onEvent: (event, ...args) => {
|
|
147
|
-
console.log("event", event);
|
|
148
|
-
},
|
|
149
|
-
});
|
|
245
|
+
};
|
|
150
246
|
```
|
|
151
247
|
|
|
152
|
-
|
|
248
|
+
**Cloudflare-specific hooks:**
|
|
153
249
|
|
|
154
|
-
|
|
250
|
+
- `cloudflare:accept(peer)`
|
|
251
|
+
- `cloudflare:message(peer, event)`
|
|
252
|
+
- `cloudflare:error(peer, event)`
|
|
253
|
+
- `cloudflare:close(peer, event)`
|
|
155
254
|
|
|
156
|
-
|
|
255
|
+
See [playground/cloudflare.ts](./playground/cloudflare.ts) for demo and [src/adapters/cloudflare.ts](./src/adapters/cloudflare.ts) for implementation.
|
|
157
256
|
|
|
158
|
-
###
|
|
257
|
+
### Integration with other runtimes
|
|
159
258
|
|
|
160
|
-
|
|
259
|
+
You can define your custom adapters using `defineWebSocketAdapter` wrapper.
|
|
161
260
|
|
|
162
|
-
|
|
261
|
+
See other adapter implementations in [./src/adapters](./src/adapters/) to get an idea of how adapters can be implemented and feel free to directly make a Pull Request to support your environment in CrossWS!
|
|
163
262
|
|
|
164
263
|
## Development
|
|
165
264
|
|
|
166
265
|
- Clone this repository
|
|
167
|
-
- Install latest LTS version of [Node.js](https://nodejs.org/en/)
|
|
266
|
+
- Install the latest LTS version of [Node.js](https://nodejs.org/en/)
|
|
168
267
|
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
|
|
169
268
|
- Install dependencies using `pnpm install`
|
|
170
269
|
- Run interactive tests using `pnpm dev`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../dist/adapters/bun";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../dist/adapters/cloudflare";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../dist/adapters/deno";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../dist/adapters/node";
|
package/dist/adapters/bun.cjs
CHANGED
|
@@ -1,57 +1,72 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const peer = require('../shared/crossws.21e14e0d.cjs');
|
|
4
4
|
|
|
5
|
-
const peer = require('../shared/crossws.002417e5.cjs');
|
|
6
|
-
|
|
7
|
-
const WebSocket = globalThis.WebSocket;
|
|
8
5
|
const bun = peer.defineWebSocketAdapter(
|
|
9
|
-
(
|
|
6
|
+
(hooks, opts = {}) => {
|
|
7
|
+
const getPeer = (ws) => {
|
|
8
|
+
if (ws.data?._peer) {
|
|
9
|
+
return ws.data._peer;
|
|
10
|
+
}
|
|
11
|
+
const peer = new WebSocketPeer({ bun: { ws } });
|
|
12
|
+
ws.data = ws.data || {};
|
|
13
|
+
ws.data._peer = peer;
|
|
14
|
+
return peer;
|
|
15
|
+
};
|
|
10
16
|
return {
|
|
11
17
|
websocket: {
|
|
12
18
|
message: (ws, message) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
const peer$1 = getPeer(ws);
|
|
20
|
+
hooks["bun:message"]?.(peer$1, ws, message);
|
|
21
|
+
hooks.message?.(peer$1, new peer.WebSocketMessage(message));
|
|
16
22
|
},
|
|
17
23
|
open: (ws) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
const peer = getPeer(ws);
|
|
25
|
+
hooks["bun:open"]?.(peer, ws);
|
|
26
|
+
hooks.open?.(peer);
|
|
21
27
|
},
|
|
22
28
|
close: (ws) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
const peer = getPeer(ws);
|
|
30
|
+
hooks["bun:close"]?.(peer, ws);
|
|
31
|
+
hooks.close?.(peer, {});
|
|
32
|
+
},
|
|
33
|
+
drain: (ws) => {
|
|
34
|
+
const peer = getPeer(ws);
|
|
35
|
+
hooks["bun:drain"]?.(peer);
|
|
26
36
|
},
|
|
37
|
+
// @ts-expect-error types unavailable but mentioned in docs
|
|
27
38
|
error: (ws, error) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
const peer$1 = getPeer(ws);
|
|
40
|
+
hooks["bun:error"]?.(peer$1, ws, error);
|
|
41
|
+
hooks.error?.(peer$1, new peer.WebSocketError(error));
|
|
31
42
|
},
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
ping(ws, data) {
|
|
44
|
+
const peer = getPeer(ws);
|
|
45
|
+
hooks["bun:ping"]?.(peer, ws, data);
|
|
46
|
+
},
|
|
47
|
+
pong(ws, data) {
|
|
48
|
+
const peer = getPeer(ws);
|
|
49
|
+
hooks["bun:pong"]?.(peer, ws, data);
|
|
34
50
|
}
|
|
35
51
|
}
|
|
36
52
|
};
|
|
37
53
|
}
|
|
38
54
|
);
|
|
39
|
-
class
|
|
40
|
-
constructor(_ws) {
|
|
41
|
-
super();
|
|
42
|
-
this._ws = _ws;
|
|
43
|
-
}
|
|
55
|
+
class WebSocketPeer extends peer.WebSocketPeerBase {
|
|
44
56
|
get id() {
|
|
45
|
-
|
|
57
|
+
let addr = this.ctx.bun.ws.remoteAddress;
|
|
58
|
+
if (addr.includes(":")) {
|
|
59
|
+
addr = `[${addr}]`;
|
|
60
|
+
}
|
|
61
|
+
return addr;
|
|
46
62
|
}
|
|
47
63
|
get readyState() {
|
|
48
|
-
return this.
|
|
64
|
+
return this.ctx.bun.ws.readyState;
|
|
49
65
|
}
|
|
50
66
|
send(message) {
|
|
51
|
-
this.
|
|
67
|
+
this.ctx.bun.ws.send(message);
|
|
52
68
|
return 0;
|
|
53
69
|
}
|
|
54
70
|
}
|
|
55
71
|
|
|
56
|
-
exports
|
|
57
|
-
exports.default = bun;
|
|
72
|
+
module.exports = bun;
|
package/dist/adapters/bun.d.cts
CHANGED
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
import { WebSocketAdapter } from '../index.cjs';
|
|
2
2
|
|
|
3
|
-
interface BunWSOptions {
|
|
4
|
-
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
-
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
-
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
-
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
-
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
-
perMessageDeflate?: boolean | {
|
|
10
|
-
compress?: boolean | BunWSCompressor;
|
|
11
|
-
decompress?: boolean | BunWSCompressor;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
-
interface BunServerWebSocket {
|
|
16
|
-
readonly data: any;
|
|
17
|
-
readonly readyState: number;
|
|
18
|
-
readonly remoteAddress: string;
|
|
19
|
-
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
-
close(code?: number, reason?: string): void;
|
|
21
|
-
subscribe(topic: string): void;
|
|
22
|
-
unsubscribe(topic: string): void;
|
|
23
|
-
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
-
isSubscribed(topic: string): boolean;
|
|
25
|
-
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
declare const WebSocket: {
|
|
29
|
-
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
-
prototype: WebSocket;
|
|
31
|
-
readonly CONNECTING: 0;
|
|
32
|
-
readonly OPEN: 1;
|
|
33
|
-
readonly CLOSING: 2;
|
|
34
|
-
readonly CLOSED: 3;
|
|
35
|
-
};
|
|
36
3
|
interface AdapterOptions {
|
|
37
4
|
}
|
|
5
|
+
type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
|
|
6
|
+
websocket: any;
|
|
7
|
+
}>["websocket"];
|
|
38
8
|
interface Adapter {
|
|
39
|
-
websocket:
|
|
9
|
+
websocket: WebSocketHooks;
|
|
40
10
|
}
|
|
41
11
|
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
12
|
|
|
43
|
-
export { type Adapter, type AdapterOptions,
|
|
13
|
+
export { type Adapter, type AdapterOptions, _default as default };
|
package/dist/adapters/bun.d.mts
CHANGED
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
import { WebSocketAdapter } from '../index.mjs';
|
|
2
2
|
|
|
3
|
-
interface BunWSOptions {
|
|
4
|
-
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
-
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
-
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
-
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
-
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
-
perMessageDeflate?: boolean | {
|
|
10
|
-
compress?: boolean | BunWSCompressor;
|
|
11
|
-
decompress?: boolean | BunWSCompressor;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
-
interface BunServerWebSocket {
|
|
16
|
-
readonly data: any;
|
|
17
|
-
readonly readyState: number;
|
|
18
|
-
readonly remoteAddress: string;
|
|
19
|
-
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
-
close(code?: number, reason?: string): void;
|
|
21
|
-
subscribe(topic: string): void;
|
|
22
|
-
unsubscribe(topic: string): void;
|
|
23
|
-
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
-
isSubscribed(topic: string): boolean;
|
|
25
|
-
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
declare const WebSocket: {
|
|
29
|
-
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
-
prototype: WebSocket;
|
|
31
|
-
readonly CONNECTING: 0;
|
|
32
|
-
readonly OPEN: 1;
|
|
33
|
-
readonly CLOSING: 2;
|
|
34
|
-
readonly CLOSED: 3;
|
|
35
|
-
};
|
|
36
3
|
interface AdapterOptions {
|
|
37
4
|
}
|
|
5
|
+
type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
|
|
6
|
+
websocket: any;
|
|
7
|
+
}>["websocket"];
|
|
38
8
|
interface Adapter {
|
|
39
|
-
websocket:
|
|
9
|
+
websocket: WebSocketHooks;
|
|
40
10
|
}
|
|
41
11
|
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
12
|
|
|
43
|
-
export { type Adapter, type AdapterOptions,
|
|
13
|
+
export { type Adapter, type AdapterOptions, _default as default };
|
package/dist/adapters/bun.d.ts
CHANGED
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
import { WebSocketAdapter } from '../index.js';
|
|
2
2
|
|
|
3
|
-
interface BunWSOptions {
|
|
4
|
-
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
-
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
-
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
-
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
-
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
-
perMessageDeflate?: boolean | {
|
|
10
|
-
compress?: boolean | BunWSCompressor;
|
|
11
|
-
decompress?: boolean | BunWSCompressor;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
-
interface BunServerWebSocket {
|
|
16
|
-
readonly data: any;
|
|
17
|
-
readonly readyState: number;
|
|
18
|
-
readonly remoteAddress: string;
|
|
19
|
-
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
-
close(code?: number, reason?: string): void;
|
|
21
|
-
subscribe(topic: string): void;
|
|
22
|
-
unsubscribe(topic: string): void;
|
|
23
|
-
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
-
isSubscribed(topic: string): boolean;
|
|
25
|
-
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
declare const WebSocket: {
|
|
29
|
-
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
-
prototype: WebSocket;
|
|
31
|
-
readonly CONNECTING: 0;
|
|
32
|
-
readonly OPEN: 1;
|
|
33
|
-
readonly CLOSING: 2;
|
|
34
|
-
readonly CLOSED: 3;
|
|
35
|
-
};
|
|
36
3
|
interface AdapterOptions {
|
|
37
4
|
}
|
|
5
|
+
type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
|
|
6
|
+
websocket: any;
|
|
7
|
+
}>["websocket"];
|
|
38
8
|
interface Adapter {
|
|
39
|
-
websocket:
|
|
9
|
+
websocket: WebSocketHooks;
|
|
40
10
|
}
|
|
41
11
|
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
12
|
|
|
43
|
-
export { type Adapter, type AdapterOptions,
|
|
13
|
+
export { type Adapter, type AdapterOptions, _default as default };
|
package/dist/adapters/bun.mjs
CHANGED
|
@@ -1,52 +1,70 @@
|
|
|
1
|
-
import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as
|
|
1
|
+
import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeerBase } from '../shared/crossws.9536f626.mjs';
|
|
2
2
|
|
|
3
|
-
const WebSocket = globalThis.WebSocket;
|
|
4
3
|
const bun = defineWebSocketAdapter(
|
|
5
|
-
(
|
|
4
|
+
(hooks, opts = {}) => {
|
|
5
|
+
const getPeer = (ws) => {
|
|
6
|
+
if (ws.data?._peer) {
|
|
7
|
+
return ws.data._peer;
|
|
8
|
+
}
|
|
9
|
+
const peer = new WebSocketPeer({ bun: { ws } });
|
|
10
|
+
ws.data = ws.data || {};
|
|
11
|
+
ws.data._peer = peer;
|
|
12
|
+
return peer;
|
|
13
|
+
};
|
|
6
14
|
return {
|
|
7
15
|
websocket: {
|
|
8
16
|
message: (ws, message) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
const peer = getPeer(ws);
|
|
18
|
+
hooks["bun:message"]?.(peer, ws, message);
|
|
19
|
+
hooks.message?.(peer, new WebSocketMessage(message));
|
|
12
20
|
},
|
|
13
21
|
open: (ws) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
const peer = getPeer(ws);
|
|
23
|
+
hooks["bun:open"]?.(peer, ws);
|
|
24
|
+
hooks.open?.(peer);
|
|
17
25
|
},
|
|
18
26
|
close: (ws) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
const peer = getPeer(ws);
|
|
28
|
+
hooks["bun:close"]?.(peer, ws);
|
|
29
|
+
hooks.close?.(peer, {});
|
|
30
|
+
},
|
|
31
|
+
drain: (ws) => {
|
|
32
|
+
const peer = getPeer(ws);
|
|
33
|
+
hooks["bun:drain"]?.(peer);
|
|
22
34
|
},
|
|
35
|
+
// @ts-expect-error types unavailable but mentioned in docs
|
|
23
36
|
error: (ws, error) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
const peer = getPeer(ws);
|
|
38
|
+
hooks["bun:error"]?.(peer, ws, error);
|
|
39
|
+
hooks.error?.(peer, new WebSocketError(error));
|
|
27
40
|
},
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
ping(ws, data) {
|
|
42
|
+
const peer = getPeer(ws);
|
|
43
|
+
hooks["bun:ping"]?.(peer, ws, data);
|
|
44
|
+
},
|
|
45
|
+
pong(ws, data) {
|
|
46
|
+
const peer = getPeer(ws);
|
|
47
|
+
hooks["bun:pong"]?.(peer, ws, data);
|
|
30
48
|
}
|
|
31
49
|
}
|
|
32
50
|
};
|
|
33
51
|
}
|
|
34
52
|
);
|
|
35
|
-
class
|
|
36
|
-
constructor(_ws) {
|
|
37
|
-
super();
|
|
38
|
-
this._ws = _ws;
|
|
39
|
-
}
|
|
53
|
+
class WebSocketPeer extends WebSocketPeerBase {
|
|
40
54
|
get id() {
|
|
41
|
-
|
|
55
|
+
let addr = this.ctx.bun.ws.remoteAddress;
|
|
56
|
+
if (addr.includes(":")) {
|
|
57
|
+
addr = `[${addr}]`;
|
|
58
|
+
}
|
|
59
|
+
return addr;
|
|
42
60
|
}
|
|
43
61
|
get readyState() {
|
|
44
|
-
return this.
|
|
62
|
+
return this.ctx.bun.ws.readyState;
|
|
45
63
|
}
|
|
46
64
|
send(message) {
|
|
47
|
-
this.
|
|
65
|
+
this.ctx.bun.ws.send(message);
|
|
48
66
|
return 0;
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
|
|
52
|
-
export {
|
|
70
|
+
export { bun as default };
|