crossws 0.4.4 → 0.4.5

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 (50) hide show
  1. package/adapters/bunny.d.ts +2 -0
  2. package/dist/THIRD-PARTY-LICENSES.md +33 -0
  3. package/dist/_chunks/_request.mjs +1 -4
  4. package/dist/_chunks/_types.d.mts +2 -3
  5. package/dist/_chunks/adapter.d.mts +5 -13
  6. package/dist/_chunks/adapter.mjs +6 -7
  7. package/dist/_chunks/bun.d.mts +0 -3
  8. package/dist/_chunks/bunny.d.mts +22 -0
  9. package/dist/_chunks/cloudflare.d.mts +0 -3
  10. package/dist/_chunks/deno.d.mts +0 -3
  11. package/dist/_chunks/error.mjs +1 -4
  12. package/dist/_chunks/libs/ws.mjs +66 -1168
  13. package/dist/_chunks/node.d.mts +36 -7
  14. package/dist/_chunks/node.mjs +129 -0
  15. package/dist/_chunks/peer.mjs +1 -59
  16. package/dist/_chunks/rolldown-runtime.mjs +7 -15
  17. package/dist/_chunks/sse.d.mts +0 -3
  18. package/dist/_chunks/web.d.mts +0 -2
  19. package/dist/adapters/bun.mjs +1 -6
  20. package/dist/adapters/bunny.d.mts +2 -0
  21. package/dist/adapters/bunny.mjs +68 -0
  22. package/dist/adapters/cloudflare.mjs +7 -12
  23. package/dist/adapters/deno.mjs +1 -6
  24. package/dist/adapters/node.d.mts +2 -2
  25. package/dist/adapters/node.mjs +2 -125
  26. package/dist/adapters/sse.mjs +1 -6
  27. package/dist/adapters/uws.d.mts +0 -5
  28. package/dist/adapters/uws.mjs +2 -7
  29. package/dist/index.d.mts +81 -1
  30. package/dist/index.mjs +161 -2
  31. package/dist/server/bun.d.mts +0 -6
  32. package/dist/server/bun.mjs +3 -7
  33. package/dist/server/bunny.d.mts +5 -0
  34. package/dist/server/bunny.mjs +23 -0
  35. package/dist/server/cloudflare.d.mts +0 -6
  36. package/dist/server/cloudflare.mjs +3 -7
  37. package/dist/server/default.d.mts +0 -6
  38. package/dist/server/default.mjs +3 -7
  39. package/dist/server/deno.d.mts +0 -6
  40. package/dist/server/deno.mjs +3 -7
  41. package/dist/server/node.d.mts +0 -6
  42. package/dist/server/node.mjs +3 -9
  43. package/dist/websocket/native.d.mts +0 -2
  44. package/dist/websocket/native.mjs +1 -5
  45. package/dist/websocket/node.d.mts +0 -2
  46. package/dist/websocket/node.mjs +1 -7
  47. package/dist/websocket/sse.d.mts +0 -3
  48. package/dist/websocket/sse.mjs +1 -4
  49. package/package.json +42 -40
  50. package/server/bunny.d.ts +2 -0
@@ -1,4 +1,4 @@
1
- import { n as AdapterInstance, r as AdapterOptions, t as Adapter } from "./adapter.mjs";
1
+ import { a as Hooks, n as AdapterInstance, r as AdapterOptions, t as Adapter } from "./adapter.mjs";
2
2
  import { EventEmitter } from "events";
3
3
  import { Agent, ClientRequest, ClientRequestArgs, IncomingMessage, OutgoingHttpHeaders, Server } from "node:http";
4
4
  import { Duplex, DuplexOptions } from "node:stream";
@@ -6,8 +6,6 @@ import { Server as Server$1 } from "node:https";
6
6
  import { SecureContextOptions } from "node:tls";
7
7
  import { URL } from "node:url";
8
8
  import { ZlibOptions } from "node:zlib";
