crossws 0.0.0 → 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.
Files changed (47) hide show
  1. package/LICENSE +46 -0
  2. package/README.md +286 -0
  3. package/adapters/bun.d.ts +1 -0
  4. package/adapters/cloudflare.d.ts +1 -0
  5. package/adapters/deno.d.ts +1 -0
  6. package/adapters/node.d.ts +1 -0
  7. package/dist/adapters/bun.cjs +72 -0
  8. package/dist/adapters/bun.d.cts +13 -0
  9. package/dist/adapters/bun.d.mts +13 -0
  10. package/dist/adapters/bun.d.ts +13 -0
  11. package/dist/adapters/bun.mjs +70 -0
  12. package/dist/adapters/cloudflare.cjs +52 -0
  13. package/dist/adapters/cloudflare.d.cts +12 -0
  14. package/dist/adapters/cloudflare.d.mts +12 -0
  15. package/dist/adapters/cloudflare.d.ts +12 -0
  16. package/dist/adapters/cloudflare.mjs +50 -0
  17. package/dist/adapters/deno.cjs +48 -0
  18. package/dist/adapters/deno.d.cts +10 -0
  19. package/dist/adapters/deno.d.mts +10 -0
  20. package/dist/adapters/deno.d.ts +10 -0
  21. package/dist/adapters/deno.mjs +46 -0
  22. package/dist/adapters/node.cjs +695 -0
  23. package/dist/adapters/node.d.cts +298 -0
  24. package/dist/adapters/node.d.mts +298 -0
  25. package/dist/adapters/node.d.ts +298 -0
  26. package/dist/adapters/node.mjs +687 -0
  27. package/dist/index.cjs +13 -0
  28. package/dist/index.d.cts +67 -0
  29. package/dist/index.d.mts +67 -0
  30. package/dist/index.d.ts +67 -0
  31. package/dist/index.mjs +7 -0
  32. package/dist/shared/crossws.21e14e0d.cjs +59 -0
  33. package/dist/shared/crossws.2ed26345.cjs +3931 -0
  34. package/dist/shared/crossws.9536f626.mjs +54 -0
  35. package/dist/shared/crossws.a5db571c.mjs +3910 -0
  36. package/dist/websocket/index.cjs +5 -0
  37. package/dist/websocket/index.d.cts +10 -0
  38. package/dist/websocket/index.d.mts +10 -0
  39. package/dist/websocket/index.d.ts +10 -0
  40. package/dist/websocket/index.mjs +3 -0
  41. package/dist/websocket/node.cjs +17 -0
  42. package/dist/websocket/node.d.cts +10 -0
  43. package/dist/websocket/node.d.mts +10 -0
  44. package/dist/websocket/node.d.ts +10 -0
  45. package/dist/websocket/node.mjs +15 -0
  46. package/package.json +94 -1
  47. package/websocket.d.ts +1 -0
