crossws 0.3.5 → 0.4.1

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 (53) hide show
  1. package/adapters/bun.d.ts +2 -2
  2. package/adapters/cloudflare.d.ts +2 -2
  3. package/adapters/deno.d.ts +2 -2
  4. package/adapters/node.d.ts +2 -2
  5. package/adapters/sse.d.ts +2 -2
  6. package/adapters/uws.d.ts +2 -2
  7. package/dist/adapters/bun.d.mts +5 -3
  8. package/dist/adapters/bun.mjs +23 -13
  9. package/dist/adapters/cloudflare.d.mts +40 -7
  10. package/dist/adapters/cloudflare.mjs +172 -14
  11. package/dist/adapters/deno.mjs +18 -9
  12. package/dist/adapters/node.d.mts +1 -1
  13. package/dist/adapters/node.mjs +28 -29
  14. package/dist/adapters/sse.mjs +8 -7
  15. package/dist/adapters/uws.d.mts +12 -9
  16. package/dist/adapters/uws.mjs +25 -27
  17. package/dist/index.d.mts +33 -20
  18. package/dist/index.mjs +1 -1
  19. package/dist/server/bun.d.mts +24 -0
  20. package/dist/server/bun.mjs +37 -0
  21. package/dist/server/cloudflare.d.mts +24 -0
  22. package/dist/server/cloudflare.mjs +36 -0
  23. package/dist/server/default.d.mts +24 -0
  24. package/dist/server/default.mjs +32 -0
  25. package/dist/server/deno.d.mts +24 -0
  26. package/dist/server/deno.mjs +30 -0
  27. package/dist/server/node.d.mts +24 -0
  28. package/dist/server/node.mjs +49 -0
  29. package/dist/shared/crossws.95-eYp2D.d.mts +23 -0
  30. package/dist/shared/crossws.B31KJMcF.mjs +83 -0
  31. package/dist/shared/{crossws.D9ehKjSh.mjs → crossws.CPlNx7g8.mjs} +44 -25
  32. package/dist/shared/{crossws.DfCzGthR.mjs → crossws.WpyOHUXc.mjs} +18 -13
  33. package/package.json +42 -53
  34. package/server/bun.d.ts +2 -0
  35. package/server/deno.d.ts +2 -0
  36. package/server/node.d.ts +2 -0
  37. package/server.d.ts +2 -0
  38. package/websocket/sse.d.ts +2 -0
  39. package/websocket.d.ts +2 -2
  40. package/dist/adapters/bun.d.ts +0 -39
  41. package/dist/adapters/cloudflare-durable.d.mts +0 -42
  42. package/dist/adapters/cloudflare-durable.d.ts +0 -42
  43. package/dist/adapters/cloudflare-durable.mjs +0 -141
  44. package/dist/adapters/cloudflare.d.ts +0 -13
  45. package/dist/adapters/deno.d.ts +0 -19
  46. package/dist/adapters/node.d.ts +0 -299
  47. package/dist/adapters/sse.d.ts +0 -13
  48. package/dist/adapters/uws.d.ts +0 -59
  49. package/dist/index.d.ts +0 -157
  50. package/dist/shared/crossws.BQXMA5bH.d.ts +0 -297
  51. package/dist/websocket/native.d.ts +0 -3
  52. package/dist/websocket/node.d.ts +0 -3
  53. package/dist/websocket/sse.d.ts +0 -42