9
-
10
- //#region types/ws.d.ts
11
9
  type BufferLike = string | Buffer | DataView | number | ArrayBufferView | Uint8Array | ArrayBuffer | SharedArrayBuffer | readonly any[] | readonly number[] | {
12
10
  valueOf(): ArrayBuffer;
13
11
  } | {
@@ -284,8 +282,40 @@ declare class Server$2<T extends typeof WebSocket = typeof WebSocket, U extends
284
282
  }
285
283
  type WebSocketServer = Server$2;
286
284
  declare function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
287
- //#endregion
288
- //#region src/adapters/node.d.ts
285
+ /**
286
+ * A Node.js `(req, socket, head)` upgrade handler.
287
+ */
288
+ type NodeUpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => void | Promise<void>;
289
+ /**
290
+ * Wrap a Node.js `(req, socket, head)` upgrade handler as a {@link Hooks}
291
+ * object that can be mounted via `crossws/server/node`.
292
+ *
293
+ * The wrapped handler takes ownership of the socket; crossws's other
294
+ * lifecycle hooks (`open`/`message`/`close`/`error`) are **not** invoked
295
+ * for connections routed through it.
296
+ *
297
+ * @example
298
+ * ```ts
299
+ * import { WebSocketServer } from "ws";
300
+ * import { fromNodeUpgradeHandler } from "crossws/adapters/node";
301
+ * import { serve } from "crossws/server/node";
302
+ *
303
+ * const wss = new WebSocketServer({ noServer: true });
304
+ * wss.on("connection", (ws) => {
305
+ * ws.on("message", (data) => ws.send(data));
306
+ * });
307
+ *
308
+ * serve({
309
+ * websocket: fromNodeUpgradeHandler((req, socket, head) => {
310
+ * wss.handleUpgrade(req, socket, head, (ws) => {
311
+ * wss.emit("connection", ws, req);
312
+ * });
313
+ * }),
314
+ * fetch: () => new Response("ok"),
315
+ * });
316
+ * ```
317
+ */
318
+ declare function fromNodeUpgradeHandler(handler: NodeUpgradeHandler): Partial<Hooks>;
289
319
  interface NodeAdapter extends AdapterInstance {
290
320
  handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer, webRequest?: Request): Promise<void>;
291
321
  closeAll: (code?: number, data?: string | Buffer, force?: boolean) => void;
@@ -295,5 +325,4 @@ interface NodeOptions extends AdapterOptions {
295
325
  serverOptions?: ServerOptions;
296
326
  }
297
327
  declare const nodeAdapter: Adapter<NodeAdapter, NodeOptions>;