package/LICENSE ADDED
@@ -0,0 +1,46 @@
1
+ MIT License
2
+
3
+ Copyright (c) Pooya Parsa <pooya@pi0.io>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Bundled with https://github.com/websockets/ws
26
+
27
+ Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
28
+ Copyright (c) 2013 Arnout Kazemier and contributors
29
+ Copyright (c) 2016 Luigi Pinca and contributors
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
32
+ this software and associated documentation files (the "Software"), to deal in
33
+ the Software without restriction, including without limitation the rights to
34
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
35
+ the Software, and to permit persons to whom the Software is furnished to do so,
36
+ subject to the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be included in all
39
+ copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
43
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
44
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
45
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
46
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # ⛨ CrossWS
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![bundle][bundle-src]][bundle-href]
5
+
6
+ <!-- [![npm downloads][npm-downloads-src]][npm-downloads-href] -->
7
+
8
+ <!-- [![Codecov][codecov-src]][codecov-href] -->
9
+
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))
15
+
16
+ 📦 No external dependencies, includes [ws](https://github.com/websockets/ws) for Node.js support
17
+
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.
24
+
25
+ ## Install
26
+
27
+ ```sh
28
+ # npm
29
+ npm install crossws
30
+
31
+ # yarn
32
+ yarn add crossws
33
+
34
+ # pnpm
35
+ pnpm install crossws
36
+
37
+ # bun
38
+ bun install crossws
39
+ ```
40
+
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
124
+
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!
126
+
127
+ ### Integration with **Node.js**
128
+
129
+ 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).
130
+
131
+ ```ts
132
+ // Initialize Server
133
+ import { createServer } from "node:http";
134
+
135
+ const server = createServer((req, res) => {
136
+ res.end(
137
+ `<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
138
+ );
139
+ }).listen(3000);
140
+
141
+ // Initialize WebSocket Hooks
142
+ import nodeWSAdapter from "crossws/adapters/node";
143
+
144
+ const { handleUpgrade } = nodeWSAdapter({ message: console.log });
145
+ server.on("upgrade", handleUpgrade);
146
+ ```
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
+
159
+ See [playground/node.ts](./playground/node.ts) for demo and [src/adapters/node.ts](./src/adapters/node.ts) for implementation.
160
+
161
+ ### Integration with **Bun**
162
+
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.
164
+
165
+ ```ts
166
+ import bunAdapter from "./dist/adapters/bun";
167
+
168
+ const { websocket } = bunAdapter({ message: console.log });
169
+
170
+ Bun.serve({
171
+ port: 3000,
172
+ websocket,
173
+ fetch(req, server) {
174
+ if (server.upgrade(req)) {
175
+ return;
176
+ }
177
+ return new Response(
178
+ `<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
179
+ { headers: { "content-type": "text/html" } },
180
+ );
181
+ },
182
+ });
183
+ ```
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
+
195
+ See [playground/bun.ts](./playground/bun.ts) for demo and [src/adapters/bun.ts](./src/adapters/bun.ts) for implementation.
196
+
197
+ ### Integration with **Deno**
198
+
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.
200
+
201
+ ```ts
202
+ import denoAdapter from "crossws/adapters/deno";
203
+
204
+ const { handleUpgrade } = denoAdapter({ message: console.log });
205
+
206
+ Deno.serve({ port: 3000 }, (req) => {
207
+ if (req.headers.get("upgrade") === "websocket") {
208
+ return handleUpgrade(req);
209
+ }
210
+ return new Response(
211
+ `<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
212
+ { headers: { "content-type": "text/html" } },
213
+ );
214
+ });
215
+ ```
216
+
217
+ **Deno-specific hooks:**
218
+
219
+ - `deno:open (peer)`
220
+ - `deno:message (peer, event)`
221
+ - `deno:close (peer)`
222
+ - `deno:error (peer, error)`
223
+
224
+ See [playground/deno.ts](./playground/deno.ts) for demo and [src/adapters/deno.ts](./src/adapters/deno.ts) for implementation.
225
+
226
+ ### Integration with **Cloudflare Workers**
227
+
228
+ To integrate CrossWS with your Cloudflare Workers, you need to check for the `upgrade` header
229
+
230
+ ```ts
231
+ import cloudflareAdapter from "crossws/adapters/cloudflare";
232
+
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);
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
+ );
244
+ },
245
+ };
246
+ ```
247
+
248
+ **Cloudflare-specific hooks:**
249
+
250
+ - `cloudflare:accept(peer)`
251
+ - `cloudflare:message(peer, event)`
252
+ - `cloudflare:error(peer, event)`
253
+ - `cloudflare:close(peer, event)`
254
+
255
+ See [playground/cloudflare.ts](./playground/cloudflare.ts) for demo and [src/adapters/cloudflare.ts](./src/adapters/cloudflare.ts) for implementation.
256
+
257
+ ### Integration with other runtimes
258
+
259
+ You can define your custom adapters using `defineWebSocketAdapter` wrapper.
260
+
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!
262
+
263
+ ## Development
264
+
265
+ - Clone this repository
266
+ - Install the latest LTS version of [Node.js](https://nodejs.org/en/)
267
+ - Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
268
+ - Install dependencies using `pnpm install`
269
+ - Run interactive tests using `pnpm dev`
270
+
271
+ ## License
272
+
273
+ Made with 💛
274
+
275
+ Published under [MIT License](./LICENSE).
276
+
277
+ <!-- Badges -->
278
+
279
+ [npm-version-src]: https://img.shields.io/npm/v/crossws?style=flat&colorA=18181B&colorB=F0DB4F
280
+ [npm-version-href]: https://npmjs.com/package/crossws
281
+ [npm-downloads-src]: https://img.shields.io/npm/dm/crossws?style=flat&colorA=18181B&colorB=F0DB4F
282
+ [npm-downloads-href]: https://npmjs.com/package/crossws
283
+ [codecov-src]: https://img.shields.io/codecov/c/gh/unjs/crossws/main?style=flat&colorA=18181B&colorB=F0DB4F
284
+ [codecov-href]: https://codecov.io/gh/unjs/crossws
285
+ [bundle-src]: https://img.shields.io/bundlephobia/minzip/crossws?style=flat&colorA=18181B&colorB=F0DB4F
286
+ [bundle-href]: https://bundlephobia.com/result?p=crossws
@@ -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";
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const peer = require('../shared/crossws.21e14e0d.cjs');
4
+
5
+ const bun = peer.defineWebSocketAdapter(
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
+ };
16
+ return {
17
+ websocket: {
18
+ 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));
22
+ },
23
+ open: (ws) => {
24
+ const peer = getPeer(ws);
25
+ hooks["bun:open"]?.(peer, ws);
26
+ hooks.open?.(peer);
27
+ },
28
+ close: (ws) => {
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);
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));
42
+ },
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);
50
+ }
51
+ }
52
+ };
53
+ }
54
+ );
55
+ class WebSocketPeer extends peer.WebSocketPeerBase {
56
+ get id() {
57
+ let addr = this.ctx.bun.ws.remoteAddress;
58
+ if (addr.includes(":")) {
59
+ addr = `[${addr}]`;
60
+ }
61
+ return addr;
62
+ }
63
+ get readyState() {
64
+ return this.ctx.bun.ws.readyState;
65
+ }
66
+ send(message) {
67
+ this.ctx.bun.ws.send(message);
68
+ return 0;
69
+ }
70
+ }
71
+
72
+ module.exports = bun;
@@ -0,0 +1,13 @@
1
+ import { WebSocketAdapter } from '../index.cjs';
2
+
3
+ interface AdapterOptions {
4
+ }
5
+ type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
6
+ websocket: any;
7
+ }>["websocket"];
8
+ interface Adapter {
9
+ websocket: WebSocketHooks;
10
+ }
11
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
12
+
13
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,13 @@
1
+ import { WebSocketAdapter } from '../index.mjs';
2
+
3
+ interface AdapterOptions {
4
+ }
5
+ type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
6
+ websocket: any;
7
+ }>["websocket"];
8
+ interface Adapter {
9
+ websocket: WebSocketHooks;
10
+ }
11
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
12
+
13
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,13 @@
1
+ import { WebSocketAdapter } from '../index.js';
2
+
3
+ interface AdapterOptions {
4
+ }
5
+ type WebSocketHooks = Extract<Parameters<typeof Bun.serve<ContextData>>[0], {
6
+ websocket: any;
7
+ }>["websocket"];
8
+ interface Adapter {
9
+ websocket: WebSocketHooks;
10
+ }
11
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
12
+
13
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,70 @@
1
+ import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeerBase } from '../shared/crossws.9536f626.mjs';
2
+
3
+ const bun = defineWebSocketAdapter(
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
+ };
14
+ return {
15
+ websocket: {
16
+ message: (ws, message) => {
17
+ const peer = getPeer(ws);
18
+ hooks["bun:message"]?.(peer, ws, message);
19
+ hooks.message?.(peer, new WebSocketMessage(message));
20
+ },
21
+ open: (ws) => {
22
+ const peer = getPeer(ws);
23
+ hooks["bun:open"]?.(peer, ws);
24
+ hooks.open?.(peer);
25
+ },
26
+ close: (ws) => {
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);
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));
40
+ },
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);
48
+ }
49
+ }
50
+ };
51
+ }
52
+ );
53
+ class WebSocketPeer extends WebSocketPeerBase {
54
+ get id() {
55
+ let addr = this.ctx.bun.ws.remoteAddress;
56
+ if (addr.includes(":")) {
57
+ addr = `[${addr}]`;
58
+ }
59
+ return addr;
60
+ }
61
+ get readyState() {
62
+ return this.ctx.bun.ws.readyState;
63
+ }
64
+ send(message) {
65
+ this.ctx.bun.ws.send(message);
66
+ return 0;
67
+ }
68
+ }
69
+
70
+ export { bun as default };
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const peer = require('../shared/crossws.21e14e0d.cjs');
4
+
5
+ const cloudflare = peer.defineWebSocketAdapter(
6
+ (hooks, opts = {}) => {
7
+ const handleUpgrade = (request, env, context) => {
8
+ const pair = new WebSocketPair();
9
+ const client = pair[0];
10
+ const server = pair[1];
11
+ const peer$1 = new CloudflareWebSocketPeer({
12
+ cloudflare: { client, server, request, env, context }
13
+ });
14
+ server.accept();
15
+ hooks["cloudflare:accept"]?.(peer$1);
16
+ hooks.open?.(peer$1);
17
+ server.addEventListener("message", (event) => {
18
+ hooks["cloudflare:message"]?.(peer$1, event);
19
+ hooks.message?.(peer$1, new peer.WebSocketMessage(event.data));
20
+ });
21
+ server.addEventListener("error", (event) => {
22
+ hooks["cloudflare:error"]?.(peer$1, event);
23
+ hooks.error?.(peer$1, new peer.WebSocketError(event.error));
24
+ });
25
+ server.addEventListener("close", (event) => {
26
+ hooks["cloudflare:close"]?.(peer$1, event);
27
+ hooks.close?.(peer$1, { code: event.code, reason: event.reason });
28
+ });
29
+ return new Response(null, {
30
+ status: 101,
31
+ webSocket: client
32
+ });
33
+ };
34
+ return {
35
+ handleUpgrade
36
+ };
37
+ }
38
+ );
39
+ class CloudflareWebSocketPeer extends peer.WebSocketPeerBase {
40
+ get id() {
41
+ return void 0;
42
+ }
43
+ get readyState() {
44
+ return this.ctx.cloudflare.client.readyState;
45
+ }
46
+ send(message) {
47
+ this.ctx.cloudflare.server.send(message);
48
+ return 0;
49
+ }
50
+ }
51
+
52
+ module.exports = cloudflare;
@@ -0,0 +1,12 @@
1
+ import { WebSocketAdapter } from '../index.cjs';
2
+ import * as _cf from '@cloudflare/workers-types';
3
+
4
+ type Env = Record<string, any>;
5
+ interface AdapterOptions {
6
+ }
7
+ interface Adapter {
8
+ handleUpgrade(req: _cf.Request, env: Env, context: _cf.ExecutionContext): _cf.Response;
9
+ }
10
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
11
+
12
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,12 @@
1
+ import { WebSocketAdapter } from '../index.mjs';
2
+ import * as _cf from '@cloudflare/workers-types';
3
+
4
+ type Env = Record<string, any>;
5
+ interface AdapterOptions {
6
+ }
7
+ interface Adapter {
8
+ handleUpgrade(req: _cf.Request, env: Env, context: _cf.ExecutionContext): _cf.Response;
9
+ }
10
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
11
+
12
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,12 @@
1
+ import { WebSocketAdapter } from '../index.js';
2
+ import * as _cf from '@cloudflare/workers-types';
3
+
4
+ type Env = Record<string, any>;
5
+ interface AdapterOptions {
6
+ }
7
+ interface Adapter {
8
+ handleUpgrade(req: _cf.Request, env: Env, context: _cf.ExecutionContext): _cf.Response;
9
+ }
10
+ declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
11
+
12
+ export { type Adapter, type AdapterOptions, _default as default };
@@ -0,0 +1,50 @@
1
+ import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeerBase } from '../shared/crossws.9536f626.mjs';
2
+
3
+ const cloudflare = defineWebSocketAdapter(
4
+ (hooks, opts = {}) => {
5
+ const handleUpgrade = (request, env, context) => {
6
+ const pair = new WebSocketPair();
7
+ const client = pair[0];
8
+ const server = pair[1];
9
+ const peer = new CloudflareWebSocketPeer({
10
+ cloudflare: { client, server, request, env, context }
11
+ });
12
+ server.accept();
13
+ hooks["cloudflare:accept"]?.(peer);
14
+ hooks.open?.(peer);
15
+ server.addEventListener("message", (event) => {
16
+ hooks["cloudflare:message"]?.(peer, event);
17
+ hooks.message?.(peer, new WebSocketMessage(event.data));
18
+ });
19
+ server.addEventListener("error", (event) => {
20
+ hooks["cloudflare:error"]?.(peer, event);
21
+ hooks.error?.(peer, new WebSocketError(event.error));
22
+ });
23
+ server.addEventListener("close", (event) => {
24
+ hooks["cloudflare:close"]?.(peer, event);
25
+ hooks.close?.(peer, { code: event.code, reason: event.reason });
26
+ });
27
+ return new Response(null, {
28
+ status: 101,
29
+ webSocket: client
30
+ });
31
+ };
32
+ return {
33
+ handleUpgrade
34
+ };
35
+ }
36
+ );
37
+ class CloudflareWebSocketPeer extends WebSocketPeerBase {
38
+ get id() {
39
+ return void 0;
40
+ }
41
+ get readyState() {
42
+ return this.ctx.cloudflare.client.readyState;
43
+ }
44
+ send(message) {
45
+ this.ctx.cloudflare.server.send(message);
46
+ return 0;
47
+ }
48
+ }
49
+
50
+ export { cloudflare as default };