@mercuryworkshop/bare-mux
Advanced tools
Comparing version 2.0.1 to 2.0.2
@@ -70,4 +70,4 @@ import { BareHeaders } from './baretypes'; | ||
constructor(worker?: string | MessagePort); | ||
createWebSocket(remote: string | URL, protocols?: string | string[] | undefined, webSocketImpl?: WebSocketImpl, requestHeaders?: BareHeaders, arrayBufferImpl?: typeof ArrayBuffer): WebSocket; | ||
createWebSocket(remote: string | URL, protocols?: string | string[] | undefined, webSocketImpl?: WebSocketImpl, requestHeaders?: BareHeaders, arrayBufferImpl?: ArrayBuffer): WebSocket; | ||
fetch(url: string | URL, init?: RequestInit): Promise<BareResponseFetch>; | ||
} |
@@ -8,3 +8,3 @@ import { BareHeaders, TransferrableResponse } from "./baretypes"; | ||
headers: BareHeaders; | ||
body: ReadableStream | undefined; | ||
body: ReadableStream | ArrayBuffer | undefined; | ||
}; | ||
@@ -33,2 +33,3 @@ websocket?: { | ||
}; | ||
export declare function browserSupportsTransferringStreams(): boolean; | ||
export declare class WorkerConnection { | ||
@@ -35,0 +36,0 @@ channel: BroadcastChannel; |
@@ -31,7 +31,16 @@ (function (global, factory) { | ||
const clients = await self.clients.matchAll({ type: "window", includeUncontrolled: true }); | ||
const promise = Promise.race([...clients.map((x) => tryGetPort(x)), new Promise((_, reject) => setTimeout(reject, 1000, new Error("")))]); | ||
const promises = clients.map(async (x) => { | ||
const port = await tryGetPort(x); | ||
await testPort(port); | ||
return port; | ||
}); | ||
const promise = Promise.race([Promise.any(promises), new Promise((_, reject) => setTimeout(reject, 1000, new TypeError("timeout")))]); | ||
try { | ||
return await promise; | ||
} | ||
catch { | ||
catch (err) { | ||
if (err instanceof AggregateError) { | ||
console.error("bare-mux: failed to get a bare-mux SharedWorker MessagePort as all clients returned an invalid MessagePort."); | ||
throw new Error("All clients returned an invalid MessagePort."); | ||
} | ||
console.warn("bare-mux: failed to get a bare-mux SharedWorker MessagePort within 1s, retrying"); | ||
@@ -50,2 +59,15 @@ return await searchForPort(); | ||
} | ||
function testPort(port) { | ||
const pingChannel = new MessageChannel(); | ||
const pingPromise = new Promise((resolve, reject) => { | ||
pingChannel.port1.onmessage = event => { | ||
if (event.data.type === "pong") { | ||
resolve(); | ||
} | ||
}; | ||
setTimeout(reject, 1500); | ||
}); | ||
port.postMessage({ message: { type: "ping" }, port: pingChannel.port2 }, [pingChannel.port2]); | ||
return pingPromise; | ||
} | ||
function createPort(path, registerHandlers) { | ||
@@ -65,2 +87,22 @@ const worker = new SharedWorker(path, "bare-mux-worker"); | ||
} | ||
let browserSupportsTransferringStreamsCache = null; | ||
function browserSupportsTransferringStreams() { | ||
if (browserSupportsTransferringStreamsCache === null) { | ||
const chan = new MessageChannel(); | ||
const stream = new ReadableStream(); | ||
let res; | ||
try { | ||
chan.port1.postMessage(stream, [stream]); | ||
res = true; | ||
} | ||
catch (err) { | ||
res = false; | ||
} | ||
browserSupportsTransferringStreamsCache = res; | ||
return res; | ||
} | ||
else { | ||
return browserSupportsTransferringStreamsCache; | ||
} | ||
} | ||
class WorkerConnection { | ||
@@ -114,14 +156,4 @@ constructor(worker) { | ||
this.port = await this.port; | ||
const pingChannel = new MessageChannel(); | ||
const pingPromise = new Promise((resolve, reject) => { | ||
pingChannel.port1.onmessage = event => { | ||
if (event.data.type === "pong") { | ||
resolve(); | ||
} | ||
}; | ||
setTimeout(reject, 1500); | ||
}); | ||
this.port.postMessage({ message: { type: "ping" }, port: pingChannel.port2 }, [pingChannel.port2]); | ||
try { | ||
await pingPromise; | ||
await testPort(this.port); | ||
} | ||
@@ -161,4 +193,2 @@ catch { | ||
} | ||
// get the unhooked value | ||
Object.getOwnPropertyDescriptor(WebSocket.prototype, 'readyState').get; | ||
const wsProtocols = ['ws:', 'wss:']; | ||
@@ -423,2 +453,3 @@ const statusEmpty = [101, 204, 205, 304]; | ||
exports.WorkerConnection = WorkerConnection; | ||
exports.browserSupportsTransferringStreams = browserSupportsTransferringStreams; | ||
exports.default = BareClient; | ||
@@ -425,0 +456,0 @@ exports.maxRedirects = maxRedirects; |
(function () { | ||
'use strict'; | ||
'use strict'; | ||
let currentTransport = null; | ||
let currentTransportName = ""; | ||
const channel = new BroadcastChannel("bare-mux"); | ||
channel.postMessage({ type: "refreshPort" }); | ||
function noClients() { | ||
// @ts-expect-error mdn error constructor: new Error(message, options) | ||
return new Error("there are no bare clients", { | ||
cause: "No BareTransport was set. Try creating a BareMuxConnection and calling setTransport() or setManualTransport() on it before using BareClient." | ||
}); | ||
} | ||
function handleConnection(port) { | ||
port.onmessage = async (event) => { | ||
const port = event.data.port; | ||
const message = event.data.message; | ||
if (message.type === "ping") { | ||
port.postMessage({ type: "pong" }); | ||
} | ||
else if (message.type === "set") { | ||
try { | ||
const AsyncFunction = (async function () { }).constructor; | ||
// @ts-expect-error | ||
const func = new AsyncFunction(message.client); | ||
const [newTransport, name] = await func(); | ||
currentTransport = newTransport; | ||
currentTransportName = name; | ||
console.log("set transport to ", currentTransport, name); | ||
port.postMessage({ type: "set" }); | ||
} | ||
catch (err) { | ||
console.error("error while processing 'set': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
else if (message.type === "get") { | ||
port.postMessage({ type: "get", name: currentTransportName }); | ||
} | ||
else if (message.type === "fetch") { | ||
try { | ||
if (!currentTransport) | ||
throw noClients(); | ||
if (!currentTransport.ready) | ||
await currentTransport.init(); | ||
const resp = await currentTransport.request(new URL(message.fetch.remote), message.fetch.method, message.fetch.body, message.fetch.headers, null); | ||
if (resp.body instanceof ReadableStream || resp.body instanceof ArrayBuffer) { | ||
port.postMessage({ type: "fetch", fetch: resp }, [resp.body]); | ||
} | ||
else { | ||
port.postMessage({ type: "fetch", fetch: resp }); | ||
} | ||
} | ||
catch (err) { | ||
console.error("error while processing 'fetch': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
else if (message.type === "websocket") { | ||
try { | ||
if (!currentTransport) | ||
throw noClients(); | ||
if (!currentTransport.ready) | ||
await currentTransport.init(); | ||
const onopen = (protocol) => { | ||
message.websocket.channel.postMessage({ type: "open", args: [protocol] }); | ||
}; | ||
const onclose = (code, reason) => { | ||
message.websocket.channel.postMessage({ type: "close", args: [code, reason] }); | ||
}; | ||
const onerror = (error) => { | ||
message.websocket.channel.postMessage({ type: "error", args: [error] }); | ||
}; | ||
const onmessage = (data) => { | ||
if (data instanceof ArrayBuffer) { | ||
message.websocket.channel.postMessage({ type: "message", args: [data] }, [data]); | ||
} | ||
else { | ||
message.websocket.channel.postMessage({ type: "message", args: [data] }); | ||
} | ||
}; | ||
const [data, close] = currentTransport.connect(new URL(message.websocket.url), message.websocket.origin, message.websocket.protocols, message.websocket.requestHeaders, onopen, onmessage, onclose, onerror); | ||
message.websocket.channel.onmessage = (event) => { | ||
if (event.data.type === "data") { | ||
data(event.data.data); | ||
} | ||
else if (event.data.type === "close") { | ||
close(event.data.closeCode, event.data.closeReason); | ||
} | ||
}; | ||
port.postMessage({ type: "websocket" }); | ||
} | ||
catch (err) { | ||
console.error("error while processing 'websocket': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
}; | ||
} | ||
// @ts-expect-error | ||
self.onconnect = (event) => { | ||
handleConnection(event.ports[0]); | ||
}; | ||
// The user likely has overwritten all networking functions after importing bare-client | ||
// It is our responsibility to make sure components of Bare-Client are using native networking functions | ||
const Response = globalThis.Response; | ||
let browserSupportsTransferringStreamsCache = null; | ||
function browserSupportsTransferringStreams() { | ||
if (browserSupportsTransferringStreamsCache === null) { | ||
const chan = new MessageChannel(); | ||
const stream = new ReadableStream(); | ||
let res; | ||
try { | ||
chan.port1.postMessage(stream, [stream]); | ||
res = true; | ||
} | ||
catch (err) { | ||
res = false; | ||
} | ||
browserSupportsTransferringStreamsCache = res; | ||
return res; | ||
} | ||
else { | ||
return browserSupportsTransferringStreamsCache; | ||
} | ||
} | ||
let currentTransport = null; | ||
let currentTransportName = ""; | ||
const channel = new BroadcastChannel("bare-mux"); | ||
channel.postMessage({ type: "refreshPort" }); | ||
function noClients() { | ||
// @ts-expect-error mdn error constructor: new Error(message, options) | ||
return new Error("there are no bare clients", { | ||
cause: "No BareTransport was set. Try creating a BareMuxConnection and calling setTransport() or setManualTransport() on it before using BareClient." | ||
}); | ||
} | ||
function handleConnection(port) { | ||
port.onmessage = async (event) => { | ||
const port = event.data.port; | ||
const message = event.data.message; | ||
if (message.type === "ping") { | ||
port.postMessage({ type: "pong" }); | ||
} | ||
else if (message.type === "set") { | ||
try { | ||
const AsyncFunction = (async function () { }).constructor; | ||
// @ts-expect-error | ||
const func = new AsyncFunction(message.client); | ||
const [newTransport, name] = await func(); | ||
currentTransport = newTransport; | ||
currentTransportName = name; | ||
console.log("set transport to ", currentTransport, name); | ||
port.postMessage({ type: "set" }); | ||
} | ||
catch (err) { | ||
console.error("error while processing 'set': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
else if (message.type === "get") { | ||
port.postMessage({ type: "get", name: currentTransportName }); | ||
} | ||
else if (message.type === "fetch") { | ||
try { | ||
if (!currentTransport) | ||
throw noClients(); | ||
if (!currentTransport.ready) | ||
await currentTransport.init(); | ||
const resp = await currentTransport.request(new URL(message.fetch.remote), message.fetch.method, message.fetch.body, message.fetch.headers, null); | ||
if (!browserSupportsTransferringStreams() && resp.body instanceof ReadableStream) { | ||
const conversionResp = new Response(resp.body); | ||
resp.body = await conversionResp.arrayBuffer(); | ||
} | ||
if (resp.body instanceof ReadableStream || resp.body instanceof ArrayBuffer) { | ||
port.postMessage({ type: "fetch", fetch: resp }, [resp.body]); | ||
} | ||
else { | ||
port.postMessage({ type: "fetch", fetch: resp }); | ||
} | ||
} | ||
catch (err) { | ||
console.error("error while processing 'fetch': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
else if (message.type === "websocket") { | ||
try { | ||
if (!currentTransport) | ||
throw noClients(); | ||
if (!currentTransport.ready) | ||
await currentTransport.init(); | ||
const onopen = (protocol) => { | ||
message.websocket.channel.postMessage({ type: "open", args: [protocol] }); | ||
}; | ||
const onclose = (code, reason) => { | ||
message.websocket.channel.postMessage({ type: "close", args: [code, reason] }); | ||
}; | ||
const onerror = (error) => { | ||
message.websocket.channel.postMessage({ type: "error", args: [error] }); | ||
}; | ||
const onmessage = (data) => { | ||
if (data instanceof ArrayBuffer) { | ||
message.websocket.channel.postMessage({ type: "message", args: [data] }, [data]); | ||
} | ||
else { | ||
message.websocket.channel.postMessage({ type: "message", args: [data] }); | ||
} | ||
}; | ||
const [data, close] = currentTransport.connect(new URL(message.websocket.url), message.websocket.origin, message.websocket.protocols, message.websocket.requestHeaders, onopen, onmessage, onclose, onerror); | ||
message.websocket.channel.onmessage = (event) => { | ||
if (event.data.type === "data") { | ||
data(event.data.data); | ||
} | ||
else if (event.data.type === "close") { | ||
close(event.data.closeCode, event.data.closeReason); | ||
} | ||
}; | ||
port.postMessage({ type: "websocket" }); | ||
} | ||
catch (err) { | ||
console.error("error while processing 'websocket': ", err); | ||
port.postMessage({ type: "error", error: err }); | ||
} | ||
} | ||
}; | ||
} | ||
// @ts-expect-error | ||
self.onconnect = (event) => { | ||
handleConnection(event.ports[0]); | ||
}; | ||
})(); | ||
//# sourceMappingURL=worker.js.map |
{ | ||
"name": "@mercuryworkshop/bare-mux", | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "type": "module", |
# Bare-Mux | ||
A system for managing http transports in a project such as [Ultraviolet](https://github.com/Titaniumnetwork-dev/Ultraviolet). | ||
@@ -37,3 +38,18 @@ | ||
``` | ||
## Upgrading | ||
A guide for updating from v1 to v2 can be found [here](https://github.com/MercuryWorkshop/bare-mux/blob/master/documentation/Upgrading.md). | ||
## Older bare-mux versions | ||
Starting from v2, bare-mux uses [SharedWorkers](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) to provide stability and improve on resource usage. | ||
If you operate using an older bare-mux, we encourage you to update. | ||
If you're too lazy to do either of the above, you can install an outdated and unsupported version of bare-mux. | ||
```sh | ||
npm install @mercuryworkshop/bare-mux@1 | ||
``` | ||
Examples of transports include [EpoxyTransport](https://github.com/MercuryWorkshop/EpoxyTransport), [CurlTransport](https://github.com/MercuryWorkshop/CurlTransport), and [Bare-Client](https://github.com/MercuryWorkshop/Bare-as-module3). | ||
@@ -40,0 +56,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
90189
1208
85