298
- //#endregion
299
- export { NodeOptions as n, nodeAdapter as r, NodeAdapter as t };
328
+ export { fromNodeUpgradeHandler as a, NodeUpgradeHandler as i, NodeOptions as n, nodeAdapter as r, NodeAdapter as t };
@@ -0,0 +1,129 @@
1
+ import { i as AdapterHookable, r as getPeers, t as adapterUtils } from "./adapter.mjs";
2
+ import { n as import_websocket_server } from "./libs/ws.mjs";
3
+ import { n as Message, r as toBufferLike, t as Peer } from "./peer.mjs";
4
+ import { t as WSError } from "./error.mjs";
5
+ import { t as StubRequest } from "./_request.mjs";
6
+ function fromNodeUpgradeHandler(handler) {
7
+ return { async upgrade(request) {
8
+ const node = request.runtime?.node;
9
+ if (!node?.upgrade) throw new Error("[crossws] `fromNodeUpgradeHandler` must be mounted via `crossws/server/node`.");
10
+ await handler(node.req, node.upgrade.socket, node.upgrade.head);
11
+ return { handled: true };
12
+ } };
13
+ }
14
+ const nodeAdapter = (options = {}) => {
15
+ if ("Deno" in globalThis || "Bun" in globalThis) throw new Error("[crossws] Using Node.js adapter in an incompatible environment.");
16
+ const hooks = new AdapterHookable(options);
17
+ const globalPeers = /* @__PURE__ */ new Map();
18
+ const wss = options.wss || new import_websocket_server.default({
19
+ noServer: true,
20
+ handleProtocols: () => false,
21
+ ...options.serverOptions
22
+ });
23
+ wss.on("connection", (ws, nodeReq) => {
24
+ const request = new NodeReqProxy(nodeReq);
25
+ const peers = getPeers(globalPeers, nodeReq._namespace);
26
+ const peer = new NodePeer({
27
+ ws,
28
+ request,
29
+ peers,
30
+ nodeReq,
31
+ namespace: nodeReq._namespace
32
+ });
33
+ peers.add(peer);
34
+ hooks.callHook("open", peer);
35
+ ws.on("message", (data, isBinary) => {
36
+ if (Array.isArray(data)) data = Buffer.concat(data);
37
+ if (!isBinary && Buffer.isBuffer(data)) data = data.toString("utf8");
38
+ hooks.callHook("message", peer, new Message(data, peer));
39
+ });
40
+ ws.on("error", (error) => {
41
+ peers.delete(peer);
42
+ hooks.callHook("error", peer, new WSError(error));
43
+ });
44
+ ws.on("close", (code, reason) => {
45
+ peers.delete(peer);
46
+ hooks.callHook("close", peer, {
47
+ code,
48
+ reason: reason?.toString()
49
+ });
50
+ });
51
+ });
52
+ wss.on("headers", (outgoingHeaders, req) => {
53
+ const upgradeHeaders = req._upgradeHeaders;
54
+ if (upgradeHeaders) for (const [key, value] of new Headers(upgradeHeaders)) outgoingHeaders.push(`${key}: ${value}`);
55
+ });
56
+ return {
57
+ ...adapterUtils(globalPeers),
58
+ handleUpgrade: async (nodeReq, socket, head, webRequest) => {
59
+ const request = webRequest || new NodeReqProxy(nodeReq);
60
+ const { upgradeHeaders, endResponse, handled, context, namespace } = await hooks.upgrade(request);
61
+ if (endResponse) return sendResponse(socket, endResponse);
62
+ if (handled) return;
63
+ nodeReq._request = request;
64
+ nodeReq._upgradeHeaders = upgradeHeaders;
65
+ nodeReq._context = context;
66
+ nodeReq._namespace = namespace;
67
+ wss.handleUpgrade(nodeReq, socket, head, (ws) => {
68
+ wss.emit("connection", ws, nodeReq);
69
+ });
70
+ },
71
+ closeAll: (code, data, force) => {
72
+ for (const client of wss.clients) if (force) client.terminate();
73
+ else client.close(code, data);
74
+ }
75
+ };
76
+ };
77
+ var NodePeer = class extends Peer {
78
+ get remoteAddress() {
79
+ return this._internal.nodeReq.socket?.remoteAddress;
80
+ }
81
+ get context() {
82
+ return this._internal.nodeReq._context;
83
+ }
84
+ send(data, options) {
85
+ const dataBuff = toBufferLike(data);
86
+ const isBinary = typeof dataBuff !== "string";
87
+ this._internal.ws.send(dataBuff, {
88
+ compress: options?.compress,
89
+ binary: isBinary,
90
+ ...options
91
+ });
92
+ return 0;
93
+ }
94
+ publish(topic, data, options) {
95
+ const dataBuff = toBufferLike(data);
96
+ const isBinary = typeof data !== "string";
97
+ const sendOptions = {
98
+ compress: options?.compress,
99
+ binary: isBinary,
100
+ ...options
101
+ };
102
+ for (const peer of this._internal.peers) if (peer !== this && peer._topics.has(topic)) peer._internal.ws.send(dataBuff, sendOptions);
103
+ }
104
+ close(code, data) {
105
+ this._internal.ws.close(code, data);
106
+ }
107
+ terminate() {
108
+ this._internal.ws.terminate();
109
+ }
110
+ };
111
+ var NodeReqProxy = class extends StubRequest {
112
+ constructor(req) {
113
+ const host = req.headers["host"] || "localhost";
114
+ const url = `${req.socket?.encrypted ?? req.headers["x-forwarded-proto"] === "https" ? "https" : "http"}://${host}${req.url}`;
115
+ super(url, { headers: req.headers });
116
+ }
117
+ };
118
+ async function sendResponse(socket, res) {
119
+ const head = [`HTTP/1.1 ${res.status || 200} ${res.statusText || ""}`, ...[...res.headers.entries()].map(([key, value]) => `${key}: ${value}`)];
120
+ socket.write(head.join("\r\n") + "\r\n\r\n");
121
+ if (res.body) for await (const chunk of res.body) socket.write(chunk);
122
+ return new Promise((resolve) => {
123
+ socket.end(() => {
124
+ socket.destroy();
125
+ resolve();
126
+ });
127
+ });
128
+ }
129
+ export { fromNodeUpgradeHandler as n, nodeAdapter as t };
@@ -1,4 +1,3 @@
1
- //#region src/utils.ts
2
1
  const kNodeInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
