🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

crossws

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

crossws - npm Package Compare versions

Comparing version
0.4.7
to
0.4.8
+2
dist/websocket/bun.d.mts
declare const _default: typeof globalThis.WebSocket;
export { _default as default };
const _WebSocket = globalThis.WebSocket;
var BunWebSocket = class extends _WebSocket {
constructor(url, protocols, options) {
if (!options) {
super(url, protocols);
return;
}
const opts = { ...options };
if (protocols !== void 0) opts.protocols = protocols;
super(url, opts);
}
};
export { BunWebSocket as default };
declare const _default: typeof globalThis.WebSocket;
export { _default as default };
const _WebSocket = globalThis.WebSocket;
var DenoWebSocket = class extends _WebSocket {
constructor(url, protocols, options) {
const href = typeof url === "string" ? url : url.href;
const isUnix = href.startsWith("ws+unix:");
if (!isUnix && !options) {
super(url, protocols);
return;
}
const opts = { ...options };
if (protocols !== void 0) opts.protocols = protocols;
if (isUnix) {
const { socketPath, path } = _parseUnixTarget(href);
opts.client ??= Deno.createHttpClient({ proxy: {
transport: "unix",
path: socketPath
} });
super(`ws://localhost${path}`, opts);
return;
}
super(url, opts);
}
};
function _parseUnixTarget(href) {
const { pathname, search } = new URL(href);
const raw = pathname + search;
const colon = raw.indexOf(":");
if (colon === -1) return {
socketPath: raw,
path: "/"
};
return {
socketPath: raw.slice(0, colon),
path: raw.slice(colon + 1) || "/"
};
}
export { DenoWebSocket as default };
+38
-0

@@ -7,2 +7,7 @@ import { Adapter, AdapterInstance, AdapterInternal, AdapterOptions, Hooks, Message, Peer, PeerContext, ResolveHooks, SyncAdapter, SyncDriver, SyncErrorContext, SyncMessage, WSError, WaitForDrainOptions, defineHooks, defineWebSocketAdapter } from "./_chunks/adapter.mjs";

*
* A `ws+unix://<socketPath>:<pathname>` target is also supported out of the
* box for proxying to a Unix-socket upstream on Node, Bun, and Deno (no custom
* {@link WebSocket} constructor required) — crossws dials it through the
* matching per-runtime `crossws/websocket` client. See the guide for details.
*
* Can be a static string/URL or a function that resolves the target dynamically

@@ -93,2 +98,35 @@ * based on the incoming {@link Peer}. The resolver may be **async** (return a

headers?: HeadersInit | ((peer: Peer) => HeadersInit | undefined | void);
/**
* Extra options merged into the upstream `WebSocket` constructor's third
* argument, as a static object or a per-peer resolver.
*
* This is the escape hatch for runtime- or client-specific dialing options
* that the WHATWG `WebSocket` signature doesn't cover — e.g. Deno's unstable
* `client` (to dial a Unix socket or use a custom `Deno.HttpClient`), or the
* `ws`/`undici` `createConnection`/`dispatcher`/`agent` options.
*
* Merged with {@link headers}: keys returned here are spread first, then the
* resolved `headers` option is applied on top (so a dedicated `headers`
* option wins over a `headers` key returned here).
*
* > [!NOTE]
* > Only honored by `WebSocket` constructors that accept a third options
* > argument. The WHATWG global browser constructor ignores it; Deno and Bun
* > extend the signature with their own options.
*
* @example Proxy to a Unix socket on Deno
* ```ts
* createWebSocketProxy({
* // Deno's WebSocket rejects the `ws+unix:` scheme, so keep a plain
* // `ws://` target and redirect the transport via the `client` option.
* target: (peer) => `ws://localhost${new URL(peer.request.url).pathname}`,
* webSocketOptions: () => ({
* client: Deno.createHttpClient({
* proxy: { transport: "unix", path: "/run/worker.sock" },
* }),
* }),
* });
* ```
*/
webSocketOptions?: Record<string, unknown> | ((peer: Peer) => Record<string, unknown> | undefined | void);
}

@@ -95,0 +133,0 @@ /**

+11
-7
import { defineHooks, defineWebSocketAdapter } from "./_chunks/adapter.mjs";
import runtimeWebSocket from "crossws/websocket";
const DEFAULT_MAX_BUFFER_SIZE = 1024 * 1024;

@@ -7,3 +8,3 @@ const DEFAULT_CONNECT_TIMEOUT = 1e4;

const options = typeof target === "string" || target instanceof URL || typeof target === "function" ? { target } : target;
const WebSocketCtor = options.WebSocket ?? globalThis.WebSocket;
const WebSocketCtor = options.WebSocket ?? runtimeWebSocket;
if (typeof WebSocketCtor !== "function") throw new TypeError("createWebSocketProxy requires a `WebSocket` constructor. Pass one via the `WebSocket` option, or use a runtime that provides a global `WebSocket` (Node.js >= 22, Bun, Deno, Cloudflare Workers, browsers).");

@@ -94,3 +95,3 @@ const upstreams = /* @__PURE__ */ new Map();

