crossws 0.1.1 → 0.1.3

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.
Files changed (39) hide show
  1. package/README.md +36 -251
  2. package/adapters/uws.d.ts +2 -0
  3. package/dist/adapters/bun.cjs +52 -29
  4. package/dist/adapters/bun.d.cts +7 -14
  5. package/dist/adapters/bun.d.mts +7 -14
  6. package/dist/adapters/bun.d.ts +7 -14
  7. package/dist/adapters/bun.mjs +52 -29
  8. package/dist/adapters/cloudflare.cjs +26 -16
  9. package/dist/adapters/cloudflare.d.cts +3 -3
  10. package/dist/adapters/cloudflare.d.mts +3 -3
  11. package/dist/adapters/cloudflare.d.ts +3 -3
  12. package/dist/adapters/cloudflare.mjs +26 -16
  13. package/dist/adapters/deno.cjs +32 -17
  14. package/dist/adapters/deno.d.cts +7 -3
  15. package/dist/adapters/deno.d.mts +7 -3
  16. package/dist/adapters/deno.d.ts +7 -3
  17. package/dist/adapters/deno.mjs +31 -16
  18. package/dist/adapters/node.cjs +48 -22
  19. package/dist/adapters/node.d.cts +2 -2
  20. package/dist/adapters/node.d.mts +2 -2
  21. package/dist/adapters/node.d.ts +2 -2
  22. package/dist/adapters/node.mjs +47 -21
  23. package/dist/adapters/uws.cjs +146 -0
  24. package/dist/adapters/uws.d.cts +19 -0
  25. package/dist/adapters/uws.d.mts +19 -0
  26. package/dist/adapters/uws.d.ts +19 -0
  27. package/dist/adapters/uws.mjs +144 -0
  28. package/dist/index.cjs +6 -4
  29. package/dist/index.d.cts +65 -17
  30. package/dist/index.d.mts +65 -17
  31. package/dist/index.d.ts +65 -17
  32. package/dist/index.mjs +2 -1
  33. package/dist/shared/crossws.6009d265.cjs +156 -0
  34. package/dist/shared/crossws.6f7f02b3.mjs +8 -0
  35. package/dist/shared/crossws.a6b0a7cc.mjs +150 -0
  36. package/dist/shared/crossws.deae10fd.cjs +10 -0
  37. package/package.json +28 -6
  38. package/dist/shared/crossws.21e14e0d.cjs +0 -59
  39. package/dist/shared/crossws.9536f626.mjs +0 -54
package/README.md CHANGED
@@ -1,11 +1,19 @@
1
1
  # ⛨ CrossWS
2
2
 
3
- [![npm version][npm-version-src]][npm-version-href]
4
- [![npm downloads][npm-downloads-src]][npm-downloads-href]
3
+ <!-- automd:badges -->
5
4
 