3
2
  function toBufferLike(val) {
4
3
  if (val === void 0 || val === null) return "";
@@ -24,15 +23,9 @@ function isPlainObject(value) {
24
23
  if (Symbol.toStringTag in value) return Object.prototype.toString.call(value) === "[object Module]";
25
24
  return true;
26
25
  }
27
-
28
- //#endregion
29
- //#region src/message.ts
30
26
  var Message = class {
31
- /** Access to the original [message event](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event) if available. */
32
27
  event;
33
- /** Access to the Peer that emitted the message. */
34
28
  peer;
35
- /** Raw message data (can be of any type). */
36
29
  rawData;
37
30
  #id;
38
31
  #uint8Array;
@@ -45,18 +38,10 @@ var Message = class {
45
38
  this.peer = peer;
46
39
  this.event = event;
47
40
  }
48
- /**
49
- * Unique random [uuid v4](https://developer.mozilla.org/en-US/docs/Glossary/UUID) identifier for the message.
50
- */
51
41
  get id() {
52
42
  if (!this.#id) this.#id = crypto.randomUUID();
53
43
  return this.#id;
54
44
  }
55
- /**
56
- * Get data as [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) value.
57
- *
58
- * If raw data is in any other format or string, it will be automatically converted and encoded.
59
- */
60
45
  uint8Array() {
61
46
  const _uint8Array = this.#uint8Array;
62
47
  if (_uint8Array) return _uint8Array;
@@ -75,11 +60,6 @@ var Message = class {
75
60
  if (rawData instanceof DataView) return this.#uint8Array = new Uint8Array(rawData.buffer, rawData.byteOffset, rawData.byteLength);
76
61
  throw new TypeError(`Unsupported message type: ${Object.prototype.toString.call(rawData)}`);
77
62
  }
78
- /**
79
- * Get data as [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) or [SharedArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) value.
80
- *
81
- * If raw data is in any other format or string, it will be automatically converted and encoded.
82
- */
83
63
  arrayBuffer() {
84
64
  const _arrayBuffer = this.#arrayBuffer;
85
65
  if (_arrayBuffer) return _arrayBuffer;
@@ -87,10 +67,6 @@ var Message = class {
87
67
  if (rawData instanceof ArrayBuffer || rawData instanceof SharedArrayBuffer) return this.#arrayBuffer = rawData;
88
68
  return this.#arrayBuffer = this.uint8Array().buffer;
89
69
  }
90
- /**
91
- * Get data as [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) value.
92
- *
93
- * If raw data is in any other format or string, it will be automatically converted and encoded. */
94
70
  blob() {
95
71
  const _blob = this.#blob;
96
72
  if (_blob) return _blob;
@@ -98,11 +74,6 @@ var Message = class {
98
74
  if (rawData instanceof Blob) return this.#blob = rawData;
99
75
  return this.#blob = new Blob([this.uint8Array()]);
100
76
  }
101
- /**
102
- * Get stringified text version of the message.
103
- *
104
- * If raw data is in any other format, it will be automatically converted and decoded.
105
- */
106
77
  text() {
107
78
  const _text = this.#text;
108
79
  if (_text) return _text;
@@ -110,17 +81,11 @@ var Message = class {
110
81
  if (typeof rawData === "string") return this.#text = rawData;
111
82
  return this.#text = new TextDecoder().decode(this.uint8Array());
112
83
  }
113
- /**
114
- * Get parsed version of the message text with [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
115
- */
116
84
  json() {
117
85
  const _json = this.#json;
118
86
  if (_json) return _json;
119
87
  return this.#json = JSON.parse(this.text());
120
88
  }
121
- /**
122
- * Message data (value varies based on `peer.websocket.binaryType`).
123
- */
124
89
  get data() {
125
90
  switch (this.peer?.websocket?.binaryType) {
126
91
  case "arraybuffer": return this.arrayBuffer();
@@ -145,9 +110,6 @@ var Message = class {
145
110
  } };
146
111
  }
147
112
  };
148
-
149
- //#endregion
150
- //#region src/peer.ts
151
113
  var Peer = class {
152
114
  _internal;
153
115
  _topics;
@@ -163,27 +125,14 @@ var Peer = class {
163
125
  get namespace() {
164
126
  return this._internal.namespace;
165
127
  }
166
- /**
167
- * Unique random [uuid v4](https://developer.mozilla.org/en-US/docs/Glossary/UUID) identifier for the peer.
168
- */
169
128
  get id() {
170
129
  if (!this._id) this._id = crypto.randomUUID();
171
130
  return this._id;
172
131
  }
173
- /** IP address of the peer */
174
132
  get remoteAddress() {}
175
- /** upgrade request */
176
133
  get request() {
177
134
  return this._internal.request;
178
135
  }
179
- /**
180
- * Get the [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) instance.
181
- *
182
- * **Note:** crossws adds polyfill for the following properties if native values are not available:
183
- * - `protocol`: Extracted from the `sec-websocket-protocol` header.
184
- * - `extensions`: Extracted from the `sec-websocket-extensions` header.
185
- * - `url`: Extracted from the request URL (http -> ws).
186
- * */
187
136
  get websocket() {
188
137
  if (!this.#ws) {
189
138
  const _ws = this._internal.ws;
@@ -192,23 +141,18 @@ var Peer = class {
192
141
  }
193
142
  return this.#ws;
194
143
  }
195
- /** All connected peers to the server */
196
144
  get peers() {
197
145
  return this._internal.peers || /* @__PURE__ */ new Set();
198
146
  }
199
- /** All topics, this peer has been subscribed to. */
200
147
  get topics() {
201
148
  return this._topics;
202
149
  }
203
- /** Abruptly close the connection */
204
150
  terminate() {
205
151
  this.close();
206
152
  }
207
- /** Subscribe to a topic */
208
153
  subscribe(topic) {
209
154
  this._topics.add(topic);
210
155
  }
211
- /** Unsubscribe from a topic */
212
156
  unsubscribe(topic) {
213
157
  this._topics.delete(topic);
214
158
  }
@@ -239,6 +183,4 @@ function createWsProxy(ws, request) {
239
183
  return value;
240
184
  } });
241
185
  }
242
-
243
- //#endregion
244
- export { toString as i, Message as n, toBufferLike as r, Peer as t };
186
+ export { toString as i, Message as n, toBufferLike as r, Peer as t };
@@ -1,6 +1,4 @@
1
1
  import { createRequire } from "node:module";
2
-
3
- //#region rolldown:runtime
4
2
  var __create = Object.create;
5
3
  var __defProp = Object.defineProperty;
6
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -9,16 +7,12 @@ var __getProtoOf = Object.getPrototypeOf;
9
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
8
  var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
11
9
  var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
- key = keys[i];
15
- if (!__hasOwnProp.call(to, key) && key !== except) {
16
- __defProp(to, key, {
17
- get: ((k) => from[k]).bind(null, key),
18
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
- });
20
- }
21
- }
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
22
16
  }
23
17
  return to;
24
18
  };
@@ -27,6 +21,4 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
21
  enumerable: true
28
22
  }) : target, mod));
