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/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# crossws
|
|
2
2
|
|
|
3
3
|
<!-- automd:badges -->
|
|
4
4
|
|
|
@@ -7,24 +7,23 @@
|
|
|
7
7
|
|
|
8
8
|
<!-- /automd -->
|
|
9
9
|
|
|
10
|
-
Elegant, typed, and simple
|
|
10
|
+
Elegant, typed, and simple toolkit to implement cross-platform WebSocket servers.
|
|
11
11
|
|
|
12
12
|
👉 [📖 documentation](https://crossws.unjs.io)
|
|
13
13
|
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
|
-
🧩 Seamlessly integrates with
|
|
16
|
+
🧩 Seamlessly integrates with [Bun](https://crossws.unjs.io/adapters/bun), [Cloudflare Workers](https://crossws.unjs.io/adapters/cloudflare), [Deno](https://crossws.unjs.io/adapters/deno) and [Node.js](https://crossws.unjs.io/adapters/node) and any compatible web framework.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
✅ Prebundled with [ws](https://github.com/websockets/ws) for Node.js support with alternative/much faster [uWebSockets](https://crossws.unjs.io/adapters/node#uwebsockets) adapter.
|
|
19
19
|
|
|
20
|
-
📦
|
|
20
|
+
📦 Extremely lightweight and tree-shakable conditional ESM exports.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
🚀 High-performance and simple hooks API, without per-connection callback creation.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
🌟 Typed hooks API and developer-friendly object inspection.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
> This project and API are under development.
|
|
26
|
+
[^1]: crossws supports Node.js via [npm:ws](https://github.com/websockets/ws) (prebundled) or [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js).
|
|
28
27
|
|
|
29
28
|
## Contribution
|
|
30
29
|
|
package/dist/adapters/bun.d.mts
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { WebSocketHandler, Server } from 'bun';
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter, Peer } from '../index.mjs';
|
|
2
|
+
import { WebSocketHandler, Server, ServerWebSocket } from 'bun';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.mjs';
|
|
3
4
|
|
|
4
|
-
interface BunAdapter {
|
|
5
|
+
interface BunAdapter extends AdapterInstance {
|
|
5
6
|
websocket: WebSocketHandler<ContextData>;
|
|
6
|
-
handleUpgrade(req: Request, server: Server): Promise<
|
|
7
|
+
handleUpgrade(req: Request, server: Server): Promise<Response | undefined>;
|
|
7
8
|
}
|
|
8
9
|
interface BunOptions extends AdapterOptions {
|
|
9
10
|
}
|
|
10
11
|
type ContextData = {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
peer?: BunPeer;
|
|
13
|
+
request: Request;
|
|
13
14
|
server?: Server;
|
|
14
15
|
};
|
|
15
16
|
declare const _default: Adapter<BunAdapter, BunOptions>;
|
|
16
17
|
|
|
18
|
+
declare class BunPeer extends Peer<{
|
|
19
|
+
ws: ServerWebSocket<ContextData>;
|
|
20
|
+
request: Request;
|
|
21
|
+
peers: Set<BunPeer>;
|
|
22
|
+
}> {
|
|
23
|
+
get remoteAddress(): string;
|
|
24
|
+
send(data: unknown, options?: {
|
|
25
|
+
compress?: boolean;
|
|
26
|
+
}): number;
|
|
27
|
+
publish(topic: string, data: unknown, options?: {
|
|
28
|
+
compress?: boolean;
|
|
29
|
+
}): number;
|
|
30
|
+
subscribe(topic: string): void;
|
|
31
|
+
unsubscribe(topic: string): void;
|
|
32
|
+
close(code?: number, reason?: string): void;
|
|
33
|
+
terminate(): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
17
36
|
export { type BunAdapter, type BunOptions, _default as default };
|
package/dist/adapters/bun.d.ts
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { WebSocketHandler, Server } from 'bun';
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter, Peer } from '../index.js';
|
|
2
|
+
import { WebSocketHandler, Server, ServerWebSocket } from 'bun';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.js';
|
|
3
4
|
|
|
4
|
-
interface BunAdapter {
|
|
5
|
+
interface BunAdapter extends AdapterInstance {
|
|
5
6
|
websocket: WebSocketHandler<ContextData>;
|
|
6
|
-
handleUpgrade(req: Request, server: Server): Promise<
|
|
7
|
+
handleUpgrade(req: Request, server: Server): Promise<Response | undefined>;
|
|
7
8
|
}
|
|
8
9
|
interface BunOptions extends AdapterOptions {
|
|
9
10
|
}
|
|
10
11
|
type ContextData = {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
peer?: BunPeer;
|
|
13
|
+
request: Request;
|
|
13
14
|
server?: Server;
|
|
14
15
|
};
|
|
15
16
|
declare const _default: Adapter<BunAdapter, BunOptions>;
|
|
16
17
|
|
|
18
|
+
declare class BunPeer extends Peer<{
|
|
19
|
+
ws: ServerWebSocket<ContextData>;
|
|
20
|
+
request: Request;
|
|
21
|
+
peers: Set<BunPeer>;
|
|
22
|
+
}> {
|
|
23
|
+
get remoteAddress(): string;
|
|
24
|
+
send(data: unknown, options?: {
|
|
25
|
+
compress?: boolean;
|
|
26
|
+
}): number;
|
|
27
|
+
publish(topic: string, data: unknown, options?: {
|
|
28
|
+
compress?: boolean;
|
|
29
|
+
}): number;
|
|
30
|
+
subscribe(topic: string): void;
|
|
31
|
+
unsubscribe(topic: string): void;
|
|
32
|
+
close(code?: number, reason?: string): void;
|
|
33
|
+
terminate(): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
17
36
|
export { type BunAdapter, type BunOptions, _default as default };
|
package/dist/adapters/bun.mjs
CHANGED
|
@@ -1,92 +1,84 @@
|
|
|
1
|
-
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 'uncrypto';
|
|
2
4
|
|
|
3
5
|
const bun = defineWebSocketAdapter(
|
|
4
6
|
(options = {}) => {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
if (ws.data?._peer) {
|
|
8
|
-
return ws.data._peer;
|
|
9
|
-
}
|
|
10
|
-
const peer = new BunPeer({ bun: { ws } });
|
|
11
|
-
ws.data = ws.data || {};
|
|
12
|
-
ws.data._peer = peer;
|
|
13
|
-
return peer;
|
|
14
|
-
};
|
|
7
|
+
const hooks = new AdapterHookable(options);
|
|
8
|
+
const peers = /* @__PURE__ */ new Set();
|
|
15
9
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
...adapterUtils(peers),
|
|
11
|
+
async handleUpgrade(request, server) {
|
|
12
|
+
const res = await hooks.callHook("upgrade", request);
|
|
13
|
+
if (res instanceof Response) {
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
const upgradeOK = server.upgrade(request, {
|
|
17
|
+
data: {
|
|
18
|
+
server,
|
|
19
|
+
request
|
|
20
|
+
},
|
|
21
|
+
headers: res?.headers
|
|
24
22
|
});
|
|
23
|
+
if (!upgradeOK) {
|
|
24
|
+
return new Response("Upgrade failed", { status: 500 });
|
|
25
|
+
}
|
|
25
26
|
},
|
|
26
27
|
websocket: {
|
|
27
28
|
message: (ws, message) => {
|
|
28
|
-
const peer = getPeer(ws);
|
|
29
|
-
|
|
30
|
-
crossws.callHook("message", peer, new Message(message));
|
|
29
|
+
const peer = getPeer(ws, peers);
|
|
30
|
+
hooks.callHook("message", peer, new Message(message, peer));
|
|
31
31
|
},
|
|
32
32
|
open: (ws) => {
|
|
33
|
-
const peer = getPeer(ws);
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const peer = getPeer(ws, peers);
|
|
34
|
+
peers.add(peer);
|
|
35
|
+
hooks.callHook("open", peer);
|
|
36
36
|
},
|
|
37
37
|
close: (ws) => {
|
|
38
|
-
const peer = getPeer(ws);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
42
|
-
drain: (ws) => {
|
|
43
|
-
const peer = getPeer(ws);
|
|
44
|
-
crossws.$callHook("bun:drain", peer);
|
|
45
|
-
},
|
|
46
|
-
ping(ws, data) {
|
|
47
|
-
const peer = getPeer(ws);
|
|
48
|
-
crossws.$callHook("bun:ping", peer, ws, data);
|
|
49
|
-
},
|
|
50
|
-
pong(ws, data) {
|
|
51
|
-
const peer = getPeer(ws);
|
|
52
|
-
crossws.$callHook("bun:pong", peer, ws, data);
|
|
38
|
+
const peer = getPeer(ws, peers);
|
|
39
|
+
peers.delete(peer);
|
|
40
|
+
hooks.callHook("close", peer, {});
|
|
53
41
|
}
|
|
54
42
|
}
|
|
55
43
|
};
|
|
56
44
|
}
|
|
57
45
|
);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (addr.includes(":")) {
|
|
62
|
-
addr = `[${addr}]`;
|
|
63
|
-
}
|
|
64
|
-
return addr;
|
|
65
|
-
}
|
|
66
|
-
get readyState() {
|
|
67
|
-
return this.ctx.bun.ws.readyState;
|
|
46
|
+
function getPeer(ws, peers) {
|
|
47
|
+
if (ws.data?.peer) {
|
|
48
|
+
return ws.data.peer;
|
|
68
49
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
50
|
+
const peer = new BunPeer({ ws, request: ws.data.request, peers });
|
|
51
|
+
ws.data = {
|
|
52
|
+
...ws.data,
|
|
53
|
+
peer
|
|
54
|
+
};
|
|
55
|
+
return peer;
|
|
56
|
+
}
|
|
57
|
+
class BunPeer extends Peer {
|
|
58
|
+
get remoteAddress() {
|
|
59
|
+
return this._internal.ws.remoteAddress;
|
|
74
60
|
}
|
|
75
|
-
send(
|
|
76
|
-
return this.
|
|
61
|
+
send(data, options) {
|
|
62
|
+
return this._internal.ws.send(toBufferLike(data), options?.compress);
|
|
77
63
|
}
|
|
78
|
-
publish(topic,
|
|
79
|
-
return this.
|
|
64
|
+
publish(topic, data, options) {
|
|
65
|
+
return this._internal.ws.publish(
|
|
80
66
|
topic,
|
|
81
|
-
toBufferLike(
|
|
67
|
+
toBufferLike(data),
|
|
82
68
|
options?.compress
|
|
83
69
|
);
|
|
84
70
|
}
|
|
85
71
|
subscribe(topic) {
|
|
86
|
-
this.
|
|
72
|
+
this._internal.ws.subscribe(topic);
|
|
87
73
|
}
|
|
88
74
|
unsubscribe(topic) {
|
|
89
|
-
this.
|
|
75
|
+
this._internal.ws.unsubscribe(topic);
|
|
76
|
+
}
|
|
77
|
+
close(code, reason) {
|
|
78
|
+
this._internal.ws.close(code, reason);
|
|
79
|
+
}
|
|
80
|
+
terminate() {
|
|
81
|
+
this._internal.ws.terminate();
|
|
90
82
|
}
|
|
91
83
|
}
|
|
92
84
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Adapter, AdapterInstance, AdapterOptions } from '../index.mjs';
|
|
2
|
+
import { W as WebSocket$1 } from '../shared/crossws.ChIJSJVK.mjs';
|
|
3
|
+
import * as CF from '@cloudflare/workers-types';
|
|
4
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
5
|
+
|
|
6
|
+
declare const _default: Adapter<CloudflareDurableAdapter, CloudflareOptions>;
|
|
7
|
+
|
|
8
|
+
interface CloudflareDurableAdapter extends AdapterInstance {
|
|
9
|
+
handleUpgrade(req: Request | CF.Request, env: unknown, context: CF.ExecutionContext): Promise<Response>;
|
|
10
|
+
handleDurableInit(obj: DurableObject, state: DurableObjectState, env: unknown): void;
|
|
11
|
+
handleDurableUpgrade(obj: DurableObject, req: Request | CF.Request): Promise<Response>;
|
|
12
|
+
handleDurableMessage(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, message: ArrayBuffer | string): Promise<void>;
|
|
13
|
+
handleDurableClose(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, code: number, reason: string, wasClean: boolean): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
interface CloudflareOptions extends AdapterOptions {
|
|
16
|
+
bindingName?: string;
|
|
17
|
+
instanceName?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { type CloudflareDurableAdapter, type CloudflareOptions, _default as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Adapter, AdapterInstance, AdapterOptions } from '../index.js';
|
|
2
|
+
import { W as WebSocket$1 } from '../shared/crossws.ChIJSJVK.js';
|
|
3
|
+
import * as CF from '@cloudflare/workers-types';
|
|
4
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
5
|
+
|
|
6
|
+
declare const _default: Adapter<CloudflareDurableAdapter, CloudflareOptions>;
|
|
7
|
+
|
|
8
|
+
interface CloudflareDurableAdapter extends AdapterInstance {
|
|
9
|
+
handleUpgrade(req: Request | CF.Request, env: unknown, context: CF.ExecutionContext): Promise<Response>;
|
|
10
|
+
handleDurableInit(obj: DurableObject, state: DurableObjectState, env: unknown): void;
|
|
11
|
+
handleDurableUpgrade(obj: DurableObject, req: Request | CF.Request): Promise<Response>;
|
|
12
|
+
handleDurableMessage(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, message: ArrayBuffer | string): Promise<void>;
|
|
13
|
+
handleDurableClose(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, code: number, reason: string, wasClean: boolean): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
interface CloudflareOptions extends AdapterOptions {
|
|
16
|
+
bindingName?: string;
|
|
17
|
+
instanceName?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { type CloudflareDurableAdapter, type CloudflareOptions, _default as default };
|
|
@@ -0,0 +1,132 @@
|
|
|
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 'uncrypto';
|
|
4
|
+
|
|
5
|
+
const cloudflareDurable = defineWebSocketAdapter((opts) => {
|
|
6
|
+
const hooks = new AdapterHookable(opts);
|
|
7
|
+
const peers = /* @__PURE__ */ new Set();
|
|
8
|
+
return {
|
|
9
|
+
...adapterUtils(peers),
|
|
10
|
+
handleUpgrade: async (req, env, _context) => {
|
|
11
|
+
const bindingName = opts?.bindingName ?? "$DurableObject";
|
|
12
|
+
const instanceName = opts?.instanceName ?? "crossws";
|
|
13
|
+
const binding = env[bindingName];
|
|
14
|
+
const id = binding.idFromName(instanceName);
|
|
15
|
+
const stub = binding.get(id);
|
|
16
|
+
return stub.fetch(req);
|
|
17
|
+
},
|
|
18
|
+
handleDurableInit: async (obj, state, env) => {
|
|
19
|
+
},
|
|
20
|
+
handleDurableUpgrade: async (obj, request) => {
|
|
21
|
+
const res = await hooks.callHook("upgrade", request);
|
|
22
|
+
if (res instanceof Response) {
|
|
23
|
+
return res;
|
|
24
|
+
}
|
|
25
|
+
const pair = new WebSocketPair();
|
|
26
|
+
const client = pair[0];
|
|
27
|
+
const server = pair[1];
|
|
28
|
+
const peer = CloudflareDurablePeer._restore(
|
|
29
|
+
obj,
|
|
30
|
+
server,
|
|
31
|
+
request
|
|
32
|
+
);
|
|
33
|
+
peers.add(peer);
|
|
34
|
+
obj.ctx.acceptWebSocket(server);
|
|
35
|
+
await hooks.callHook("open", peer);
|
|
36
|
+
return new Response(null, {
|
|
37
|
+
status: 101,
|
|
38
|
+
webSocket: client,
|
|
39
|
+
headers: res?.headers
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
handleDurableMessage: async (obj, ws, message) => {
|
|
43
|
+
const peer = CloudflareDurablePeer._restore(obj, ws);
|
|
44
|
+
await hooks.callHook("message", peer, new Message(message, peer));
|
|
45
|
+
},
|
|
46
|
+
handleDurableClose: async (obj, ws, code, reason, wasClean) => {
|
|
47
|
+
const peer = CloudflareDurablePeer._restore(obj, ws);
|
|
48
|
+
peers.delete(peer);
|
|
49
|
+
const details = { code, reason, wasClean };
|
|
50
|
+
await hooks.callHook("close", peer, details);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
class CloudflareDurablePeer extends Peer {
|
|
55
|
+
get peers() {
|
|
56
|
+
return new Set(
|
|
57
|
+
this.#getwebsockets().map(
|
|
58
|
+
(ws) => CloudflareDurablePeer._restore(this._internal.durable, ws)
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
#getwebsockets() {
|
|
63
|
+
return this._internal.durable.ctx.getWebSockets();
|
|
64
|
+
}
|
|
65
|
+
send(data) {
|
|
66
|
+
return this._internal.ws.send(toBufferLike(data));
|
|
67
|
+
}
|
|
68
|
+
subscribe(topic) {
|
|
69
|
+
super.subscribe(topic);
|
|
70
|
+
const state = getAttachedState(this._internal.ws);
|
|
71
|
+
if (!state.t) {
|
|
72
|
+
state.t = /* @__PURE__ */ new Set();
|
|
73
|
+
}
|
|
74
|
+
state.t.add(topic);
|
|
75
|
+
setAttachedState(this._internal.ws, state);
|
|
76
|
+
}
|
|
77
|
+
publish(topic, data) {
|
|
78
|
+
const websockets = this.#getwebsockets();
|
|
79
|
+
if (websockets.length < 2) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const dataBuff = toBufferLike(data);
|
|
83
|
+
for (const ws of websockets) {
|
|
84
|
+
if (ws === this._internal.ws) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const state = getAttachedState(ws);
|
|
88
|
+
if (state.t?.has(topic)) {
|
|
89
|
+
ws.send(dataBuff);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
close(code, reason) {
|
|
94
|
+
this._internal.ws.close(code, reason);
|
|
95
|
+
}
|
|
96
|
+
static _restore(durable, ws, request) {
|
|
97
|
+
let peer = ws._crosswsPeer;
|
|
98
|
+
if (peer) {
|
|
99
|
+
return peer;
|
|
100
|
+
}
|
|
101
|
+
const state = ws.deserializeAttachment() || {};
|
|
102
|
+
peer = ws._crosswsPeer = new CloudflareDurablePeer({
|
|
103
|
+
ws,
|
|
104
|
+
request: request || { url: state.u },
|
|
105
|
+
durable
|
|
106
|
+
});
|
|
107
|
+
if (state.i) {
|
|
108
|
+
peer._id = state.i;
|
|
109
|
+
}
|
|
110
|
+
if (request?.url) {
|
|
111
|
+
state.u = request.url;
|
|
112
|
+
}
|
|
113
|
+
state.i = peer.id;
|
|
114
|
+
setAttachedState(ws, state);
|
|
115
|
+
return peer;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function getAttachedState(ws) {
|
|
119
|
+
let state = ws._crosswsState;
|
|
120
|
+
if (state) {
|
|
121
|
+
return state;
|
|
122
|
+
}
|
|
123
|
+
state = ws.deserializeAttachment() || {};
|
|
124
|
+
ws._crosswsState = state;
|
|
125
|
+
return state;
|
|
126
|
+
}
|
|
127
|
+
function setAttachedState(ws, state) {
|
|
128
|
+
ws._crosswsState = state;
|
|
129
|
+
ws.serializeAttachment(state);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { cloudflareDurable as default };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.mjs';
|
|
2
|
+
import * as CF from '@cloudflare/workers-types';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.mjs';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
handleUpgrade(req: _cf.Request, env: Env, context: _cf.ExecutionContext): Promise<_cf.Response>;
|
|
5
|
+
interface CloudflareAdapter extends AdapterInstance {
|
|
6
|
+
handleUpgrade(req: CF.Request, env: unknown, context: CF.ExecutionContext): Promise<CF.Response>;
|
|
7
7
|
}
|
|
8
8
|
interface CloudflareOptions extends AdapterOptions {
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.js';
|
|
2
|
+
import * as CF from '@cloudflare/workers-types';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.js';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
handleUpgrade(req: _cf.Request, env: Env, context: _cf.ExecutionContext): Promise<_cf.Response>;
|
|
5
|
+
interface CloudflareAdapter extends AdapterInstance {
|
|
6
|
+
handleUpgrade(req: CF.Request, env: unknown, context: CF.ExecutionContext): Promise<CF.Response>;
|
|
7
7
|
}
|
|
8
8
|
interface CloudflareOptions extends AdapterOptions {
|
|
9
9
|
}
|
|
@@ -1,62 +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 cloudflare = defineWebSocketAdapter(
|
|
5
7
|
(options = {}) => {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const pair = new WebSocketPair();
|
|
9
|
-
const client = pair[0];
|
|
10
|
-
const server = pair[1];
|
|
11
|
-
const peer = new CloudflarePeer({
|
|
12
|
-
cloudflare: { client, server, req, env, context }
|
|
13
|
-
});
|
|
14
|
-
const { headers } = await crossws.upgrade(peer);
|
|
15
|
-
server.accept();
|
|
16
|
-
crossws.$callHook("cloudflare:accept", peer);
|
|
17
|
-
crossws.callHook("open", peer);
|
|
18
|
-
server.addEventListener("message", (event) => {
|
|
19
|
-
crossws.$callHook("cloudflare:message", peer, event);
|
|
20
|
-
crossws.callHook("message", peer, new Message(event.data));
|
|
21
|
-
});
|
|
22
|
-
server.addEventListener("error", (event) => {
|
|
23
|
-
crossws.$callHook("cloudflare:error", peer, event);
|
|
24
|
-
crossws.callHook("error", peer, new WSError(event.error));
|
|
25
|
-
});
|
|
26
|
-
server.addEventListener("close", (event) => {
|
|
27
|
-
crossws.$callHook("cloudflare:close", peer, event);
|
|
28
|
-
crossws.callHook("close", peer, {
|
|
29
|
-
code: event.code,
|
|
30
|
-
reason: event.reason
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
return new Response(null, {
|
|
34
|
-
status: 101,
|
|
35
|
-
webSocket: client,
|
|
36
|
-
headers
|
|
37
|
-
});
|
|
38
|
-
};
|
|
8
|
+
const hooks = new AdapterHookable(options);
|
|
9
|
+
const peers = /* @__PURE__ */ new Set();
|
|
39
10
|
return {
|
|
40
|
-
|
|
11
|
+
...adapterUtils(peers),
|
|
12
|
+
handleUpgrade: async (request, env, context) => {
|
|
13
|
+
const res = await hooks.callHook(
|
|
14
|
+
"upgrade",
|
|
15
|
+
request
|
|
16
|
+
);
|
|
17
|
+
if (res instanceof Response) {
|
|
18
|
+
return res;
|
|
19
|
+
}
|
|
20
|
+
const pair = new WebSocketPair();
|
|
21
|
+
const client = pair[0];
|
|
22
|
+
const server = pair[1];
|
|
23
|
+
const peer = new CloudflarePeer({
|
|
24
|
+
ws: client,
|
|
25
|
+
peers,
|
|
26
|
+
wsServer: server,
|
|
27
|
+
request,
|
|
28
|
+
cfEnv: env,
|
|
29
|
+
cfCtx: context
|
|
30
|
+
});
|
|
31
|
+
peers.add(peer);
|
|
32
|
+
server.accept();
|
|
33
|
+
hooks.callHook("open", peer);
|
|
34
|
+
server.addEventListener("message", (event) => {
|
|
35
|
+
hooks.callHook(
|
|
36
|
+
"message",
|
|
37
|
+
peer,
|
|
38
|
+
new Message(event.data, peer, event)
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
server.addEventListener("error", (event) => {
|
|
42
|
+
peers.delete(peer);
|
|
43
|
+
hooks.callHook("error", peer, new WSError(event.error));
|
|
44
|
+
});
|
|
45
|
+
server.addEventListener("close", (event) => {
|
|
46
|
+
peers.delete(peer);
|
|
47
|
+
hooks.callHook("close", peer, event);
|
|
48
|
+
});
|
|
49
|
+
return new Response(null, {
|
|
50
|
+
status: 101,
|
|
51
|
+
webSocket: client,
|
|
52
|
+
headers: res?.headers
|
|
53
|
+
});
|
|
54
|
+
}
|
|
41
55
|
};
|
|
42
56
|
}
|
|
43
57
|
);
|
|
44
58
|
class CloudflarePeer extends Peer {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
get url() {
|
|
49
|
-
return this.ctx.cloudflare.req.url;
|
|
50
|
-
}
|
|
51
|
-
get headers() {
|
|
52
|
-
return this.ctx.cloudflare.req.headers;
|
|
59
|
+
send(data) {
|
|
60
|
+
this._internal.wsServer.send(toBufferLike(data));
|
|
61
|
+
return 0;
|
|
53
62
|
}
|
|
54
|
-
|
|
55
|
-
return this.ctx.cloudflare.client.readyState;
|
|
63
|
+
publish(_topic, _message) {
|
|
56
64
|
}
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
return 0;
|
|
65
|
+
close(code, reason) {
|
|
66
|
+
this._internal.ws.close(code, reason);
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
|
package/dist/adapters/deno.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.mjs';
|
|
2
2
|
import * as _deno_types from '@deno/types';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.mjs';
|
|
3
4
|
|
|
4
|
-
interface DenoAdapter {
|
|
5
|
+
interface DenoAdapter extends AdapterInstance {
|
|
5
6
|
handleUpgrade(req: Request, info: ServeHandlerInfo): Promise<Response>;
|
|
6
7
|
}
|
|
7
8
|
interface DenoOptions extends AdapterOptions {
|
|
@@ -9,7 +10,13 @@ interface DenoOptions extends AdapterOptions {
|
|
|
9
10
|
declare global {
|
|
10
11
|
const Deno: typeof _deno_types.Deno;
|
|
11
12
|
}
|
|
12
|
-
type ServeHandlerInfo =
|
|
13
|
+
type ServeHandlerInfo = {
|
|
14
|
+
remoteAddr?: {
|
|
15
|
+
transport: string;
|
|
16
|
+
hostname: string;
|
|
17
|
+
port: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
13
20
|
declare const _default: Adapter<DenoAdapter, DenoOptions>;
|
|
14
21
|
|
|
15
22
|
export { type DenoAdapter, type DenoOptions, _default as default };
|
package/dist/adapters/deno.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdapterInstance, AdapterOptions, Adapter } from '../index.js';
|
|
2
2
|
import * as _deno_types from '@deno/types';
|
|
3
|
+
import '../shared/crossws.ChIJSJVK.js';
|
|
3
4
|
|
|
4
|
-
interface DenoAdapter {
|
|
5
|
+
interface DenoAdapter extends AdapterInstance {
|
|
5
6
|
handleUpgrade(req: Request, info: ServeHandlerInfo): Promise<Response>;
|
|
6
7
|
}
|
|
7
8
|
interface DenoOptions extends AdapterOptions {
|
|
@@ -9,7 +10,13 @@ interface DenoOptions extends AdapterOptions {
|
|
|
9
10
|
declare global {
|
|
10
11
|
const Deno: typeof _deno_types.Deno;
|
|
11
12
|
}
|
|
12
|
-
type ServeHandlerInfo =
|
|
13
|
+
type ServeHandlerInfo = {
|
|
14
|
+
remoteAddr?: {
|
|
15
|
+
transport: string;
|
|
16
|
+
hostname: string;
|
|
17
|
+
port: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
13
20
|
declare const _default: Adapter<DenoAdapter, DenoOptions>;
|
|
14
21
|
|
|
15
22
|
export { type DenoAdapter, type DenoOptions, _default as default };
|