crossws 0.4.0 → 0.4.2

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.
@@ -4,7 +4,7 @@ import '../shared/crossws.BQXMA5bH.mjs';
4
4
 
5
5
  interface BunAdapter extends AdapterInstance {
6
6
  websocket: WebSocketHandler<ContextData>;
7
- handleUpgrade(req: Request, server: Server): Promise<Response | undefined>;
7
+ handleUpgrade(req: Request, server: Server<ContextData>): Promise<Response | undefined>;
8
8
  }
9
9
  interface BunOptions extends AdapterOptions {
10
10
  }
@@ -12,7 +12,7 @@ type ContextData = {
12
12
  peer?: BunPeer;
13
13
  namespace: string;
14
14
  request: Request;
15
- server?: Server;
15
+ server?: Server<ContextData>;
16
16
  context: PeerContext;
17
17
  };
18
18
  declare const bunAdapter: Adapter<BunAdapter, BunOptions>;
@@ -67,6 +67,7 @@ const cloudflareAdapter = (opts = {}) => {
67
67
  server.addEventListener("close", (event) => {
68
68
  peers.delete(peer);
69
69
  hooks.callHook("close", peer, event);
70
+ server.close();
70
71
  });
71
72
  return new Response(null, {
72
73
  status: 101,
@@ -1,7 +1,7 @@
1
1
  import { M as Message, P as Peer, t as toBufferLike } from '../shared/crossws.WpyOHUXc.mjs';
2
2
  import { g as getPeers, A as AdapterHookable, a as adapterUtils } from '../shared/crossws.CPlNx7g8.mjs';
3
3
  import { W as WSError } from '../shared/crossws.By9qWDAI.mjs';
4
- import { _ as _WebSocketServer } from '../shared/crossws.CipVM6lf.mjs';
4
+ import { _ as _WebSocketServer } from '../shared/crossws.C5pESzqN.mjs';
5
5
  import { S as StubRequest } from '../shared/crossws.B31KJMcF.mjs';
6
6
  import 'stream';
7
7
  import 'events';
@@ -1,5 +1,5 @@
1
- import { ServerPlugin, Server } from 'srvx/types';
2
- import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.95-eYp2D.mjs';
1
+ import { ServerPlugin, Server } from 'srvx';
2
+ import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.CP-89VBK.mjs';
3
3
  import '../index.mjs';
4
4
  import '../shared/crossws.BQXMA5bH.mjs';
5
5
  import '../adapters/bun.mjs';
@@ -1,5 +1,5 @@
1
- import { ServerPlugin, Server } from 'srvx/types';
2
- import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.95-eYp2D.mjs';
1
+ import { ServerPlugin, Server } from 'srvx';
2
+ import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.CP-89VBK.mjs';
3
3
  import '../index.mjs';
4
4
  import '../shared/crossws.BQXMA5bH.mjs';
5
5
  import '../adapters/bun.mjs';
@@ -1,5 +1,5 @@
1
- import { ServerPlugin, Server } from 'srvx/types';
2
- import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.95-eYp2D.mjs';
1
+ import { ServerPlugin, Server } from 'srvx';
2
+ import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.CP-89VBK.mjs';
3
3
  import '../index.mjs';
4
4
  import '../shared/crossws.BQXMA5bH.mjs';
5
5
  import '../adapters/bun.mjs';
@@ -1,5 +1,5 @@
1
- import { ServerPlugin, Server } from 'srvx/types';
2
- import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.95-eYp2D.mjs';
1
+ import { ServerPlugin, Server } from 'srvx';
2
+ import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.CP-89VBK.mjs';
3
3
  import '../index.mjs';
4
4
  import '../shared/crossws.BQXMA5bH.mjs';
5
5
  import '../adapters/bun.mjs';
@@ -1,5 +1,5 @@
1
- import { ServerPlugin, Server } from 'srvx/types';
2
- import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.95-eYp2D.mjs';
1
+ import { ServerPlugin, Server } from 'srvx';
2
+ import { W as WSOptions, S as ServerWithWSOptions } from '../shared/crossws.CP-89VBK.mjs';
3
3
  import '../index.mjs';
4
4
  import '../shared/crossws.BQXMA5bH.mjs';
5
5
  import '../adapters/bun.mjs';
@@ -3,7 +3,7 @@ import nodeAdapter from '../adapters/node.mjs';
3
3
  import '../shared/crossws.WpyOHUXc.mjs';
4
4
  import '../shared/crossws.CPlNx7g8.mjs';
5
5
  import '../shared/crossws.By9qWDAI.mjs';
6
- import '../shared/crossws.CipVM6lf.mjs';
6
+ import '../shared/crossws.C5pESzqN.mjs';
7
7
  import 'stream';
8
8
  import 'events';
9
9
  import 'http';
@@ -26,7 +26,13 @@ function plugin(wsOpts) {
26
26
  const originalServe = server.serve;
27
27
  server.serve = () => {
28
28
  server.node?.server.on("upgrade", (req, socket, head) => {
29
- ws.handleUpgrade(req, socket, head, new NodeRequest(req));
29
+ ws.handleUpgrade(
30
+ req,
31
+ socket,
32
+ head,
33
+ // @ts-expect-error (upgrade is not typed)
34
+ new NodeRequest({ req, upgrade: { socket, head } })
35
+ );
30
36
  });
31
37
  return originalServe.call(server);
32
38
  };
@@ -29,6 +29,7 @@ function requireConstants () {
29
29
 
30
30
  constants = {
31
31
  BINARY_TYPES,
32
+ CLOSE_TIMEOUT: 30000,
32
33
  EMPTY_BUFFER: Buffer.alloc(0),
33
34
  GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
34
35
  hasBlob,
@@ -2799,6 +2800,7 @@ function requireWebsocket () {
2799
2800
 
2800
2801
  const {
2801
2802
  BINARY_TYPES,
2803
+ CLOSE_TIMEOUT,
2802
2804
  EMPTY_BUFFER,
2803
2805
  GUID,
2804
2806
  kForOnEventAttribute,
@@ -2813,7 +2815,6 @@ function requireWebsocket () {
2813
2815
  const { format, parse } = requireExtension();
2814
2816
  const { toBuffer } = requireBufferUtil();
2815
2817
 
2816
- const closeTimeout = 30 * 1000;
2817
2818
  const kAborted = Symbol('kAborted');
2818
2819
  const protocolVersions = [8, 13];
2819
2820
  const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
@@ -2869,6 +2870,7 @@ function requireWebsocket () {
2869
2870
  initAsClient(this, address, protocols, options);
2870
2871
  } else {
2871
2872
  this._autoPong = options.autoPong;
2873
+ this._closeTimeout = options.closeTimeout;
2872
2874
  this._isServer = true;
2873
2875
  }
2874
2876
  }
@@ -3410,6 +3412,8 @@ function requireWebsocket () {
3410
3412
  * times in the same tick
3411
3413
  * @param {Boolean} [options.autoPong=true] Specifies whether or not to
3412
3414
  * automatically send a pong in response to a ping
3415
+ * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
3416
+ * for the closing handshake to finish after `websocket.close()` is called
3413
3417
  * @param {Function} [options.finishRequest] A function which can be used to
3414
3418
  * customize the headers of each http request before it is sent
3415
3419
  * @param {Boolean} [options.followRedirects=false] Whether or not to follow
@@ -3436,6 +3440,7 @@ function requireWebsocket () {
3436
3440
  const opts = {
3437
3441
  allowSynchronousEvents: true,
3438
3442
  autoPong: true,
3443
+ closeTimeout: CLOSE_TIMEOUT,
3439
3444
  protocolVersion: protocolVersions[1],
3440
3445
  maxPayload: 100 * 1024 * 1024,
3441
3446
  skipUTF8Validation: false,
@@ -3454,6 +3459,7 @@ function requireWebsocket () {
3454
3459
  };
3455
3460
 
3456
3461
  websocket._autoPong = opts.autoPong;
3462
+ websocket._closeTimeout = opts.closeTimeout;
3457
3463
 
3458
3464
  if (!protocolVersions.includes(opts.protocolVersion)) {
3459
3465
  throw new RangeError(
@@ -4071,7 +4077,7 @@ function requireWebsocket () {
4071
4077
  function setCloseTimer(websocket) {
4072
4078
  websocket._closeTimer = setTimeout(
4073
4079
  websocket._socket.destroy.bind(websocket._socket),
4074
- closeTimeout
4080
+ websocket._closeTimeout
4075
4081
  );
4076
4082
  }
4077
4083
 
@@ -4089,23 +4095,23 @@ function requireWebsocket () {
4089
4095
 
4090
4096
  websocket._readyState = WebSocket.CLOSING;
4091
4097
 
4092
- let chunk;
4093
-
4094
4098
  //
4095
4099
  // The close frame might not have been received or the `'end'` event emitted,
4096
4100
  // for example, if the socket was destroyed due to an error. Ensure that the
4097
4101
  // `receiver` stream is closed after writing any remaining buffered data to
4098
4102
  // it. If the readable side of the socket is in flowing mode then there is no
4099
- // buffered data as everything has been already written and `readable.read()`
4100
- // will return `null`. If instead, the socket is paused, any possible buffered
4101
- // data will be read as a single chunk.
4103
+ // buffered data as everything has been already written. If instead, the
4104
+ // socket is paused, any possible buffered data will be read as a single
4105
+ // chunk.
4102
4106
  //
4103
4107
  if (
4104
4108
  !this._readableState.endEmitted &&
4105
4109
  !websocket._closeFrameReceived &&
4106
4110
  !websocket._receiver._writableState.errorEmitted &&
4107
- (chunk = websocket._socket.read()) !== null
4111
+ this._readableState.length !== 0
4108
4112
  ) {
4113
+ const chunk = this.read(this._readableState.length);
4114
+
4109
4115
  websocket._receiver.write(chunk);
4110
4116
  }
4111
4117
 
@@ -4437,7 +4443,7 @@ function requireWebsocketServer () {
4437
4443
  const PerMessageDeflate = requirePermessageDeflate();
4438
4444
  const subprotocol = requireSubprotocol();
4439
4445
  const WebSocket = requireWebsocket();
4440
- const { GUID, kWebSocket } = requireConstants();
4446
+ const { CLOSE_TIMEOUT, GUID, kWebSocket } = requireConstants();
4441
4447
 
4442
4448
  const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
4443
4449
 
@@ -4464,6 +4470,9 @@ function requireWebsocketServer () {
4464
4470
  * pending connections
4465
4471
  * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
4466
4472
  * track clients
4473
+ * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
4474
+ * wait for the closing handshake to finish after `websocket.close()` is
4475
+ * called
4467
4476
  * @param {Function} [options.handleProtocols] A hook to handle protocols
4468
4477
  * @param {String} [options.host] The hostname where to bind the server
4469
4478
  * @param {Number} [options.maxPayload=104857600] The maximum allowed message
@@ -4493,6 +4502,7 @@ function requireWebsocketServer () {
4493
4502
  perMessageDeflate: false,
4494
4503
  handleProtocols: null,
4495
4504
  clientTracking: true,
4505
+ closeTimeout: CLOSE_TIMEOUT,
4496
4506
  verifyClient: null,
4497
4507
  noServer: false,
4498
4508
  backlog: null, // use default (511 as implemented in net.js)
@@ -4682,9 +4692,11 @@ function requireWebsocketServer () {
4682
4692
  return;
4683
4693
  }
4684
4694
 
4685
- if (version !== 8 && version !== 13) {
4695
+ if (version !== 13 && version !== 8) {
4686
4696
  const message = 'Missing or invalid Sec-WebSocket-Version header';
4687
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4697
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {
4698
+ 'Sec-WebSocket-Version': '13, 8'
4699
+ });
4688
4700
  return;
4689
4701
  }
4690
4702
 
@@ -4952,16 +4964,24 @@ function requireWebsocketServer () {
4952
4964
  * @param {Duplex} socket The socket of the upgrade request
4953
4965
  * @param {Number} code The HTTP response status code
4954
4966
  * @param {String} message The HTTP response body
4967
+ * @param {Object} [headers] The HTTP response headers
4955
4968
  * @private
4956
4969
  */
4957
- function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) {
4970
+ function abortHandshakeOrEmitwsClientError(
4971
+ server,
4972
+ req,
4973
+ socket,
4974
+ code,
4975
+ message,
4976
+ headers
4977
+ ) {
4958
4978
  if (server.listenerCount('wsClientError')) {
4959
4979
  const err = new Error(message);
4960
4980
  Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
4961
4981
 
4962
4982
  server.emit('wsClientError', err, socket, req);
4963
4983
  } else {
4964
- abortHandshake(socket, code, message);
4984
+ abortHandshake(socket, code, message, headers);
4965
4985
  }
4966
4986
  }
4967
4987
  return websocketServer;
@@ -1,4 +1,4 @@
1
- import { ServerRequest, ServerOptions } from 'srvx/types';
1
+ import { ServerRequest, ServerOptions } from 'srvx';
2
2
  import { Hooks } from '../index.mjs';
3
3
  import { BunOptions } from '../adapters/bun.mjs';
4
4
  import { DenoOptions } from '../adapters/deno.mjs';
@@ -1,4 +1,4 @@
1
- import { a as _WebSocket } from '../shared/crossws.CipVM6lf.mjs';
1
+ import { a as _WebSocket } from '../shared/crossws.C5pESzqN.mjs';
2
2
  import 'stream';
3
3
  import 'events';
4
4
  import 'http';
@@ -12,12 +12,10 @@ class WebSocketSSE extends _EventTarget {
12
12
  OPEN = 1;
13
13
  CLOSING = 2;
14
14
  CLOSED = 3;
15
- /* eslint-disable unicorn/no-null */
16
15
  onclose = null;
17
16
  onerror = null;
18
17
  onopen = null;
19
18
  onmessage = null;
20
- /* eslint-enable unicorn/no-null */
21
19
  binaryType = "blob";
22
20
  readyState = WebSocketSSE.CONNECTING;
23
21
  url;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crossws",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Cross-platform WebSocket Servers for Node.js, Deno, Bun and Cloudflare Workers",
5
5
  "homepage": "https://crossws.h3.dev",
6
6
  "repository": "h3js/crossws",
@@ -62,39 +62,40 @@
62
62
  "play:uws": "jiti test/fixture/uws.ts",
63
63
  "release": "pnpm test && pnpm build && changelogen --release && npm publish && git push --follow-tags",
64
64
  "test": "pnpm lint && pnpm test:types && vitest run --coverage",
65
- "test:types": "tsc --noEmit --skipLibCheck"
65
+ "test:types": "tsgo --noEmit --skipLibCheck"
66
66
  },
67
67
  "resolutions": {
68
68
  "crossws": "workspace:*"
69
69
  },
70
70
  "devDependencies": {
71
- "@cloudflare/workers-types": "^4.20250523.0",
72
- "@types/bun": "^1.2.14",
73
- "@types/deno": "^2.3.0",
74
- "@types/node": "^22.15.21",
75
- "@types/web": "^0.0.235",
71
+ "@cloudflare/workers-types": "^4.20260118.0",
72
+ "@types/bun": "^1.3.6",
73
+ "@types/deno": "^2.5.0",
74
+ "@types/node": "^25.0.9",
75
+ "@types/web": "^0.0.318",
76
76
  "@types/ws": "^8.18.1",
77
- "@vitest/coverage-v8": "^3.1.4",
78
- "automd": "^0.4.0",
79
- "changelogen": "^0.6.1",
77
+ "@typescript/native-preview": "7.0.0-dev.20260119.1",
78
+ "@vitest/coverage-v8": "^4.0.17",
79
+ "automd": "^0.4.2",
80
+ "changelogen": "^0.6.2",
80
81
  "consola": "^3.4.2",
81
- "eslint": "^9.27.0",
82
- "eslint-config-unjs": "^0.4.2",
83
- "eventsource": "^4.0.0",
84
- "execa": "^9.5.3",
85
- "get-port-please": "^3.1.2",
86
- "h3": "^1.15.3",
87
- "jiti": "^2.4.2",
82
+ "eslint": "^9.39.2",
83
+ "eslint-config-unjs": "^0.6.2",
84
+ "eventsource": "^4.1.0",
85
+ "execa": "^9.6.1",
86
+ "get-port-please": "^3.2.0",
87
+ "h3": "^2.0.1-rc.8",
88
+ "jiti": "^2.6.1",
88
89
  "listhen": "^1.9.0",
89
- "prettier": "^3.5.3",
90
- "srvx": "^0.7.1",
91
- "typescript": "^5.8.3",
92
- "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.44.0",
93
- "unbuild": "^3.5.0",
94
- "undici": "^7.10.0",
95
- "vitest": "^3.1.4",
96
- "wrangler": "^4.16.1",
97
- "ws": "^8.18.2"
90
+ "prettier": "^3.8.0",
91
+ "srvx": "^0.10.1",
92
+ "typescript": "^5.9.3",
93
+ "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.57.0",
94
+ "unbuild": "^3.6.1",
95
+ "undici": "^7.18.2",
96
+ "vitest": "^4.0.17",
97
+ "wrangler": "^4.59.2",
98
+ "ws": "^8.19.0"
98
99
  },
99
100
  "peerDependencies": {
100
101
  "srvx": ">=0.7.1"
@@ -104,13 +105,19 @@
104
105
  "optional": true
105
106
  }
106
107
  },
107
- "packageManager": "pnpm@10.11.0",
108
+ "packageManager": "pnpm@10.28.1",
108
109
  "pnpm": {
109
110
  "ignoredBuiltDependencies": [
110
111
  "@parcel/watcher",
111
112
  "esbuild",
112
113
  "sharp",
113
114
  "workerd"
115
+ ],
116
+ "onlyBuiltDependencies": [
117
+ "@parcel/watcher",
118
+ "esbuild",
119
+ "sharp",
120
+ "workerd"
114
121
  ]
115
122
  }
116
123
  }
@@ -1,2 +0,0 @@
1
- export * from "../dist/adapters/cloudflare-durable";
2
- export { default } from "../dist/adapters/cloudflare-durable";