crossws 0.2.3 → 0.3.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 +8 -9
- package/adapters/cloudflare-durable.d.ts +2 -0
- package/adapters/sse.d.ts +2 -0
- package/dist/adapters/bun.d.mts +25 -6
- package/dist/adapters/bun.d.ts +25 -6
- package/dist/adapters/bun.mjs +54 -62
- package/dist/adapters/cloudflare-durable.d.mts +20 -0
- package/dist/adapters/cloudflare-durable.d.ts +20 -0
- package/dist/adapters/cloudflare-durable.mjs +132 -0
- package/dist/adapters/cloudflare.d.mts +5 -5
- package/dist/adapters/cloudflare.d.ts +5 -5
- package/dist/adapters/cloudflare.mjs +56 -49
- package/dist/adapters/deno.d.mts +10 -3
- package/dist/adapters/deno.d.ts +10 -3
- package/dist/adapters/deno.mjs +54 -45
- package/dist/adapters/node.d.mts +4 -2
- package/dist/adapters/node.d.ts +4 -2
- package/dist/adapters/node.mjs +108 -71
- package/dist/adapters/sse.d.mts +12 -0
- package/dist/adapters/sse.d.ts +12 -0
- package/dist/adapters/sse.mjs +120 -0
- package/dist/adapters/uws.d.mts +45 -9
- package/dist/adapters/uws.d.ts +45 -9
- package/dist/adapters/uws.mjs +148 -124
- package/dist/index.d.mts +136 -4
- package/dist/index.d.ts +136 -4
- package/dist/index.mjs +1 -10
- package/dist/shared/crossws.B4sHId41.mjs +42 -0
- package/dist/shared/crossws.By9qWDAI.mjs +8 -0
- package/dist/shared/crossws.ChIJSJVK.d.mts +297 -0
- package/dist/shared/crossws.ChIJSJVK.d.ts +297 -0
- package/dist/shared/crossws.DTY7a69w.mjs +315 -0
- package/dist/shared/{crossws.a5db571c.mjs → crossws.YgHWLi0G.mjs} +284 -115
- package/dist/websocket/{index.d.mts → native.d.mts} +1 -1
- package/dist/websocket/{node.d.cts → native.d.ts} +1 -1
- package/dist/websocket/native.mjs +3 -0
- package/dist/websocket/node.d.mts +1 -1
- package/dist/websocket/node.d.ts +1 -1
- package/dist/websocket/node.mjs +1 -1
- package/dist/websocket/sse.d.mts +41 -0
- package/dist/websocket/sse.d.ts +41 -0
- package/dist/websocket/sse.mjs +127 -0
- package/package.json +78 -75
- package/dist/adapters/bun.cjs +0 -95
- package/dist/adapters/bun.d.cts +0 -17
- package/dist/adapters/cloudflare.cjs +0 -65
- package/dist/adapters/cloudflare.d.cts +0 -12
- package/dist/adapters/deno.cjs +0 -63
- package/dist/adapters/deno.d.cts +0 -15
- package/dist/adapters/node.cjs +0 -726
- package/dist/adapters/node.d.cts +0 -298
- package/dist/adapters/uws.cjs +0 -153
- package/dist/adapters/uws.d.cts +0 -19
- package/dist/index.cjs +0 -17
- package/dist/index.d.cts +0 -6
- package/dist/shared/crossws.2ed26345.cjs +0 -3931
- package/dist/shared/crossws.34cfc8d0.mjs +0 -139
- package/dist/shared/crossws.a2e5c71e.d.cts +0 -112
- package/dist/shared/crossws.a2e5c71e.d.mts +0 -112
- package/dist/shared/crossws.a2e5c71e.d.ts +0 -112
- package/dist/shared/crossws.c13afbe7.cjs +0 -146
- package/dist/websocket/index.cjs +0 -5
- package/dist/websocket/index.d.cts +0 -10
- package/dist/websocket/index.d.ts +0 -10
- package/dist/websocket/index.mjs +0 -3
- package/dist/websocket/node.cjs +0 -17
package/dist/adapters/deno.mjs
CHANGED
|
@@ -1,60 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { M as Message, P as Peer, t as toBufferLike } from '../shared/crossws.DTY7a69w.mjs';
|
|
2
|
+
import { d as defineWebSocketAdapter, a as adapterUtils, A as AdapterHookable } from '../shared/crossws.B4sHId41.mjs';
|
|
3
|
+
import { W as WSError } from '../shared/crossws.By9qWDAI.mjs';
|
|
4
|
+
import 'uncrypto';
|
|
3
5
|
|
|
4
6
|
const deno = defineWebSocketAdapter(
|
|
5
7
|
(options = {}) => {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const { headers } = await crossws.upgrade({
|
|
9
|
-
url: req.url,
|
|
10
|
-
headers: req.headers
|
|
11
|
-
});
|
|
12
|
-
const upgrade = Deno.upgradeWebSocket(req, {
|
|
13
|
-
// @ts-expect-error https://github.com/denoland/deno/pull/22242
|
|
14
|
-
headers
|
|
15
|
-
});
|
|
16
|
-
const peer = new DenoPeer({
|
|
17
|
-
deno: { ws: upgrade.socket, req, info }
|
|
18
|
-
});
|
|
19
|
-
upgrade.socket.addEventListener("open", () => {
|
|
20
|
-
crossws.$callHook("deno:open", peer);
|
|
21
|
-
crossws.callHook("open", peer);
|
|
22
|
-
});
|
|
23
|
-
upgrade.socket.addEventListener("message", (event) => {
|
|
24
|
-
crossws.$callHook("deno:message", peer, event);
|
|
25
|
-
crossws.callHook("message", peer, new Message(event.data));
|
|
26
|
-
});
|
|
27
|
-
upgrade.socket.addEventListener("close", () => {
|
|
28
|
-
crossws.$callHook("deno:close", peer);
|
|
29
|
-
crossws.callHook("close", peer, {});
|
|
30
|
-
});
|
|
31
|
-
upgrade.socket.addEventListener("error", (error) => {
|
|
32
|
-
crossws.$callHook("deno:error", peer, error);
|
|
33
|
-
crossws.callHook("error", peer, new WSError(error));
|
|
34
|
-
});
|
|
35
|
-
return upgrade.response;
|
|
36
|
-
};
|
|
8
|
+
const hooks = new AdapterHookable(options);
|
|
9
|
+
const peers = /* @__PURE__ */ new Set();
|
|
37
10
|
return {
|
|
38
|
-
|
|
11
|
+
...adapterUtils(peers),
|
|
12
|
+
handleUpgrade: async (request, info) => {
|
|
13
|
+
const res = await hooks.callHook("upgrade", request);
|
|
14
|
+
if (res instanceof Response) {
|
|
15
|
+
return res;
|
|
16
|
+
}
|
|
17
|
+
const upgrade = Deno.upgradeWebSocket(request, {
|
|
18
|
+
// @ts-expect-error https://github.com/denoland/deno/pull/22242
|
|
19
|
+
headers: res?.headers
|
|
20
|
+
});
|
|
21
|
+
const peer = new DenoPeer({
|
|
22
|
+
ws: upgrade.socket,
|
|
23
|
+
request,
|
|
24
|
+
peers,
|
|
25
|
+
denoInfo: info
|
|
26
|
+
});
|
|
27
|
+
peers.add(peer);
|
|
28
|
+
upgrade.socket.addEventListener("open", () => {
|
|
29
|
+
hooks.callHook("open", peer);
|
|
30
|
+
});
|
|
31
|
+
upgrade.socket.addEventListener("message", (event) => {
|
|
32
|
+
hooks.callHook("message", peer, new Message(event.data, peer, event));
|
|
33
|
+
});
|
|
34
|
+
upgrade.socket.addEventListener("close", () => {
|
|
35
|
+
peers.delete(peer);
|
|
36
|
+
hooks.callHook("close", peer, {});
|
|
37
|
+
});
|
|
38
|
+
upgrade.socket.addEventListener("error", (error) => {
|
|
39
|
+
peers.delete(peer);
|
|
40
|
+
hooks.callHook("error", peer, new WSError(error));
|
|
41
|
+
});
|
|
42
|
+
return upgrade.response;
|
|
43
|
+
}
|
|
39
44
|
};
|
|
40
45
|
}
|
|
41
46
|
);
|
|
42
47
|
class DenoPeer extends Peer {
|
|
43
|
-
get
|
|
44
|
-
return this.
|
|
48
|
+
get remoteAddress() {
|
|
49
|
+
return this._internal.denoInfo.remoteAddr?.hostname;
|
|
45
50
|
}
|
|
46
|
-
|
|
47
|
-
return this.
|
|
51
|
+
send(data) {
|
|
52
|
+
return this._internal.ws.send(toBufferLike(data));
|
|
48
53
|
}
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
publish(topic, data) {
|
|
55
|
+
const dataBuff = toBufferLike(data);
|
|
56
|
+
for (const peer of this._internal.peers) {
|
|
57
|
+
if (peer !== this && peer._topics.has(topic)) {
|
|
58
|
+
peer._internal.ws.send(dataBuff);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
51
61
|
}
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
close(code, reason) {
|
|
63
|
+
this._internal.ws.close(code, reason);
|
|
54
64
|
}
|
|
55
|
-
|
|
56
|
-
this.
|
|
57
|
-
return 0;
|
|
65
|
+
terminate() {
|
|
66
|
+
this._internal.ws.terminate();
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
|
package/dist/adapters/node.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.mjs';
|
|
2
2
|
import { IncomingMessage as IncomingMessage$1 } from 'node:http';
|
|
3
3
|
import { Duplex as Duplex$1 } from 'node:stream';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
@@ -8,6 +8,7 @@ import { Duplex, DuplexOptions } from 'stream';
|
|
|
8
8
|
import { SecureContextOptions } from 'tls';
|
|
9
9
|
import { URL } from 'url';
|
|
10
10
|
import { ZlibOptions } from 'zlib';
|
|
11
|
+
import '../shared/crossws.ChIJSJVK.mjs';
|
|
11
12
|
|
|
12
13
|
type BufferLike = string | Buffer | DataView | number | ArrayBufferView | Uint8Array | ArrayBuffer | SharedArrayBuffer | readonly any[] | readonly number[] | {
|
|
13
14
|
valueOf(): ArrayBuffer;
|
|
@@ -286,8 +287,9 @@ declare class Server<T extends typeof WebSocket = typeof WebSocket, U extends ty
|
|
|
286
287
|
type WebSocketServer = Server;
|
|
287
288
|
declare function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
|
|
288
289
|
|
|
289
|
-
interface NodeAdapter {
|
|
290
|
+
interface NodeAdapter extends AdapterInstance {
|
|
290
291
|
handleUpgrade(req: IncomingMessage$1, socket: Duplex$1, head: Buffer): void;
|
|
292
|
+
closeAll: (code?: number, data?: string | Buffer) => void;
|
|
291
293
|
}
|
|
292
294
|
interface NodeOptions extends AdapterOptions {
|
|
293
295
|
wss?: WebSocketServer;
|
package/dist/adapters/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.js';
|
|
2
2
|
import { IncomingMessage as IncomingMessage$1 } from 'node:http';
|
|
3
3
|
import { Duplex as Duplex$1 } from 'node:stream';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
@@ -8,6 +8,7 @@ import { Duplex, DuplexOptions } from 'stream';
|
|
|
8
8
|
import { SecureContextOptions } from 'tls';
|
|
9
9
|
import { URL } from 'url';
|
|
10
10
|
import { ZlibOptions } from 'zlib';
|
|
11
|
+
import '../shared/crossws.ChIJSJVK.js';
|
|
11
12
|
|
|
12
13
|
type BufferLike = string | Buffer | DataView | number | ArrayBufferView | Uint8Array | ArrayBuffer | SharedArrayBuffer | readonly any[] | readonly number[] | {
|
|
13
14
|
valueOf(): ArrayBuffer;
|
|
@@ -286,8 +287,9 @@ declare class Server<T extends typeof WebSocket = typeof WebSocket, U extends ty
|
|
|
286
287
|
type WebSocketServer = Server;
|
|
287
288
|
declare function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
|
|
288
289
|
|
|
289
|
-
interface NodeAdapter {
|
|
290
|
+
interface NodeAdapter extends AdapterInstance {
|
|
290
291
|
handleUpgrade(req: IncomingMessage$1, socket: Duplex$1, head: Buffer): void;
|
|
292
|
+
closeAll: (code?: number, data?: string | Buffer) => void;
|
|
291
293
|
}
|
|
292
294
|
interface NodeOptions extends AdapterOptions {
|
|
293
295
|
wss?: WebSocketServer;
|
package/dist/adapters/node.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { M as Message, P as Peer, t as toBufferLike } from '../shared/crossws.DTY7a69w.mjs';
|
|
2
|
+
import { d as defineWebSocketAdapter, a as adapterUtils, A as AdapterHookable } from '../shared/crossws.B4sHId41.mjs';
|
|
3
|
+
import { W as WSError } from '../shared/crossws.By9qWDAI.mjs';
|
|
1
4
|
import 'stream';
|
|
2
|
-
import { v as validationExports, g as getDefaultExportFromCjs, e as extension$1, p as permessageDeflate, w as websocket, c as constants } from '../shared/crossws.
|
|
5
|
+
import { v as validationExports, g as getDefaultExportFromCjs, e as extension$1, p as permessageDeflate, w as websocket, c as constants } from '../shared/crossws.YgHWLi0G.mjs';
|
|
3
6
|
import require$$0 from 'events';
|
|
4
7
|
import require$$2 from 'http';
|
|
5
8
|
import require$$1 from 'crypto';
|
|
6
|
-
import
|
|
7
|
-
import { WSError } from '../index.mjs';
|
|
9
|
+
import 'uncrypto';
|
|
8
10
|
import 'https';
|
|
9
11
|
import 'net';
|
|
10
12
|
import 'tls';
|
|
@@ -73,7 +75,7 @@ function parse(header) {
|
|
|
73
75
|
|
|
74
76
|
var subprotocol$1 = { parse };
|
|
75
77
|
|
|
76
|
-
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$" }] */
|
|
78
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */
|
|
77
79
|
|
|
78
80
|
const EventEmitter = require$$0;
|
|
79
81
|
const http = require$$2;
|
|
@@ -101,7 +103,7 @@ class WebSocketServer extends EventEmitter {
|
|
|
101
103
|
* Create a `WebSocketServer` instance.
|
|
102
104
|
*
|
|
103
105
|
* @param {Object} options Configuration options
|
|
104
|
-
* @param {Boolean} [options.allowSynchronousEvents=
|
|
106
|
+
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
|
|
105
107
|
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
|
106
108
|
* multiple times in the same tick
|
|
107
109
|
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
|
|
@@ -132,7 +134,7 @@ class WebSocketServer extends EventEmitter {
|
|
|
132
134
|
super();
|
|
133
135
|
|
|
134
136
|
options = {
|
|
135
|
-
allowSynchronousEvents:
|
|
137
|
+
allowSynchronousEvents: true,
|
|
136
138
|
autoPong: true,
|
|
137
139
|
maxPayload: 100 * 1024 * 1024,
|
|
138
140
|
skipUTF8Validation: false,
|
|
@@ -307,6 +309,7 @@ class WebSocketServer extends EventEmitter {
|
|
|
307
309
|
socket.on('error', socketOnError);
|
|
308
310
|
|
|
309
311
|
const key = req.headers['sec-websocket-key'];
|
|
312
|
+
const upgrade = req.headers.upgrade;
|
|
310
313
|
const version = +req.headers['sec-websocket-version'];
|
|
311
314
|
|
|
312
315
|
if (req.method !== 'GET') {
|
|
@@ -315,13 +318,13 @@ class WebSocketServer extends EventEmitter {
|
|
|
315
318
|
return;
|
|
316
319
|
}
|
|
317
320
|
|
|
318
|
-
if (
|
|
321
|
+
if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
|
|
319
322
|
const message = 'Invalid Upgrade header';
|
|
320
323
|
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
321
324
|
return;
|
|
322
325
|
}
|
|
323
326
|
|
|
324
|
-
if (
|
|
327
|
+
if (key === undefined || !keyRegex.test(key)) {
|
|
325
328
|
const message = 'Missing or invalid Sec-WebSocket-Key header';
|
|
326
329
|
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
327
330
|
return;
|
|
@@ -614,105 +617,139 @@ const _WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServer);
|
|
|
614
617
|
|
|
615
618
|
const node = defineWebSocketAdapter(
|
|
616
619
|
(options = {}) => {
|
|
617
|
-
const
|
|
620
|
+
const hooks = new AdapterHookable(options);
|
|
621
|
+
const peers = /* @__PURE__ */ new Set();
|
|
618
622
|
const wss = options.wss || new _WebSocketServer({
|
|
619
623
|
noServer: true,
|
|
620
624
|
...options.serverOptions
|
|
621
625
|
});
|
|
622
|
-
wss.on("connection", (ws,
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
626
|
+
wss.on("connection", (ws, nodeReq) => {
|
|
627
|
+
const request = new NodeReqProxy(nodeReq);
|
|
628
|
+
const peer = new NodePeer({ ws, request, peers, nodeReq });
|
|
629
|
+
peers.add(peer);
|
|
630
|
+
hooks.callHook("open", peer);
|
|
631
|
+
ws.on("message", (data) => {
|
|
627
632
|
if (Array.isArray(data)) {
|
|
628
633
|
data = Buffer.concat(data);
|
|
629
634
|
}
|
|
630
|
-
|
|
635
|
+
hooks.callHook("message", peer, new Message(data, peer));
|
|
631
636
|
});
|
|
632
637
|
ws.on("error", (error) => {
|
|
633
|
-
|
|
634
|
-
|
|
638
|
+
peers.delete(peer);
|
|
639
|
+
hooks.callHook("error", peer, new WSError(error));
|
|
635
640
|
});
|
|
636
641
|
ws.on("close", (code, reason) => {
|
|
637
|
-
|
|
638
|
-
|
|
642
|
+
peers.delete(peer);
|
|
643
|
+
hooks.callHook("close", peer, {
|
|
639
644
|
code,
|
|
640
645
|
reason: reason?.toString()
|
|
641
646
|
});
|
|
642
647
|
});
|
|
643
|
-
ws.on("open", () => {
|
|
644
|
-
crossws.$callHook("node:open", peer);
|
|
645
|
-
});
|
|
646
|
-
ws.on("ping", (data) => {
|
|
647
|
-
crossws.$callHook("node:ping", peer, data);
|
|
648
|
-
});
|
|
649
|
-
ws.on("pong", (data) => {
|
|
650
|
-
crossws.$callHook("node:pong", peer, data);
|
|
651
|
-
});
|
|
652
|
-
ws.on(
|
|
653
|
-
"unexpected-response",
|
|
654
|
-
(req2, res) => {
|
|
655
|
-
crossws.$callHook("node:unexpected-response", peer, req2, res);
|
|
656
|
-
}
|
|
657
|
-
);
|
|
658
|
-
ws.on("upgrade", (req2) => {
|
|
659
|
-
crossws.$callHook("node:upgrade", peer, req2);
|
|
660
|
-
});
|
|
661
648
|
});
|
|
662
|
-
wss.on("headers",
|
|
649
|
+
wss.on("headers", (outgoingHeaders, req) => {
|
|
663
650
|
const upgradeHeaders = req._upgradeHeaders;
|
|
664
651
|
if (upgradeHeaders) {
|
|
665
|
-
const
|
|
666
|
-
for (const [key, value] of _headers) {
|
|
652
|
+
for (const [key, value] of new Headers(upgradeHeaders)) {
|
|
667
653
|
outgoingHeaders.push(`${key}: ${value}`);
|
|
668
654
|
}
|
|
669
655
|
}
|
|
670
656
|
});
|
|
671
657
|
return {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
658
|
+
...adapterUtils(peers),
|
|
659
|
+
handleUpgrade: async (nodeReq, socket, head) => {
|
|
660
|
+
const request = new NodeReqProxy(nodeReq);
|
|
661
|
+
const res = await hooks.callHook("upgrade", request);
|
|
662
|
+
if (res instanceof Response) {
|
|
663
|
+
return sendResponse(socket, res);
|
|
664
|
+
}
|
|
665
|
+
nodeReq._request = request;
|
|
666
|
+
nodeReq._upgradeHeaders = res?.headers;
|
|
667
|
+
wss.handleUpgrade(nodeReq, socket, head, (ws) => {
|
|
668
|
+
wss.emit("connection", ws, nodeReq);
|
|
680
669
|
});
|
|
670
|
+
},
|
|
671
|
+
closeAll: (code, data) => {
|
|
672
|
+
for (const client of wss.clients) {
|
|
673
|
+
client.close(code, data);
|
|
674
|
+
}
|
|
681
675
|
}
|
|
682
676
|
};
|
|
683
677
|
}
|
|
684
678
|
);
|
|
685
679
|
class NodePeer extends Peer {
|
|
686
|
-
get
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
680
|
+
get remoteAddress() {
|
|
681
|
+
return this._internal.nodeReq.socket?.remoteAddress;
|
|
682
|
+
}
|
|
683
|
+
send(data, options) {
|
|
684
|
+
const dataBuff = toBufferLike(data);
|
|
685
|
+
const isBinary = typeof data !== "string";
|
|
686
|
+
this._internal.ws.send(dataBuff, {
|
|
687
|
+
compress: options?.compress,
|
|
688
|
+
binary: isBinary,
|
|
689
|
+
...options
|
|
690
|
+
});
|
|
691
|
+
return 0;
|
|
692
|
+
}
|
|
693
|
+
publish(topic, data, options) {
|
|
694
|
+
const dataBuff = toBufferLike(data);
|
|
695
|
+
const isBinary = typeof data !== "string";
|
|
696
|
+
const sendOptions = {
|
|
697
|
+
compress: options?.compress,
|
|
698
|
+
binary: isBinary,
|
|
699
|
+
...options
|
|
700
|
+
};
|
|
701
|
+
for (const peer of this._internal.peers) {
|
|
702
|
+
if (peer !== this && peer._topics.has(topic)) {
|
|
703
|
+
peer._internal.ws.send(dataBuff, sendOptions);
|
|
704
|
+
}
|
|
695
705
|
}
|
|
696
|
-
|
|
697
|
-
|
|
706
|
+
}
|
|
707
|
+
close(code, data) {
|
|
708
|
+
this._internal.ws.close(code, data);
|
|
709
|
+
}
|
|
710
|
+
terminate() {
|
|
711
|
+
this._internal.ws.terminate();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
class NodeReqProxy {
|
|
715
|
+
_req;
|
|
716
|
+
_headers;
|
|
717
|
+
_url;
|
|
718
|
+
constructor(req) {
|
|
719
|
+
this._req = req;
|
|
698
720
|
}
|
|
699
721
|
get url() {
|
|
700
|
-
|
|
722
|
+
if (!this._url) {
|
|
723
|
+
const req = this._req;
|
|
724
|
+
const host = req.headers["host"] || "localhost";
|
|
725
|
+
const isSecure = req.socket?.encrypted ?? req.headers["x-forwarded-proto"] === "https";
|
|
726
|
+
this._url = `${isSecure ? "https" : "http"}://${host}${req.url}`;
|
|
727
|
+
}
|
|
728
|
+
return this._url;
|
|
701
729
|
}
|
|
702
730
|
get headers() {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
return this.
|
|
731
|
+
if (!this._headers) {
|
|
732
|
+
this._headers = new Headers(this._req.headers);
|
|
733
|
+
}
|
|
734
|
+
return this._headers;
|
|
707
735
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
736
|
+
}
|
|
737
|
+
async function sendResponse(socket, res) {
|
|
738
|
+
const head = [
|
|
739
|
+
`HTTP/1.1 ${res.status || 200} ${res.statusText || ""}`,
|
|
740
|
+
...[...res.headers.entries()].map(
|
|
741
|
+
([key, value]) => `${encodeURIComponent(key)}: ${encodeURIComponent(value)}`
|
|
742
|
+
)
|
|
743
|
+
];
|
|
744
|
+
socket.write(head.join("\r\n") + "\r\n\r\n");
|
|
745
|
+
if (res.body) {
|
|
746
|
+
for await (const chunk of res.body) {
|
|
747
|
+
socket.write(chunk);
|
|
748
|
+
}
|
|
715
749
|
}
|
|
750
|
+
return new Promise((resolve) => {
|
|
751
|
+
socket.end(resolve);
|
|
752
|
+
});
|
|
716
753
|
}
|
|
717
754
|
|
|
718
755
|
export { node as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.mjs';
|
|
2
|
+
import '../shared/crossws.ChIJSJVK.mjs';
|
|
3
|
+
|
|
4
|
+
interface SSEAdapter extends AdapterInstance {
|
|
5
|
+
fetch(req: Request): Promise<Response>;
|
|
6
|
+
}
|
|
7
|
+
interface SSEOptions extends AdapterOptions {
|
|
8
|
+
bidir?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: Adapter<SSEAdapter, SSEOptions>;
|
|
11
|
+
|
|
12
|
+
export { type SSEAdapter, type SSEOptions, _default as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.js';
|
|
2
|
+
import '../shared/crossws.ChIJSJVK.js';
|
|
3
|
+
|
|
4
|
+
interface SSEAdapter extends AdapterInstance {
|
|
5
|
+
fetch(req: Request): Promise<Response>;
|
|
6
|
+
}
|
|
7
|
+
interface SSEOptions extends AdapterOptions {
|
|
8
|
+
bidir?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: Adapter<SSEAdapter, SSEOptions>;
|
|
11
|
+
|
|
12
|
+
export { type SSEAdapter, type SSEOptions, _default as default };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { M as Message, P as Peer, a as toString } from '../shared/crossws.DTY7a69w.mjs';
|
|
2
|
+
import { d as defineWebSocketAdapter, a as adapterUtils, A as AdapterHookable } from '../shared/crossws.B4sHId41.mjs';
|
|
3
|
+
import 'uncrypto';
|
|
4
|
+
|
|
5
|
+
const sse = defineWebSocketAdapter((opts = {}) => {
|
|
6
|
+
const hooks = new AdapterHookable(opts);
|
|
7
|
+
const peers = /* @__PURE__ */ new Set();
|
|
8
|
+
const peersMap = opts.bidir ? /* @__PURE__ */ new Map() : void 0;
|
|
9
|
+
return {
|
|
10
|
+
...adapterUtils(peers),
|
|
11
|
+
fetch: async (request) => {
|
|
12
|
+
const _res = await hooks.callHook("upgrade", request);
|
|
13
|
+
if (_res instanceof Response) {
|
|
14
|
+
return _res;
|
|
15
|
+
}
|
|
16
|
+
let peer;
|
|
17
|
+
if (opts.bidir && request.body && request.headers.has("x-crossws-id")) {
|
|
18
|
+
const id = request.headers.get("x-crossws-id");
|
|
19
|
+
peer = peersMap?.get(id);
|
|
20
|
+
if (!peer) {
|
|
21
|
+
return new Response("invalid peer id", { status: 400 });
|
|
22
|
+
}
|
|
23
|
+
const stream = request.body.pipeThrough(new TextDecoderStream());
|
|
24
|
+
try {
|
|
25
|
+
for await (const chunk of stream) {
|
|
26
|
+
hooks.callHook("message", peer, new Message(chunk, peer));
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
await stream.cancel().catch(() => {
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return new Response(null, {});
|
|
33
|
+
} else {
|
|
34
|
+
const ws = new SSEWebSocketStub();
|
|
35
|
+
peer = new SSEPeer({
|
|
36
|
+
peers,
|
|
37
|
+
peersMap,
|
|
38
|
+
request,
|
|
39
|
+
hooks,
|
|
40
|
+
ws
|
|
41
|
+
});
|
|
42
|
+
peers.add(peer);
|
|
43
|
+
if (opts.bidir) {
|
|
44
|
+
peersMap.set(peer.id, peer);
|
|
45
|
+
peer._sendEvent("crossws-id", peer.id);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
let headers = {
|
|
49
|
+
"Content-Type": "text/event-stream",
|
|
50
|
+
"Cache-Control": "no-cache",
|
|
51
|
+
Connection: "keep-alive"
|
|
52
|
+
};
|
|
53
|
+
if (opts.bidir) {
|
|
54
|
+
headers["x-crossws-id"] = peer.id;
|
|
55
|
+
}
|
|
56
|
+
if (_res?.headers) {
|
|
57
|
+
headers = new Headers(headers);
|
|
58
|
+
for (const [key, value] of new Headers(_res.headers)) {
|
|
59
|
+
headers.set(key, value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return new Response(peer._sseStream, { ..._res, headers });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
class SSEPeer extends Peer {
|
|
67
|
+
_sseStream;
|
|
68
|
+
// server -> client
|
|
69
|
+
_sseStreamController;
|
|
70
|
+
constructor(_internal) {
|
|
71
|
+
super(_internal);
|
|
72
|
+
_internal.ws.readyState = 0;
|
|
73
|
+
this._sseStream = new ReadableStream({
|
|
74
|
+
start: (controller) => {
|
|
75
|
+
_internal.ws.readyState = 1;
|
|
76
|
+
this._sseStreamController = controller;
|
|
77
|
+
_internal.hooks.callHook("open", this);
|
|
78
|
+
},
|
|
79
|
+
cancel: () => {
|
|
80
|
+
_internal.ws.readyState = 2;
|
|
81
|
+
_internal.peers.delete(this);
|
|
82
|
+
_internal.peersMap?.delete(this.id);
|
|
83
|
+
Promise.resolve(this._internal.hooks.callHook("close", this)).finally(
|
|
84
|
+
() => {
|
|
85
|
+
_internal.ws.readyState = 3;
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}).pipeThrough(new TextEncoderStream());
|
|
90
|
+
}
|
|
91
|
+
_sendEvent(event, data) {
|
|
92
|
+
const lines = data.split("\n");
|
|
93
|
+
this._sseStreamController?.enqueue(
|
|
94
|
+
`event: ${event}
|
|
95
|
+
${lines.map((l) => `data: ${l}`)}
|
|
96
|
+
|
|
97
|
+
`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
send(data) {
|
|
101
|
+
this._sendEvent("message", toString(data));
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
publish(topic, data) {
|
|
105
|
+
const dataBuff = toString(data);
|
|
106
|
+
for (const peer of this._internal.peers) {
|
|
107
|
+
if (peer !== this && peer._topics.has(topic)) {
|
|
108
|
+
peer._sendEvent("message", dataBuff);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
close() {
|
|
113
|
+
this._sseStreamController?.close();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
class SSEWebSocketStub {
|
|
117
|
+
readyState;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { sse as default };
|
package/dist/adapters/uws.d.mts
CHANGED
|
@@ -1,19 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter, Peer } from '../index.mjs';
|
|
2
|
+
import { W as WebSocket } from '../shared/crossws.ChIJSJVK.mjs';
|
|
3
|
+
import uws from 'uWebSockets.js';
|
|
3
4
|
|
|
4
5
|
type UserData = {
|
|
5
|
-
|
|
6
|
-
req: HttpRequest;
|
|
7
|
-
res: HttpResponse;
|
|
8
|
-
|
|
6
|
+
peer?: UWSPeer;
|
|
7
|
+
req: uws.HttpRequest;
|
|
8
|
+
res: uws.HttpResponse;
|
|
9
|
+
protocol: string;
|
|
10
|
+
extensions: string;
|
|
9
11
|
};
|
|
10
|
-
type WebSocketHandler = WebSocketBehavior<UserData>;
|
|
11
|
-
interface UWSAdapter {
|
|
12
|
+
type WebSocketHandler = uws.WebSocketBehavior<UserData>;
|
|
13
|
+
interface UWSAdapter extends AdapterInstance {
|
|
12
14
|
websocket: WebSocketHandler;
|
|
13
15
|
}
|
|
14
16
|
interface UWSOptions extends AdapterOptions {
|
|
15
|
-
uws?: Exclude<WebSocketBehavior<any>, "close" | "drain" | "message" | "open" | "ping" | "pong" | "subscription" | "upgrade">;
|
|
17
|
+
uws?: Exclude<uws.WebSocketBehavior<any>, "close" | "drain" | "message" | "open" | "ping" | "pong" | "subscription" | "upgrade">;
|
|
16
18
|
}
|
|
17
19
|
declare const _default: Adapter<UWSAdapter, UWSOptions>;
|
|
18
20
|
|
|
21
|
+
declare class UWSPeer extends Peer<{
|
|
22
|
+
peers: Set<UWSPeer>;
|
|
23
|
+
request: UWSReqProxy;
|
|
24
|
+
uws: uws.WebSocket<UserData>;
|
|
25
|
+
ws: UwsWebSocketProxy;
|
|
26
|
+
uwsData: UserData;
|
|
27
|
+
}> {
|
|
28
|
+
get remoteAddress(): string | undefined;
|
|
29
|
+
send(data: unknown, options?: {
|
|
30
|
+
compress?: boolean;
|
|
31
|
+
}): number;
|
|
32
|
+
subscribe(topic: string): void;
|
|
33
|
+
publish(topic: string, message: string, options?: {
|
|
34
|
+
compress?: boolean;
|
|
35
|
+
}): number;
|
|
36
|
+
close(code?: number, reason?: uws.RecognizedString): void;
|
|
37
|
+
terminate(): void;
|
|
38
|
+
}
|
|
39
|
+
declare class UWSReqProxy {
|
|
40
|
+
private _headers?;
|
|
41
|
+
private _rawHeaders;
|
|
42
|
+
url: string;
|
|
43
|
+
constructor(_req: uws.HttpRequest);
|
|
44
|
+
get headers(): Headers;
|
|
45
|
+
}
|
|
46
|
+
declare class UwsWebSocketProxy implements Partial<WebSocket> {
|
|
47
|
+
private _uws;
|
|
48
|
+
readyState?: number;
|
|
49
|
+
constructor(_uws: uws.WebSocket<UserData>);
|
|
50
|
+
get bufferedAmount(): number;
|
|
51
|
+
get protocol(): string;
|
|
52
|
+
get extensions(): string;
|
|
53
|
+
}
|
|
54
|
+
|
|
19
55
|
export { type UWSAdapter, type UWSOptions, _default as default };
|