const protocols = _resolveProtocols(peer, options.forwardProtocol);
const wsOptions = _resolveWsOptions(options.headers, peer);
const wsOptions = _resolveWsOptions(options, peer);
ws = wsOptions ? new WebSocketCtor(url, protocols, wsOptions) : new WebSocketCtor(url, protocols);

@@ -151,7 +152,10 @@ ws.binaryType = "arraybuffer";

}
function _resolveWsOptions(headers, peer) {
if (!headers) return;
const resolved = typeof headers === "function" ? headers(peer) : headers;
if (!resolved) return;
return { headers: resolved };
function _resolveWsOptions(options, peer) {
const { headers, webSocketOptions } = options;
const extra = typeof webSocketOptions === "function" ? webSocketOptions(peer) : webSocketOptions;
const resolvedHeaders = typeof headers === "function" ? headers(peer) : headers;
if (!extra && !resolvedHeaders) return;
const merged = { ...extra };
if (resolvedHeaders) merged.headers = resolvedHeaders;
return merged;
}

@@ -158,0 +162,0 @@ function _resolveProtocols(peer, forwardProtocol) {

@@ -1,2 +0,2 @@

declare const Websocket: typeof globalThis.WebSocket;
export { Websocket as default };
declare const NodeWebSocket: typeof globalThis.WebSocket;
export { NodeWebSocket as default };
import { import_websocket } from "../_chunks/libs/ws.mjs";
const Websocket = globalThis.WebSocket || import_websocket.default;
export { Websocket as default };
const _global = globalThis.WebSocket;
const NodeWebSocket = _global ? new Proxy(_global, { construct(target, args) {
const url = args[0];
const Ctor = (typeof url === "string" ? url : url?.href ?? "").startsWith("ws+unix:") || args[2] != null ? import_websocket.default : target;
return Reflect.construct(Ctor, args);
} }) : import_websocket.default;
export { NodeWebSocket as default };
{
"name": "crossws",
"version": "0.4.7",
"version": "0.4.8",
"description": "Cross-platform WebSocket Servers for Node.js, Deno, Bun and Cloudflare Workers",
"homepage": "https://crossws.h3.dev",
"repository": "h3js/crossws",
"license": "MIT",
"repository": "h3js/crossws",
"files": [
"dist",
"adapters",
"websocket",
"server",
"*.d.ts"
],
"sideEffects": false,
"type": "module",
"sideEffects": false,
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"exports": {

@@ -46,4 +36,4 @@ ".": "./dist/index.mjs",

"worker": "./dist/websocket/native.mjs",
"bun": "./dist/websocket/native.mjs",
"deno": "./dist/websocket/native.mjs",
"bun": "./dist/websocket/bun.mjs",
"deno": "./dist/websocket/deno.mjs",
"edge-light": "./dist/websocket/native.mjs",

@@ -55,7 +45,18 @@ "workerd": "./dist/websocket/native.mjs",

},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": [
"dist",
"adapters",
"websocket",
"server",
"*.d.ts"
],
"scripts": {
"prepare": "obuild --stub",
"build": "obuild",
"dev": "vitest",
"fmt": "oxlint . --fix && oxfmt src test",
"lint": "oxlint . && oxfmt --check src test",
"fmt": "oxlint . --fix && oxfmt src test",
"prepack": "pnpm run build",

@@ -73,10 +74,13 @@ "play:bun": "bun --watch test/fixture/bun.ts",

},
"resolutions": {
"crossws": "workspace:*"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20260629.1",
"@cloudflare/workers-types": "^4.20260701.1",
"@types/bun": "^1.3.14",
"@types/deno": "^2.7.0",
"@types/node": "^26.0.1",
"@types/web": "^0.0.351",
"@types/node": "^26.1.0",
"@types/web": "^0.0.352",
"@types/ws": "^8.18.1",
"@typescript/native-preview": "7.0.0-dev.20260629.1",
"@typescript/native-preview": "^7.0.0-dev.20260701.1",
"@vitest/coverage-v8": "^4.1.9",

@@ -94,5 +98,5 @@ "automd": "^0.4.3",

"obuild": "^0.4.37",
"oxfmt": "^0.56.0",
"oxlint": "^1.71.0",
"srvx": "^0.11.17",
"oxfmt": "^0.57.0",
"oxlint": "^1.72.0",
"srvx": "^0.11.18",
"typescript": "^6.0.3",

@@ -103,3 +107,3 @@ "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.57.0",

"vitest": "^4.1.9",
"wrangler": "^4.105.0",
"wrangler": "^4.106.0",
"ws": "^8.21.0"

@@ -115,6 +119,3 @@ },

},
"resolutions": {
"crossws": "workspace:*"
},
"packageManager": "pnpm@11.7.0"
}