29
23
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
-
31
- //#endregion
32
- export { __require as n, __toESM as r, __commonJSMin as t };
24
+ export { __require as n, __toESM as r, __commonJSMin as t };
@@ -1,6 +1,4 @@
1
1
  import { n as AdapterInstance, r as AdapterOptions, t as Adapter } from "./adapter.mjs";
2
-
3
- //#region src/adapters/sse.d.ts
4
2
  interface SSEAdapter extends AdapterInstance {
5
3
  fetch(req: Request): Promise<Response>;
6
4
  }
@@ -8,5 +6,4 @@ interface SSEOptions extends AdapterOptions {
8
6
  bidir?: boolean;
9
7
  }
10
8
  declare const sseAdapter: Adapter<SSEAdapter, SSEOptions>;
11
- //#endregion
12
9
  export { SSEOptions as n, sseAdapter as r, SSEAdapter as t };
@@ -1,4 +1,3 @@
1
- //#region types/web.d.ts
2
1
  /**
3
2
  * A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute.
4
3
  *
@@ -294,5 +293,4 @@ interface WebSocket extends EventTarget {
294
293
  removeEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
295
294
  removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
296
295
  }
297
- //#endregion
298
296
  export { WebSocket as a, MessageEvent as i, Event as n, EventTarget as r, CloseEvent as t };
@@ -1,7 +1,5 @@
1
1
  import { i as AdapterHookable, r as getPeers, t as adapterUtils } from "../_chunks/adapter.mjs";
2
2
  import { n as Message, r as toBufferLike, t as Peer } from "../_chunks/peer.mjs";
3
-
4
- //#region src/adapters/bun.ts
5
3
  const bunAdapter = (options = {}) => {
6
4
  if (typeof Bun === "undefined") throw new Error("[crossws] Using Bun adapter in an incompatible environment.");
7
5
  const hooks = new AdapterHookable(options);
@@ -44,7 +42,6 @@ const bunAdapter = (options = {}) => {
44
42
  }
45
43
  };
46
44
  };
47
- var bun_default = bunAdapter;
48
45
  function getPeer(ws, peers) {
49
46
  if (ws.data.peer) return ws.data.peer;
50
47
  const peer = new BunPeer({
@@ -84,6 +81,4 @@ var BunPeer = class extends Peer {
84
81
  this._internal.ws.terminate();
85
82
  }
86
83
  };
87
-
88
- //#endregion
89
- export { bun_default as default };
84
+ export { bunAdapter as default };
@@ -0,0 +1,2 @@
1
+ import { n as BunnyOptions, r as bunnyAdapter, t as BunnyAdapter } from "../_chunks/bunny.mjs";
2
+ export { BunnyAdapter, BunnyOptions, bunnyAdapter as default };
@@ -0,0 +1,68 @@
1
+ import { i as AdapterHookable, r as getPeers, t as adapterUtils } from "../_chunks/adapter.mjs";
2
+ import { n as Message, r as toBufferLike, t as Peer } from "../_chunks/peer.mjs";
3
+ import { t as WSError } from "../_chunks/error.mjs";
4
+ const bunnyAdapter = (options = {}) => {
5
+ const hooks = new AdapterHookable(options);
6
+ const globalPeers = /* @__PURE__ */ new Map();
7
+ return {
8
+ ...adapterUtils(globalPeers),
9
+ handleUpgrade: async (request) => {
10
+ if (!request.upgradeWebSocket || typeof request.upgradeWebSocket !== "function") throw new Error("[crossws] Bunny adapter requires the request to have an upgradeWebSocket method.");
11
+ const { endResponse, context, namespace, upgradeHeaders } = await hooks.upgrade(request);
12
+ if (endResponse) return endResponse;
13
+ const negotiatedProtocol = (upgradeHeaders instanceof Headers ? upgradeHeaders : new Headers(upgradeHeaders)).get("sec-websocket-protocol") ?? options.protocol;
14
+ const upgradeOptions = {};
15
+ if (negotiatedProtocol) upgradeOptions.protocol = negotiatedProtocol;
16
+ if (options.idleTimeout !== void 0) upgradeOptions.idleTimeout = options.idleTimeout;
17
+ const { response, socket } = request.upgradeWebSocket(Object.keys(upgradeOptions).length > 0 ? upgradeOptions : void 0);
18
+ const remoteAddress = request.headers.get("x-real-ip") || void 0;
19
+ const peers = getPeers(globalPeers, namespace);
20
+ const peer = new BunnyPeer({
21
+ ws: socket,
22
+ request,
23
+ namespace,
24
+ remoteAddress,
25
+ peers,
26
+ context
27
+ });
28
+ peers.add(peer);
29
+ socket.addEventListener("open", () => {
30
+ hooks.callHook("open", peer);
31
+ });
32
+ socket.addEventListener("message", (event) => {
33
+ hooks.callHook("message", peer, new Message(event.data, peer, event));
34
+ });
35
+ socket.addEventListener("close", (event) => {
36
+ peers.delete(peer);
37
+ hooks.callHook("close", peer, {
38
+ code: event.code,
39
+ reason: event.reason
40
+ });
41
+ });
42
+ socket.addEventListener("error", (error) => {
43
+ peers.delete(peer);
44
+ hooks.callHook("error", peer, new WSError(error));
45
+ });
46
+ return response;
47
+ }
48
+ };
49
+ };
50
+ var BunnyPeer = class extends Peer {
51
+ get remoteAddress() {
52
+ return this._internal.remoteAddress;
53
+ }
54
+ send(data) {
55
+ return this._internal.ws.send(toBufferLike(data));
56
+ }
57
+ publish(topic, data) {
58
+ const dataBuff = toBufferLike(data);
59
+ for (const peer of this._internal.peers) if (peer !== this && peer._topics.has(topic)) peer._internal.ws.send(dataBuff);
60
+ }
61
+ close(code, reason) {
62
+ this._internal.ws.close(code, reason);
63
+ }
64
+ terminate() {
65
+ this._internal.ws.close();
66
+ }
67
+ };
68
+ export { bunnyAdapter as default };
@@ -1,16 +1,14 @@
1
1
  import { i as AdapterHookable, r as getPeers, t as adapterUtils } from "../_chunks/adapter.mjs";