@@ -6,7 +6,8 @@ class AdapterHookable {
6
6
  callHook(name, arg1, arg2) {
7
7
  const globalHook = this.options.hooks?.[name];
8
8
  const globalPromise = globalHook?.(arg1, arg2);
9
- const resolveHooksPromise = this.options.resolve?.(arg1);
9
+ const request = arg1.request || arg1;
10
+ const resolveHooksPromise = this.options.resolve?.(request);
10
11
  if (!resolveHooksPromise) {
11
12
  return globalPromise;
12
13
  }
@@ -19,28 +20,32 @@ class AdapterHookable {
19
20
  );
20
21
  }
21
22
  async upgrade(request) {
22
- let context = request.context;
23
- if (!context) {
24
- context = {};
25
- Object.defineProperty(request, "context", {
26
- enumerable: true,
27
- value: context
28
- });
29
- }
23
+ let namespace = this.options.getNamespace?.(request) ?? new URL(request.url).pathname;
24
+ const context = request.context || {};
30
25
  try {
31
26
  const res = await this.callHook(
32
27
  "upgrade",
33
28
  request
34
29
  );
35
30
  if (!res) {
36
- return { context };
31
+ return { context, namespace };
32
+ }
33
+ if (res.namespace) {
34
+ namespace = res.namespace;
37
35
  }
38
- if (res.ok === false) {
39
- return { context, endResponse: res };
36
+ if (res.context) {
37
+ Object.assign(
38
+ context,
39
+ res.context
40
+ );
41
+ }
42
+ if (res instanceof Response) {
43
+ return { context, namespace, endResponse: res };
40
44
  }
41
45
  if (res.headers) {
42
46
  return {
43
47
  context,
48
+ namespace,
44
49
  upgradeHeaders: res.headers
45
50
  };
46
51
  }
@@ -49,38 +54,52 @@ class AdapterHookable {
49
54
  if (errResponse instanceof Response) {
50
55
  return {
51
56
  context,
57
+ namespace,
52
58
  endResponse: errResponse
53
59
  };
54
60
  }
55
61
  throw error;
56
62
  }
57
- return { context };
63
+ return { context, namespace };
58
64
  }
59
65
  }
60
66
  function defineHooks(hooks) {
61
67
  return hooks;
62
68
  }
63
69
 
64
- function adapterUtils(peers) {
70
+ function adapterUtils(globalPeers) {
65
71
  return {
66
- peers,
72
+ peers: globalPeers,
67
73
  publish(topic, message, options) {
68
- let firstPeerWithTopic;
69
- for (const peer of peers) {
70
- if (peer.topics.has(topic)) {
71
- firstPeerWithTopic = peer;
72
- break;
74
+ for (const peers of options?.namespace ? [globalPeers.get(options.namespace) || []] : globalPeers.values()) {
75
+ let firstPeerWithTopic;
76
+ for (const peer of peers) {
77
+ if (peer.topics.has(topic)) {
78
+ firstPeerWithTopic = peer;
79
+ break;
80
+ }
81
+ }
82
+ if (firstPeerWithTopic) {
83
+ firstPeerWithTopic.send(message, options);
84
+ firstPeerWithTopic.publish(topic, message, options);
73
85
  }
74
- }
75
- if (firstPeerWithTopic) {
76
- firstPeerWithTopic.send(message, options);
77
- firstPeerWithTopic.publish(topic, message, options);
78
86
  }
79
87
  }
80
88
  };
81
89
  }
90
+ function getPeers(globalPeers, namespace) {
91
+ if (!namespace) {
92
+ throw new Error("Websocket publish namespace missing.");
93
+ }
94
+ let peers = globalPeers.get(namespace);
95
+ if (!peers) {
96
+ peers = /* @__PURE__ */ new Set();
97
+ globalPeers.set(namespace, peers);
98
+ }
99
+ return peers;
100
+ }
82
101
  function defineWebSocketAdapter(factory) {
83
102
  return factory;
84
103
  }
85
104
 
86
- export { AdapterHookable as A, adapterUtils as a, defineWebSocketAdapter as b, defineHooks as d };
105
+ export { AdapterHookable as A, adapterUtils as a, defineWebSocketAdapter as b, defineHooks as d, getPeers as g };
@@ -1,5 +1,3 @@
1
- import { randomUUID } from 'uncrypto';
2
-
3
1
  const kNodeInspect = /* @__PURE__ */ Symbol.for(
4
2
  "nodejs.util.inspect.custom"
5
3
  );
@@ -76,7 +74,7 @@ class Message {
76
74
  */
77
75
  get id() {
78
76
  if (!this.#id) {
79
- this.#id = randomUUID();
77
+ this.#id = crypto.randomUUID();
80
78
  }
81
79
  return this.#id;
82
80
  }
@@ -210,7 +208,13 @@ class Message {
210
208
  return this.text();
211
209
  }
212
210
  [kNodeInspect]() {
213
- return { data: this.rawData };
211
+ return {
212
+ message: {
213
+ id: this.id,
214
+ peer: this.peer,
215
+ text: this.text()
216
+ }
217
+ };
214
218
  }
215
219
  }
216
220
 
@@ -226,12 +230,15 @@ class Peer {
226
230
  get context() {
227
231
  return this._internal.context ??= {};
228
232
  }
233
+ get namespace() {
234
+ return this._internal.namespace;
235
+ }
229
236
  /**
230
237
  * Unique random [uuid v4](https://developer.mozilla.org/en-US/docs/Glossary/UUID) identifier for the peer.
231
238
  */
232
239
  get id() {
233
240
  if (!this._id) {
234
- this._id = randomUUID();
241
+ this._id = crypto.randomUUID();
235
242
  }
236
243
  return this._id;
237
244
  }
@@ -290,14 +297,12 @@ class Peer {
290
297
  return "WebSocket";
291
298
  }
292
299
  [kNodeInspect]() {
293
- return Object.fromEntries(
294
- [
295
- ["id", this.id],
296
- ["remoteAddress", this.remoteAddress],
297
- ["peers", this.peers],
298
- ["webSocket", this.websocket]
299
- ].filter((p) => p[1])
300
- );
300
+ return {
301
+ peer: {
302
+ id: this.id,
303
+ ip: this.remoteAddress
304
+ }
305
+ };
301
306
  }
302
307
  }
303
308
  function createWsProxy(ws, request) {
package/package.json CHANGED
@@ -1,47 +1,32 @@
1
1
  {
2
2
  "name": "crossws",
3
- "version": "0.3.5",
3
+ "version": "0.4.1",
4
4
  "description": "Cross-platform WebSocket Servers for Node.js, Deno, Bun and Cloudflare Workers",
5
- "repository": "h3js/crossws",
6
5
  "homepage": "https://crossws.h3.dev",
6
+ "repository": "h3js/crossws",
7
7
  "license": "MIT",
8
8
  "sideEffects": false,
9
9
  "type": "module",
10
10
  "exports": {
11
- ".": {
12
- "types": "./dist/index.d.mts",
13
- "default": "./dist/index.mjs"
14
- },
15
- "./adapters/bun": {
16
- "types": "./dist/adapters/bun.d.mts",
17
- "default": "./dist/adapters/bun.mjs"
18
- },
19
- "./adapters/deno": {
20
- "types": "./dist/adapters/deno.d.mts",
21
- "default": "./dist/adapters/deno.mjs"
22
- },
23
- "./adapters/cloudflare": {
24
- "types": "./dist/adapters/cloudflare.d.mts",
25
- "default": "./dist/adapters/cloudflare.mjs"
26
- },
27
- "./adapters/cloudflare-durable": {
28
- "types": "./dist/adapters/cloudflare-durable.d.mts",
29
- "default": "./dist/adapters/cloudflare-durable.mjs"
30
- },
31
- "./adapters/sse": {
32
- "types": "./dist/adapters/sse.d.mts",
33
- "default": "./dist/adapters/sse.mjs"
34
- },
35
- "./adapters/node": {
36
- "types": "./dist/adapters/node.d.mts",
37
- "default": "./dist/adapters/node.mjs"
38
- },
39
- "./adapters/uws": {
40
- "types": "./dist/adapters/uws.d.mts",
41
- "default": "./dist/adapters/uws.mjs"
11
+ ".": "./dist/index.mjs",
12
+ "./adapters/bun": "./dist/adapters/bun.mjs",
13
+ "./adapters/deno": "./dist/adapters/deno.mjs",
14
+ "./adapters/cloudflare": "./dist/adapters/cloudflare.mjs",
15
+ "./adapters/sse": "./dist/adapters/sse.mjs",
16
+ "./adapters/node": "./dist/adapters/node.mjs",
17
+ "./adapters/uws": "./dist/adapters/uws.mjs",
18
+ "./server/bun": "./dist/server/bun.mjs",
19
+ "./server/deno": "./dist/server/deno.mjs",
20
+ "./server/node": "./dist/server/node.mjs",
21
+ "./server": {
22
+ "deno": "./dist/server/deno.mjs",
23
+ "bun": "./dist/server/bun.mjs",
24
+ "workerd": "./dist/server/cloudflare.mjs",
25
+ "node": "./dist/server/node.mjs",
26
+ "default": "./dist/server/default.mjs"
42
27
  },
28
+ "./websocket/sse": "./dist/websocket/sse.mjs",
43
29
  "./websocket": {
44
- "types": "./dist/websocket/native.d.mts",
45
30
  "browser": "./dist/websocket/native.mjs",
46
31
  "worker": "./dist/websocket/native.mjs",
47
32
  "bun": "./dist/websocket/native.mjs",
@@ -50,10 +35,6 @@
50
35
  "workerd": "./dist/websocket/native.mjs",
51
36
  "node": "./dist/websocket/node.mjs",
52
37
  "default": "./dist/websocket/native.mjs"
53
- },
54
- "./websocket/sse": {
55
- "types": "./dist/websocket/sse.d.mts",
56
- "default": "./dist/websocket/sse.mjs"
57
38
  }
58
39
  },
59
40
  "main": "./dist/index.mjs",
@@ -62,6 +43,8 @@
62
43
  "files": [
63
44
  "dist",
64
45
  "adapters",
46
+ "websocket",
47
+ "server",
65
48
  "*.d.ts"
66
49
  ],
67
50
  "scripts": {
@@ -84,38 +67,44 @@
84
67
  "resolutions": {
85
68
  "crossws": "workspace:*"
86
69
  },
87
- "dependencies": {
88
- "uncrypto": "^0.1.3"
89
- },
90
70
  "devDependencies": {
91
- "@cloudflare/workers-types": "^4.20250506.0",
92
- "@types/bun": "^1.2.12",
71
+ "@cloudflare/workers-types": "^4.20250523.0",
72
+ "@types/bun": "^1.2.14",
93
73
  "@types/deno": "^2.3.0",
94
- "@types/node": "^22.15.14",
95
- "@types/web": "^0.0.232",
74
+ "@types/node": "^22.15.21",
75
+ "@types/web": "^0.0.235",
96
76
  "@types/ws": "^8.18.1",
97
- "@vitest/coverage-v8": "^3.1.3",
77
+ "@vitest/coverage-v8": "^3.1.4",
98
78
  "automd": "^0.4.0",
99
79
  "changelogen": "^0.6.1",
100
80
  "consola": "^3.4.2",
101
- "eslint": "^9.26.0",
81
+ "eslint": "^9.27.0",
102
82
  "eslint-config-unjs": "^0.4.2",
103
- "eventsource": "^3.0.6",
104
- "execa": "^9.5.2",
83
+ "eventsource": "^4.0.0",
84
+ "execa": "^9.5.3",
105
85
  "get-port-please": "^3.1.2",
106
86
  "h3": "^1.15.3",
107
87
  "jiti": "^2.4.2",
108
88
  "listhen": "^1.9.0",
109
89
  "prettier": "^3.5.3",
90
+ "srvx": "^0.7.1",
110
91
  "typescript": "^5.8.3",
111
92
  "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.44.0",
112
93
  "unbuild": "^3.5.0",
113
- "undici": "^7.8.0",
114
- "vitest": "^3.1.3",
115
- "wrangler": "^4.14.1",
94
+ "undici": "^7.10.0",
95
+ "vitest": "^3.1.4",
96
+ "wrangler": "^4.16.1",
116
97
  "ws": "^8.18.2"
117
98
  },
118
- "packageManager": "pnpm@10.10.0",
99
+ "peerDependencies": {
100
+ "srvx": ">=0.7.1"
101
+ },
102
+ "peerDependenciesMeta": {
103
+ "srvx": {
104
+ "optional": true
105
+ }
106
+ },
107
+ "packageManager": "pnpm@10.11.0",
119
108
  "pnpm": {
120
109
  "ignoredBuiltDependencies": [
121
110
  "@parcel/watcher",
@@ -0,0 +1,2 @@
1
+ export * from "../dist/server/bun.mjs";
2
+ export { default } from "../dist/server/bun.mjs";
@@ -0,0 +1,2 @@
1
+ export * from "../dist/server/deno.mjs";
2
+ export { default } from "../dist/server/deno.mjs";
@@ -0,0 +1,2 @@
1
+ export * from "../dist/server/node.mjs";
2
+ export { default } from "../dist/server/node.mjs";
package/server.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./dist/server/node.mjs";
2
+ export { default } from "./dist/server/node.mjs";
@@ -0,0 +1,2 @@
1
+ export * from "../dist/websocket/sse.mjs";
2
+ export { default } from "../dist/websocket/sse.mjs";
package/websocket.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./dist/websocket";
2
- export { default } from "./dist/websocket";
1
+ export * from "./dist/websocket/native.mjs";
2
+ export { default } from "./dist/websocket/native.mjs";
@@ -1,39 +0,0 @@
1
- import { WebSocketHandler, ServerWebSocket, Server } from 'bun';
2
- import { Adapter, AdapterInstance, Peer, AdapterOptions } from '../index.js';
3
- import '../shared/crossws.BQXMA5bH.js';
4
-
5
- interface BunAdapter extends AdapterInstance {
6
- websocket: WebSocketHandler<ContextData>;
7
- handleUpgrade(req: Request, server: Server): Promise<Response | undefined>;
8
- }
9
- interface BunOptions extends AdapterOptions {
10
- }
11
- type ContextData = {
12
- peer?: BunPeer;
13
- request: Request;
14
- server?: Server;
15
- context: Peer["context"];
16
- };
17
- declare const bunAdapter: Adapter<BunAdapter, BunOptions>;
18
-
19
- declare class BunPeer extends Peer<{
20
- ws: ServerWebSocket<ContextData>;
21
- request: Request;
22
- peers: Set<BunPeer>;
23
- }> {
24
- get remoteAddress(): string;
25
- get context(): Peer["context"];
26
- send(data: unknown, options?: {
27
- compress?: boolean;
28
- }): number;
29
- publish(topic: string, data: unknown, options?: {
30
- compress?: boolean;
31
- }): number;
32
- subscribe(topic: string): void;
33
- unsubscribe(topic: string): void;
34
- close(code?: number, reason?: string): void;
35
- terminate(): void;
36
- }
37
-
38
- export { bunAdapter as default };
39
- export type { BunAdapter, BunOptions };
@@ -1,42 +0,0 @@
1
- import * as CF from '@cloudflare/workers-types';
2
- import { DurableObject } from 'cloudflare:workers';
3
- import { Adapter, AdapterInstance, AdapterOptions } from '../index.mjs';
4
- import { W as WebSocket$1 } from '../shared/crossws.BQXMA5bH.mjs';
5
-
6
- type ResolveDurableStub = (req: CF.Request, env: unknown, context: CF.ExecutionContext) => CF.DurableObjectStub | Promise<CF.DurableObjectStub>;
7
- interface CloudflareOptions extends AdapterOptions {
8
- /**
9
- * Durable Object binding name from environment.
10
- *
11
- * **Note:** This option will be ignored if `resolveDurableStub` is provided.
12
- *
13
- * @default "$DurableObject"
14
- */
15
- bindingName?: string;
16
- /**
17
- * Durable Object instance name.
18
- *
19
- * **Note:** This option will be ignored if `resolveDurableStub` is provided.
20
- *
21
- * @default "crossws"
22
- */
23
- instanceName?: string;
24
- /**
25
- * Custom function that resolves Durable Object binding to handle the WebSocket upgrade.
26
- *
27
- * **Note:** This option will override `bindingName` and `instanceName`.
28
- */
29
- resolveDurableStub?: ResolveDurableStub;
30
- }
31
- declare const cloudflareDurableAdapter: Adapter<CloudflareDurableAdapter, CloudflareOptions>;
32
-
33
- interface CloudflareDurableAdapter extends AdapterInstance {
34
- handleUpgrade(req: Request | CF.Request, env: unknown, context: CF.ExecutionContext): Promise<Response>;
35
- handleDurableInit(obj: DurableObject, state: DurableObjectState, env: unknown): void;
36
- handleDurableUpgrade(obj: DurableObject, req: Request | CF.Request): Promise<Response>;
37
- handleDurableMessage(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, message: ArrayBuffer | string): Promise<void>;
38
- handleDurableClose(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, code: number, reason: string, wasClean: boolean): Promise<void>;
39
- }
40
-
41
- export { cloudflareDurableAdapter as default };
42
- export type { CloudflareDurableAdapter, CloudflareOptions };
@@ -1,42 +0,0 @@
1
- import * as CF from '@cloudflare/workers-types';
2
- import { DurableObject } from 'cloudflare:workers';
3
- import { Adapter, AdapterInstance, AdapterOptions } from '../index.js';
4
- import { W as WebSocket$1 } from '../shared/crossws.BQXMA5bH.js';
5
-
6
- type ResolveDurableStub = (req: CF.Request, env: unknown, context: CF.ExecutionContext) => CF.DurableObjectStub | Promise<CF.DurableObjectStub>;
7
- interface CloudflareOptions extends AdapterOptions {
8
- /**
9
- * Durable Object binding name from environment.
10
- *
11
- * **Note:** This option will be ignored if `resolveDurableStub` is provided.
12
- *
13
- * @default "$DurableObject"
14
- */
15
- bindingName?: string;
16
- /**
17
- * Durable Object instance name.
18
- *
19
- * **Note:** This option will be ignored if `resolveDurableStub` is provided.
20
- *
21
- * @default "crossws"
22
- */
23
- instanceName?: string;
24
- /**
25
- * Custom function that resolves Durable Object binding to handle the WebSocket upgrade.
26
- *
27
- * **Note:** This option will override `bindingName` and `instanceName`.
28
- */
29
- resolveDurableStub?: ResolveDurableStub;
30
- }
31
- declare const cloudflareDurableAdapter: Adapter<CloudflareDurableAdapter, CloudflareOptions>;
32
-
33
- interface CloudflareDurableAdapter extends AdapterInstance {
34
- handleUpgrade(req: Request | CF.Request, env: unknown, context: CF.ExecutionContext): Promise<Response>;
35
- handleDurableInit(obj: DurableObject, state: DurableObjectState, env: unknown): void;
36
- handleDurableUpgrade(obj: DurableObject, req: Request | CF.Request): Promise<Response>;
37
- handleDurableMessage(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, message: ArrayBuffer | string): Promise<void>;
38
- handleDurableClose(obj: DurableObject, ws: WebSocket | CF.WebSocket | WebSocket$1, code: number, reason: string, wasClean: boolean): Promise<void>;
39
- }
40
-
41
- export { cloudflareDurableAdapter as default };
42
- export type { CloudflareDurableAdapter, CloudflareOptions };
@@ -1,141 +0,0 @@
1
- import { M as Message, P as Peer, t as toBufferLike } from '../shared/crossws.DfCzGthR.mjs';
2
- import { a as adapterUtils, A as AdapterHookable } from '../shared/crossws.D9ehKjSh.mjs';
3
- import 'uncrypto';
4
-
5
- const cloudflareDurableAdapter = (opts = {}) => {
6
- const hooks = new AdapterHookable(opts);
7
- const peers = /* @__PURE__ */ new Set();
8
- const resolveDurableStub = opts.resolveDurableStub || ((_req, env, _context) => {
9
- const bindingName = opts.bindingName || "$DurableObject";
10
- const binding = env[bindingName];
11
- if (!binding) {
12
- throw new Error(
13
- `Durable Object binding "${bindingName}" not available`
14
- );
15
- }
16
- const instanceId = binding.idFromName(opts.instanceName || "crossws");
17
- return binding.get(instanceId);
18
- });
19
- return {
20
- ...adapterUtils(peers),
21
- handleUpgrade: async (req, env, context) => {
22
- const stub = await resolveDurableStub(req, env, context);
23
- return stub.fetch(req);
24
- },
25
- handleDurableInit: async (obj, state, env) => {
26
- },
27
- handleDurableUpgrade: async (obj, request) => {
28
- const { upgradeHeaders, endResponse } = await hooks.upgrade(
29
- request
30
- );
31
- if (endResponse) {
32
- return endResponse;
33
- }
34
- const pair = new WebSocketPair();
35
- const client = pair[0];
36
- const server = pair[1];
37
- const peer = CloudflareDurablePeer._restore(
38
- obj,
39
- server,
40
- request
41
- );
42
- peers.add(peer);
43
- obj.ctx.acceptWebSocket(server);
44
- await hooks.callHook("open", peer);
45
- return new Response(null, {
46
- status: 101,
47
- webSocket: client,
48
- headers: upgradeHeaders
49
- });
50
- },
51
- handleDurableMessage: async (obj, ws, message) => {
52
- const peer = CloudflareDurablePeer._restore(obj, ws);
53
- await hooks.callHook("message", peer, new Message(message, peer));
54
- },
55
- handleDurableClose: async (obj, ws, code, reason, wasClean) => {
56
- const peer = CloudflareDurablePeer._restore(obj, ws);
57
- peers.delete(peer);
58
- const details = { code, reason, wasClean };
59
- await hooks.callHook("close", peer, details);
60
- }
61
- };
62
- };
63
- class CloudflareDurablePeer extends Peer {
64
- get peers() {
65
- return new Set(
66
- this.#getwebsockets().map(
67
- (ws) => CloudflareDurablePeer._restore(this._internal.durable, ws)
68
- )
69
- );
70
- }
71
- #getwebsockets() {
72
- return this._internal.durable.ctx.getWebSockets();
73
- }
74
- send(data) {
75
- return this._internal.ws.send(toBufferLike(data));
76
- }
77
- subscribe(topic) {
78
- super.subscribe(topic);
79
- const state = getAttachedState(this._internal.ws);
80
- if (!state.t) {
81
- state.t = /* @__PURE__ */ new Set();
82
- }
83
- state.t.add(topic);
84
- setAttachedState(this._internal.ws, state);
85
- }
86
- publish(topic, data) {
87
- const websockets = this.#getwebsockets();
88
- if (websockets.length < 2) {
89
- return;
90
- }
91
- const dataBuff = toBufferLike(data);
92
- for (const ws of websockets) {
93
- if (ws === this._internal.ws) {
94
- continue;
95
- }
96
- const state = getAttachedState(ws);
97
- if (state.t?.has(topic)) {
98
- ws.send(dataBuff);
99
- }
100
- }
101
- }
102
- close(code, reason) {
103
- this._internal.ws.close(code, reason);
104
- }
105
- static _restore(durable, ws, request) {
106
- let peer = ws._crosswsPeer;
107
- if (peer) {
108
- return peer;
109
- }
110
- const state = ws.deserializeAttachment() || {};
111
- peer = ws._crosswsPeer = new CloudflareDurablePeer({
112
- ws,
113
- request: request || { url: state.u },
114
- durable
115
- });
116
- if (state.i) {
117
- peer._id = state.i;
118
- }
119
- if (request?.url) {
120
- state.u = request.url;
121
- }
122
- state.i = peer.id;
123
- setAttachedState(ws, state);
124
- return peer;
125
- }
126
- }
127
- function getAttachedState(ws) {
128
- let state = ws._crosswsState;
129
- if (state) {
130
- return state;
131
- }
132
- state = ws.deserializeAttachment() || {};
133
- ws._crosswsState = state;
134
- return state;
135
- }
136
- function setAttachedState(ws, state) {
137
- ws._crosswsState = state;
138
- ws.serializeAttachment(state);
139
- }
140
-
141
- export { cloudflareDurableAdapter as default };
@@ -1,13 +0,0 @@
1
- import { Adapter, AdapterInstance, AdapterOptions } from '../index.js';
2
- import * as CF from '@cloudflare/workers-types';
3
- import '../shared/crossws.BQXMA5bH.js';
4
-
5
- interface CloudflareAdapter extends AdapterInstance {
6
- handleUpgrade(req: CF.Request, env: unknown, context: CF.ExecutionContext): Promise<CF.Response>;
7
- }
8
- interface CloudflareOptions extends AdapterOptions {
9
- }
10
- declare const cloudflareAdapter: Adapter<CloudflareAdapter, CloudflareOptions>;
11
-
12
- export { cloudflareAdapter as default };
13
- export type { CloudflareAdapter, CloudflareOptions };
@@ -1,19 +0,0 @@
1
- import { Adapter, AdapterInstance, AdapterOptions } from '../index.js';
2
- import '../shared/crossws.BQXMA5bH.js';
3
-
4
- interface DenoAdapter extends AdapterInstance {
5
- handleUpgrade(req: Request, info: ServeHandlerInfo): Promise<Response>;
6
- }
7
- interface DenoOptions extends AdapterOptions {
8
- }
9
- type ServeHandlerInfo = {
10
- remoteAddr?: {
11
- transport: string;
12
- hostname: string;
13
- port: number;
14
- };
15
- };
16
- declare const denoAdapter: Adapter<DenoAdapter, DenoOptions>;
17
-
18
- export { denoAdapter as default };
19
- export type { DenoAdapter, DenoOptions };