6
- 👉 Elegant, typed, and simple interface to implement platform-agnostic WebSocket servers
5
+ [![npm version](https://flat.badgen.net/npm/v/crossws)](https://npmjs.com/package/crossws)
6
+ [![npm downloads](https://flat.badgen.net/npm/dm/crossws)](https://npmjs.com/package/crossws)
7
7
 
8
- 🧩 Seamlessly integrates with, [Node.js](https://nodejs.org/en), [Bun](https://bun.sh/), [Deno](https://deno.com/) and [Cloudflare Workers](https://workers.cloudflare.com/)!
8
+ <!-- /automd -->
9
+
10
+ Elegant, typed, and simple interface to implement platform-agnostic WebSocket servers.
11
+
12
+ 👉 [📖 documentation](https://crossws.unjs.io)
13
+
14
+ ## Features
15
+
16
+ 🧩 Seamlessly integrates with, [Bun](https://bun.sh/), [Deno](https://deno.com/), [Cloudflare Workers](https://workers.cloudflare.com/) and [Node.js](https://nodejs.org/en) ([ws](https://github.com/websockets/ws) || [uWebSockets](https://github.com/uNetworking/uWebSockets.js)).
9
17
 
10
18
  🚀 High-performance server hooks, avoiding heavy per-connection events API ([why](https://bun.sh/docs/api/websockets#lcYFjkFYJC-summary))
11
19
 
@@ -15,264 +23,41 @@
15
23
 
16
24
  🔍 Developer-friendly object logging
17
25
 
18
- > [!WARNING]
26
+ > [!IMPORTANT]
19
27
  > This project and API are under development.
20
28
 
21
- ## Install
22
-
23
- ```sh
24
- # npm
25
- npm install crossws
26
-
27
- # yarn
28
- yarn add crossws
29
-
30
- # pnpm
31
- pnpm install crossws
32
-
33
- # bun
34
- bun install crossws
35
- ```
36
-
37
- ## Unified Hooks
38
-
39
- 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.
40
-
41
- > [!NOTE]
42
- > For type support and IDE auto-completion, you can use `defineWebSocketHooks` utility or `WebSocketHooks` type export from the main.
43
-
44
- ```ts
45
- import { defineWebSocketHooks } from "crossws";
46
-
47
- const websocketHooks = defineWebSocketHooks({
48
- open(peer) {
49
- console.log("[ws] open", peer);
50
- },
51
-
52
- message(peer, message) {
53
- console.log("[ws] message", peer, message);
54
- if (message.text().includes("ping")) {
55
- peer.send("pong");
56
- }
57
- },
58
-
59
- close(peer, event) {
60
- console.log("[ws] close", peer, event);
61
- },
62
-
63
- error(peer, error) {
64
- console.log("[ws] error", peer, error);
65
- },
66
-
67
- // ... platform hooks such as bun:drain ...
68
- });
69
- ```
70
-
71
- ### Peer Object
72
-
73
- Websocket hooks always accept a peer instance as the first argument. `peer`, keeps the state of the connected client.
74
-
75
- **Properties:**
76
-
77
- - `peer.id?`: The peer address or unique id (might be `undefined`)
78
- - `peer.readyState`: The connection status ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState))
79
- - `peer.ctx[name]`: Keeps the state of native client connection
80
-
81
- **Methods:**
82
-
83
- - `send(message, compress)`: Send a message to the connected client
84
-
85
- > [!TIP]
86
- > 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!
87
-
88
- ### Message Object
89
-
90
- on `message` hook, you receive a message object containing an incoming message from the client.
91
-
92
- **Properties:**
93
-
94
- - `message.rawData`: Raw message data
95
- - `message.isBinary`: Indicates if the message is binary (might be `undefined`)
96
-
97
- **Methods:**
98
-
99
- - `message.text()`: Get stringified version of the message
100
-
101
- > [!TIP]
102
- > You can safely log `message` object to the console using `console.log` it will be automatically stringified!
103
-
104
- ## Error handling
105
-
106
- You can catch errors using `error` hook. The second argument is error wrapped into a `WebSocketError` class.
107
-
108
- ## Universal WebSocket client
109
-
110
- 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.
111
-
112
- ```js
113
- import WebSocket from "crossws/websocket";
114
- ```
115
-
116
- > [!NOTE]
117
- > Using export conditions, the correct version will be always used so you don't have to worry about picking the right build!
118
-
119
- ## Integrations
120
-
121
- 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!
122
-
123
- ### Integration with **Node.js**
29
+ ## Contribution
124
30
 
125
- To integrate CrossWS with your Node.js HTTP server, you need to connect the `upgrade` event to the `handleUpgrade` method returned from the adapter. Behind the scenes, CrossWS uses an embedded version of [ws](https://github.com/websockets/ws).
126
-
127
- ```ts
128
- // Initialize Server
129
- import { createServer } from "node:http";
130
-
131
- const server = createServer((req, res) => {
132
- res.end(
133
- `<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
134
- );
135
- }).listen(3000);
136
-
137
- // Initialize WebSocket Hooks
138
- import nodeWSAdapter from "crossws/adapters/node";
139
-
140
- const { handleUpgrade } = nodeWSAdapter({ message: console.log });
141
- server.on("upgrade", handleUpgrade);
142
- ```
143
-
144
- **Node-specific hooks:**
145
-
146
- - `node:open (peer)`
147
- - `node:message (peer, data, isBinary)`
148
- - `node:close (peer, code, reason)`
149
- - `node:error (peer, error)`
150
- - `node:ping (peer)`
151
- - `node:pong (peer)`
152
- - `node:unexpected-response (peer, req, res)`
153
- - `node:upgrade (peer, req)`
154
-
155
- See [playground/node.ts](./playground/node.ts) for demo and [src/adapters/node.ts](./src/adapters/node.ts) for implementation.
156
-
157
- ### Integration with **Bun**
158
-
159
- 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.
160
-
161
- ```ts
162
- import bunAdapter from "./dist/adapters/bun";
163
-
164
- const { websocket } = bunAdapter({ message: console.log });
165
-
166
- Bun.serve({
167
- port: 3000,
168
- websocket,
169
- fetch(req, server) {
170
- if (server.upgrade(req)) {
171
- return;
172
- }
173
- return new Response(
174
- `<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
175
- { headers: { "content-type": "text/html" } },
176
- );
177
- },
178
- });
179
- ```
180
-
181
- **Bun-specific hooks:**
182
-
183
- - `bun:message (peer, ws,message)`
184
- - `bun:open (peer, ws)`
185
- - `bun:close (peer, ws)`
186
- - `bun:drain (peer)`
187
- - `bun:error (peer, ws, error)`
188
- - `bun:ping (peer, ws, data)`
189
- - `bun:pong (peer, ws, data)`
190
-
191
- See [playground/bun.ts](./playground/bun.ts) for demo and [src/adapters/bun.ts](./src/adapters/bun.ts) for implementation.
192
-
193
- ### Integration with **Deno**
194
-
195
- 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.
196
-
197
- ```ts
198
- import denoAdapter from "crossws/adapters/deno";
199
-
200
- const { handleUpgrade } = denoAdapter({ message: console.log });
201
-
202
- Deno.serve({ port: 3000 }, (req) => {
203
- if (req.headers.get("upgrade") === "websocket") {
204
- return handleUpgrade(req);
205
- }
206
- return new Response(
207
- `<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
208
- { headers: { "content-type": "text/html" } },
209
- );
210
- });
211
- ```
212
-
213
- **Deno-specific hooks:**
214
-
215
- - `deno:open (peer)`
216
- - `deno:message (peer, event)`
217
- - `deno:close (peer)`
218
- - `deno:error (peer, error)`
219
-
220
- See [playground/deno.ts](./playground/deno.ts) for demo and [src/adapters/deno.ts](./src/adapters/deno.ts) for implementation.
221
-
222
- ### Integration with **Cloudflare Workers**
223
-
224
- To integrate CrossWS with your Cloudflare Workers, you need to check for the `upgrade` header
225
-
226
- ```ts
227
- import cloudflareAdapter from "crossws/adapters/cloudflare";
228
-
229
- const { handleUpgrade } = cloudflareAdapter({ message: console.log });
230
-
231
- export default {
232
- async fetch(request, env, context) {
233
- if (request.headers.get("upgrade") === "websocket") {
234
- return handleUpgrade(request, env, context);
235
- }
236
- return new Response(
237
- `<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
238
- { headers: { "content-type": "text/html" } },
239
- );
240
- },
241
- };
242
- ```
243
-
244
- **Cloudflare-specific hooks:**
245
-
246
- - `cloudflare:accept(peer)`
247
- - `cloudflare:message(peer, event)`
248
- - `cloudflare:error(peer, event)`
249
- - `cloudflare:close(peer, event)`
250
-
251
- See [playground/cloudflare.ts](./playground/cloudflare.ts) for demo and [src/adapters/cloudflare.ts](./src/adapters/cloudflare.ts) for implementation.
252
-
253
- ### Integration with other runtimes
254
-
255
- You can define your custom adapters using `defineWebSocketAdapter` wrapper.
256
-
257
- 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!
258
-
259
- ## Development
31
+ <details>
32
+ <summary>Local development</summary>
260
33
 
261
34
  - Clone this repository
262
35
  - Install the latest LTS version of [Node.js](https://nodejs.org/en/)
263
36
  - Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
264
37
  - Install dependencies using `pnpm install`
265
- - Run interactive tests using `pnpm dev`
38
+ - Run examples using `pnpm play:` scripts
39
+
40
+ </details>
41
+
42
+ <!-- /automd -->
266
43
 
267
44
  ## License
268
45
 
269
- Made with 💛
46
+ <!-- automd:contributors license=MIT author="pi0" -->
47
+
48
+ Published under the [MIT](https://github.com/unjs/crossws/blob/main/LICENSE) license.
49
+ Made by [@pi0](https://github.com/pi0) and [community](https://github.com/unjs/crossws/graphs/contributors) 💛
50
+ <br><br>
51
+ <a href="https://github.com/unjs/crossws/graphs/contributors">
52
+ <img src="https://contrib.rocks/image?repo=unjs/crossws" />
53
+ </a>
54
+
55
+ <!-- /automd -->
56
+
57
+ <!-- automd:with-automd -->
270
58
 
271
- Published under [MIT License](./LICENSE).
59
+ ---
272
60
 
273
- <!-- Badges -->
61
+ _🤖 auto updated with [automd](https://automd.unjs.io)_
274
62
 
275
- [npm-version-src]: https://img.shields.io/npm/v/crossws?style=flat&colorA=18181B&colorB=F0DB4F
276
- [npm-version-href]: https://npmjs.com/package/crossws
277
- [npm-downloads-src]: https://img.shields.io/npm/dm/crossws?style=flat&colorA=18181B&colorB=F0DB4F
278
- [npm-downloads-href]: https://npmjs.com/package/crossws
63
+ <!-- /automd -->
@@ -0,0 +1,2 @@
1
+ export * from "../dist/adapters/uws";
2
+ export { default } from "../dist/adapters/uws";
@@ -1,58 +1,63 @@
1
1
  'use strict';
2
2
 
3
- const peer = require('../shared/crossws.21e14e0d.cjs');
3
+ const peer = require('../shared/crossws.6009d265.cjs');
4
4
 
5
5
  const bun = peer.defineWebSocketAdapter(
6
- (hooks, opts = {}) => {
7
- const getPeer = (ws) => {
6
+ (hooks, options = {}) => {
7
+ const crossws = peer.createCrossWS(hooks, options);
8
+ const getWSPeer = (ws) => {
8
9
  if (ws.data?._peer) {
9
10
  return ws.data._peer;
10
11
  }
11
- const peer = new WebSocketPeer({ bun: { ws } });
12
+ const peer = new BunWSPeer({ bun: { ws } });
12
13
  ws.data = ws.data || {};
13
14
  ws.data._peer = peer;
14
15
  return peer;
15
16
  };
16
17
  return {
18
+ async handleUpgrade(req, server) {
19
+ const { headers } = await crossws.upgrade({
20
+ url: req.url,
21
+ headers: req.headers
22
+ });
23
+ return server.upgrade(req, {
24
+ data: { req, server },
25
+ headers
26
+ });
27
+ },
17
28
  websocket: {
18
29
  message: (ws, message) => {
19
- const peer$1 = getPeer(ws);
20
- hooks["bun:message"]?.(peer$1, ws, message);
21
- hooks.message?.(peer$1, new peer.WebSocketMessage(message));
30
+ const peer$1 = getWSPeer(ws);
31
+ crossws.$("bun:message", peer$1, ws, message);
32
+ crossws.message(peer$1, new peer.WSMessage(message));
22
33
  },
23
34
  open: (ws) => {
24
- const peer = getPeer(ws);
25
- hooks["bun:open"]?.(peer, ws);
26
- hooks.open?.(peer);
35
+ const peer = getWSPeer(ws);
36
+ crossws.$("bun:open", peer, ws);
37
+ crossws.open(peer);
27
38
  },
28
39
  close: (ws) => {
29
- const peer = getPeer(ws);
30
- hooks["bun:close"]?.(peer, ws);
31
- hooks.close?.(peer, {});
40
+ const peer = getWSPeer(ws);
41
+ crossws.$("bun:close", peer, ws);
42
+ crossws.close(peer, {});
32
43
  },
33
44
  drain: (ws) => {
34
- const peer = getPeer(ws);
35
- hooks["bun:drain"]?.(peer);
36
- },
37
- // @ts-expect-error types unavailable but mentioned in docs
38
- error: (ws, error) => {
39
- const peer$1 = getPeer(ws);
40
- hooks["bun:error"]?.(peer$1, ws, error);
41
- hooks.error?.(peer$1, new peer.WebSocketError(error));
45
+ const peer = getWSPeer(ws);
46
+ crossws.$("bun:drain", peer);
42
47
  },
43
48
  ping(ws, data) {
44
- const peer = getPeer(ws);
45
- hooks["bun:ping"]?.(peer, ws, data);
49
+ const peer = getWSPeer(ws);
50
+ crossws.$("bun:ping", peer, ws, data);
46
51
  },
47
52
  pong(ws, data) {
48
- const peer = getPeer(ws);
49
- hooks["bun:pong"]?.(peer, ws, data);
53
+ const peer = getWSPeer(ws);
54
+ crossws.$("bun:pong", peer, ws, data);
50
55
  }
51
56
  }
52
57
  };
53
58
  }
54
59
  );
55
- class WebSocketPeer extends peer.WebSocketPeerBase {
60
+ class BunWSPeer extends peer.WSPeer {
56
61
  get id() {
57
62
  let addr = this.ctx.bun.ws.remoteAddress;
58
63
  if (addr.includes(":")) {
@@ -63,9 +68,27 @@ class WebSocketPeer extends peer.WebSocketPeerBase {
63
68
  get readyState() {
64
69
  return this.ctx.bun.ws.readyState;
65
70
  }
66
- send(message) {
67
- this.ctx.bun.ws.send(message);
68
- return 0;
71
+ get url() {
72
+ return this.ctx.bun.ws.data.req?.url || "/";
73
+ }
74
+ get headers() {
75
+ return this.ctx.bun.ws.data.req?.headers || new Headers();
76
+ }
77
+ send(message, options) {
78
+ return this.ctx.bun.ws.send(peer.toBufferLike(message), options?.compress);
79
+ }
80
+ publish(topic, message, options) {
81
+ return this.ctx.bun.ws.publish(
82
+ topic,
83
+ peer.toBufferLike(message),
84
+ options?.compress
85
+ );
86
+ }
87
+ subscribe(topic) {
88
+ this.ctx.bun.ws.subscribe(topic);
89
+ }
90
+ unsubscribe(topic) {
91
+ this.ctx.bun.ws.unsubscribe(topic);
69
92
  }
70
93
  }
71
94
 
@@ -1,24 +1,17 @@
1
- import { WebSocketAdapter, WebSocketPeerBase } from '../index.cjs';
2
- import { WebSocketHandler, ServerWebSocket } from 'bun';
1
+ import { CrossWSOptions, WebSocketAdapter, WSPeer } from '../index.cjs';
2
+ import { WebSocketHandler, Server } from 'bun';
3
3
 
4
- interface AdapterOptions {
4
+ interface AdapterOptions extends CrossWSOptions {
5
5
  }
6
6
  type ContextData = {
7
- _peer?: WebSocketPeer;
7
+ _peer?: WSPeer;
8
+ req?: Request;
9
+ server?: Server;
8
10
  };
9
11
  interface Adapter {
10
12
  websocket: WebSocketHandler<ContextData>;
13
+ handleUpgrade(req: Request, server: Server): Promise<boolean>;
11
14
  }
12
15
  declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
13
16
 
14
- declare class WebSocketPeer extends WebSocketPeerBase<{
15
- bun: {
16
- ws: ServerWebSocket<ContextData>;
17
- };
18
- }> {
19
- get id(): string;
20
- get readyState(): any;
21
- send(message: string | ArrayBuffer): number;
22
- }
23
-
24
17
  export { type Adapter, type AdapterOptions, _default as default };
@@ -1,24 +1,17 @@
1
- import { WebSocketAdapter, WebSocketPeerBase } from '../index.mjs';
2
- import { WebSocketHandler, ServerWebSocket } from 'bun';
1
+ import { CrossWSOptions, WebSocketAdapter, WSPeer } from '../index.mjs';
2
+ import { WebSocketHandler, Server } from 'bun';
3
3
 
4
- interface AdapterOptions {
4
+ interface AdapterOptions extends CrossWSOptions {
5
5
  }
6
6
  type ContextData = {
7
- _peer?: WebSocketPeer;
7
+ _peer?: WSPeer;
8
+ req?: Request;
9
+ server?: Server;
8
10
  };
9
11
  interface Adapter {
10
12
  websocket: WebSocketHandler<ContextData>;
13
+ handleUpgrade(req: Request, server: Server): Promise<boolean>;
11
14
  }
12
15
  declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
13
16
 
14
- declare class WebSocketPeer extends WebSocketPeerBase<{
15
- bun: {
16
- ws: ServerWebSocket<ContextData>;
17
- };
18
- }> {
19
- get id(): string;
20
- get readyState(): any;
21
- send(message: string | ArrayBuffer): number;
22
- }
23
-
24
17
  export { type Adapter, type AdapterOptions, _default as default };
@@ -1,24 +1,17 @@
1
- import { WebSocketAdapter, WebSocketPeerBase } from '../index.js';
2
- import { WebSocketHandler, ServerWebSocket } from 'bun';
1
+ import { CrossWSOptions, WebSocketAdapter, WSPeer } from '../index.js';
2
+ import { WebSocketHandler, Server } from 'bun';
3
3
 
4
- interface AdapterOptions {
4
+ interface AdapterOptions extends CrossWSOptions {
5
5
  }
6
6
  type ContextData = {
7
- _peer?: WebSocketPeer;
7
+ _peer?: WSPeer;
8
+ req?: Request;
9
+ server?: Server;
8
10
  };
9
11
  interface Adapter {
10
12
  websocket: WebSocketHandler<ContextData>;
13
+ handleUpgrade(req: Request, server: Server): Promise<boolean>;
11
14
  }
12
15
  declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
13
16
 
14
- declare class WebSocketPeer extends WebSocketPeerBase<{
15
- bun: {
16
- ws: ServerWebSocket<ContextData>;
17
- };
18
- }> {
19
- get id(): string;
20
- get readyState(): any;
21
- send(message: string | ArrayBuffer): number;
22
- }
23
-
24
17
  export { type Adapter, type AdapterOptions, _default as default };
@@ -1,56 +1,61 @@
1
- import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeerBase } from '../shared/crossws.9536f626.mjs';
1
+ import { d as defineWebSocketAdapter, c as createCrossWS, W as WSMessage, a as WSPeer, t as toBufferLike } from '../shared/crossws.a6b0a7cc.mjs';
2
2
 
3
3
  const bun = defineWebSocketAdapter(
4
- (hooks, opts = {}) => {
5
- const getPeer = (ws) => {
4
+ (hooks, options = {}) => {
5
+ const crossws = createCrossWS(hooks, options);
6
+ const getWSPeer = (ws) => {
6
7
  if (ws.data?._peer) {
7
8
  return ws.data._peer;
8
9
  }
9
- const peer = new WebSocketPeer({ bun: { ws } });
10
+ const peer = new BunWSPeer({ bun: { ws } });
10
11
  ws.data = ws.data || {};
11
12
  ws.data._peer = peer;
12
13
  return peer;
13
14
  };
14
15
  return {
16
+ async handleUpgrade(req, server) {
17
+ const { headers } = await crossws.upgrade({
18
+ url: req.url,
19
+ headers: req.headers
20
+ });
21
+ return server.upgrade(req, {
22
+ data: { req, server },
23
+ headers
24
+ });
25
+ },
15
26
  websocket: {
16
27
  message: (ws, message) => {
17
- const peer = getPeer(ws);
18
- hooks["bun:message"]?.(peer, ws, message);
19
- hooks.message?.(peer, new WebSocketMessage(message));
28
+ const peer = getWSPeer(ws);
29
+ crossws.$("bun:message", peer, ws, message);
30
+ crossws.message(peer, new WSMessage(message));
20
31
  },
21
32
  open: (ws) => {
22
- const peer = getPeer(ws);
23
- hooks["bun:open"]?.(peer, ws);
24
- hooks.open?.(peer);
33
+ const peer = getWSPeer(ws);
34
+ crossws.$("bun:open", peer, ws);
35
+ crossws.open(peer);
25
36
  },
26
37
  close: (ws) => {
27
- const peer = getPeer(ws);
28
- hooks["bun:close"]?.(peer, ws);
29
- hooks.close?.(peer, {});
38
+ const peer = getWSPeer(ws);
39
+ crossws.$("bun:close", peer, ws);
40
+ crossws.close(peer, {});
30
41
  },
31
42
  drain: (ws) => {
32
- const peer = getPeer(ws);
33
- hooks["bun:drain"]?.(peer);
34
- },
35
- // @ts-expect-error types unavailable but mentioned in docs
36
- error: (ws, error) => {
37
- const peer = getPeer(ws);
38
- hooks["bun:error"]?.(peer, ws, error);
39
- hooks.error?.(peer, new WebSocketError(error));
43
+ const peer = getWSPeer(ws);
44
+ crossws.$("bun:drain", peer);
40
45
  },
41
46
  ping(ws, data) {
42
- const peer = getPeer(ws);
43
- hooks["bun:ping"]?.(peer, ws, data);
47
+ const peer = getWSPeer(ws);
48
+ crossws.$("bun:ping", peer, ws, data);
44
49
  },
45
50
  pong(ws, data) {
46
- const peer = getPeer(ws);
47
- hooks["bun:pong"]?.(peer, ws, data);
51
+ const peer = getWSPeer(ws);
52
+ crossws.$("bun:pong", peer, ws, data);
48
53
  }
49
54
  }
50
55
  };
51
56
  }
52
57
  );
53
- class WebSocketPeer extends WebSocketPeerBase {
58
+ class BunWSPeer extends WSPeer {
54
59
  get id() {
55
60
  let addr = this.ctx.bun.ws.remoteAddress;
56
61
  if (addr.includes(":")) {
@@ -61,9 +66,27 @@ class WebSocketPeer extends WebSocketPeerBase {
61
66
  get readyState() {
62
67
  return this.ctx.bun.ws.readyState;
63
68
  }
64
- send(message) {
65
- this.ctx.bun.ws.send(message);
66
- return 0;
69
+ get url() {
70
+ return this.ctx.bun.ws.data.req?.url || "/";
71
+ }
72
+ get headers() {
73
+ return this.ctx.bun.ws.data.req?.headers || new Headers();
74
+ }
75
+ send(message, options) {
76
+ return this.ctx.bun.ws.send(toBufferLike(message), options?.compress);
77
+ }
78
+ publish(topic, message, options) {
79
+ return this.ctx.bun.ws.publish(
80
+ topic,
81
+ toBufferLike(message),
82
+ options?.compress
83
+ );
84
+ }
85
+ subscribe(topic) {
86
+ this.ctx.bun.ws.subscribe(topic);
87
+ }
88
+ unsubscribe(topic) {
89
+ this.ctx.bun.ws.unsubscribe(topic);
67
90
  }
68
91
  }
69
92