2
2
  import { n as Message, r as toBufferLike, t as Peer } from "../_chunks/peer.mjs";
3
- import { t as StubRequest } from "../_chunks/_request.mjs";
4
3
  import { t as WSError } from "../_chunks/error.mjs";
5
- import { env as env$1 } from "cloudflare:workers";
6
-
7
- //#region src/adapters/cloudflare.ts
4
+ import { t as StubRequest } from "../_chunks/_request.mjs";
5
+ import { env } from "cloudflare:workers";
8
6
  const cloudflareAdapter = (opts = {}) => {
9
7
  const hooks = new AdapterHookable(opts);
10
8
  const globalPeers = /* @__PURE__ */ new Map();
11
- const resolveDurableStub = opts.resolveDurableStub || ((_req, env, _context) => {
9
+ const resolveDurableStub = opts.resolveDurableStub || ((_req, env$1, _context) => {
12
10
  const bindingName = opts.bindingName || "$DurableObject";
13
- const binding = (env || env$1)[bindingName];
11
+ const binding = (env$1 || env)[bindingName];
14
12
  if (binding) {
15
13
  const instanceId = binding.idFromName(opts.instanceName || "crossws");
16
14
  return binding.get(instanceId);
@@ -59,7 +57,7 @@ const cloudflareAdapter = (opts = {}) => {
59
57
  headers: upgradeHeaders
60
58
  });
61
59
  },
62
- handleDurableInit: async (obj, state, env) => {},
60
+ handleDurableInit: async (_obj, _state, _env) => {},
63
61
  handleDurableUpgrade: async (obj, request) => {
64
62
  const { upgradeHeaders, endResponse, namespace } = await hooks.upgrade(request);
65
63
  if (endResponse) return endResponse;
@@ -95,7 +93,7 @@ const cloudflareAdapter = (opts = {}) => {
95
93
  return durablePublish(topic, data, opts);
96
94
  },
97
95
  publish: async (topic, data, opts) => {
98
- const stub = await resolveDurableStub(void 0, env$1, void 0);
96
+ const stub = await resolveDurableStub(void 0, env, void 0);
99
97
  if (!stub) throw new Error("[crossws] Durable Object binding cannot be resolved.");
100
98
  try {
101
99
  return await stub.webSocketPublish(topic, data, opts);
@@ -106,7 +104,6 @@ const cloudflareAdapter = (opts = {}) => {
106
104
  }
107
105
  };
108
106
  };
109
- var cloudflare_default = cloudflareAdapter;
110
107
  var CloudflareDurablePeer = class CloudflareDurablePeer extends Peer {
111
108
  get peers() {
112
109
  return new Set(this.#getwebsockets().map((ws) => CloudflareDurablePeer._restore(this._internal.durable, ws)));
@@ -176,6 +173,4 @@ function setAttachedState(ws, state) {
176
173
  ws._crosswsState = state;
177
174
  ws.serializeAttachment(state);
178
175
  }
179
-
180
- //#endregion
181
- export { cloudflare_default as default };
176
+ export { cloudflareAdapter as default };
@@ -1,8 +1,6 @@
1
1
  import { i as AdapterHookable, r as getPeers, t as adapterUtils } from "../_chunks/adapter.mjs";
2
2
  import { n as Message, r as toBufferLike, t as Peer } from "../_chunks/peer.mjs";
3
3
  import { t as WSError } from "../_chunks/error.mjs";
4
-
5
- //#region src/adapters/deno.ts
6
4
  const denoAdapter = (options = {}) => {
7
5
  if (typeof Deno === "undefined") throw new Error("[crossws] Using Deno adapter in an incompatible environment.");
8
6
  const hooks = new AdapterHookable(options);
@@ -45,7 +43,6 @@ const denoAdapter = (options = {}) => {
45
43
  }
46
44
  };
47
45
  };
48
- var deno_default = denoAdapter;
49
46
  var DenoPeer = class extends Peer {
50
47
  get remoteAddress() {
51
48
  return this._internal.denoInfo.remoteAddr?.hostname;
@@ -64,6 +61,4 @@ var DenoPeer = class extends Peer {
64
61
  this._internal.ws.terminate();
65
62
  }
66
63
  };
67
-
68
- //#endregion
69
- export { deno_default as default };
64
+ export { denoAdapter as default };
@@ -1,2 +1,2 @@
1
- import { n as NodeOptions, r as nodeAdapter, t as NodeAdapter } from "../_chunks/node.mjs";
2
- export { NodeAdapter, NodeOptions, nodeAdapter as default };
1
+ import { a as fromNodeUpgradeHandler, i as NodeUpgradeHandler, n as NodeOptions, r as nodeAdapter, t as NodeAdapter } from "../_chunks/node.mjs";
2
+ export { NodeAdapter, NodeOptions, NodeUpgradeHandler, nodeAdapter as default, fromNodeUpgradeHandler };