This commit is contained in:
CoolElectronics 2024-02-11 20:53:00 -05:00
parent 86abdca21e
commit 5a5a5debdb
No known key found for this signature in database
GPG key ID: F63593D168636C50
13 changed files with 314 additions and 222 deletions

View file

@ -56,6 +56,6 @@ export declare class BareClient {
* Create a BareClient. Calls to fetch and connect will wait for an implementation to be ready.
*/
constructor();
createWebSocket(remote: string | URL, protocols: string | string[] | undefined, options: BareWebSocket.Options, origin: string): WebSocket;
createWebSocket(remote: string | URL, protocols: string | string[] | undefined, webSocketImpl: WebSocketImpl, requestHeaders: BareHeaders): WebSocket;
fetch(url: string | URL, init?: RequestInit): Promise<BareResponseFetch>;
}

2
dist/BareTypes.d.ts vendored
View file

@ -9,7 +9,7 @@ export type TransferrableResponse = {
export interface BareTransport {
init: () => Promise<void>;
ready: boolean;
connect: (url: URL, origin: string, protocols: string[], onopen: (protocol: string) => void, onmessage: (data: Blob | ArrayBuffer | string) => void, onclose: (code: number, reason: string) => void, onerror: (error: string) => void) => (data: Blob | ArrayBuffer | string) => void;
connect: (url: URL, origin: string, protocols: string[], requestHeaders: BareHeaders, onopen: (protocol: string) => void, onmessage: (data: Blob | ArrayBuffer | string) => void, onclose: (code: number, reason: string) => void, onerror: (error: string) => void) => (data: Blob | ArrayBuffer | string) => void;
request: (remote: URL, method: string, body: BodyInit | null, headers: BareHeaders, signal: AbortSignal | undefined) => Promise<TransferrableResponse>;
meta: () => BareMeta;
}

7
dist/Switcher.d.ts vendored
View file

@ -17,10 +17,11 @@ declare global {
}
}
declare class Switcher {
transports: Record<string, BareTransport>;
active: BareTransport | null;
channel: BroadcastChannel;
constructor();
}
export declare function findSwitcher(): Switcher;
export declare function AddTransport(name: string, client: BareTransport): void;
export declare function SetTransport(name: string): void;
export declare function SetTransport(name: string, ...config: any[]): void;
export declare function SetSingletonTransport(client: BareTransport): void;
export {};

122
dist/bare.cjs vendored
View file

@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bare = {}));
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.BareMux = {}));
})(this, (function (exports) { 'use strict';
const maxRedirects = 20;
@ -22,25 +22,45 @@
OPEN: WebSocket.OPEN,
};
self.BCC_VERSION = "2.1.3";
self.BCC_VERSION = "3.0.2";
console.warn("BCC_VERSION: " + self.BCC_VERSION);
if (!("gTransports" in globalThis)) {
globalThis.gTransports = {};
}
class Switcher {
transports = {};
active = null;
channel = new BroadcastChannel("bare-mux");
constructor() {
this.channel.addEventListener("message", ({ data: { type, data } }) => {
console.log(type, data, "ServiceWorker" in globalThis);
switch (type) {
case "setremote":
// this.active = new RemoteClient
break;
case "set":
const { name, config } = data;
this.active = new ((0, eval)(name))(...config);
break;
}
});
}
}
function findSwitcher() {
if (globalThis.gSwitcher)
return globalThis.gSwitcher;
if ("ServiceWorkerGlobalScope" in globalThis) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
let _parent = window;
for (let i = 0; i < 20; i++) {
try {
parent = parent.parent;
if (parent && parent["gSwitcher"]) {
if (_parent == _parent.parent) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
_parent = _parent.parent;
if (_parent && _parent["gSwitcher"]) {
console.warn("found implementation on parent");
globalThis.gSwitcher = parent["gSwitcher"];
return parent["gSwitcher"];
globalThis.gSwitcher = _parent["gSwitcher"];
return _parent["gSwitcher"];
}
}
catch (e) {
@ -50,6 +70,17 @@
}
throw "unreachable";
}
findSwitcher();
function SetTransport(name, ...config) {
let switcher = findSwitcher();
switcher.active = new ((0, eval)(name))(...config);
switcher.channel.postMessage({ type: "set", data: { name, config } });
}
function SetSingletonTransport(client) {
let switcher = findSwitcher();
switcher.active = client;
switcher.channel.postMessage({ type: "setremote" });
}
/*
* WebSocket helpers
@ -75,7 +106,7 @@
* Create a BareClient. Calls to fetch and connect will wait for an implementation to be ready.
*/
constructor() { }
createWebSocket(remote, protocols = [], options, origin) {
createWebSocket(remote, protocols = [], webSocketImpl, requestHeaders) {
let switcher = findSwitcher();
let client = switcher.active;
if (!client)
@ -96,7 +127,7 @@
for (const proto of protocols)
if (!validProtocol(proto))
throw new DOMException(`Failed to construct 'WebSocket': The subprotocol '${proto}' is invalid.`);
let wsImpl = (options.webSocketImpl || WebSocket);
let wsImpl = (webSocketImpl || WebSocket);
const socket = new wsImpl("wss:null", protocols);
let fakeProtocol = '';
let fakeReadyState = WebSocketFields.CONNECTING;
@ -108,21 +139,37 @@
initialErrorHappened = true;
}
});
const sendData = client.connect(remote, origin, protocols, (protocol) => {
// TODO socket onerror will be broken
requestHeaders['Host'] = (new URL(remote)).host;
// requestHeaders['Origin'] = origin;
requestHeaders['Pragma'] = 'no-cache';
requestHeaders['Cache-Control'] = 'no-cache';
requestHeaders['Upgrade'] = 'websocket';
// requestHeaders['User-Agent'] = navigator.userAgent;
requestHeaders['Connection'] = 'Upgrade';
const sendData = client.connect(remote, origin, protocols, requestHeaders, (protocol) => {
fakeReadyState = WebSocketFields.OPEN;
fakeProtocol = protocol;
socket.meta = {
headers: {
"sec-websocket-protocol": protocol,
}
}; // what the fuck is a meta
socket.dispatchEvent(new Event("open"));
}, (payload) => {
if (typeof payload === "string") {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
console.log(payload);
if (payload.data) {
socket.dispatchEvent(new MessageEvent("message", { data: payload.data }));
return;
}
else if (payload instanceof ArrayBuffer) {
Object.setPrototypeOf(payload, ArrayBuffer);
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
}
else if (payload instanceof Blob) {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
}
// if (typeof payload === "string") {
// } else if (payload instanceof ArrayBuffer) {
// Object.setPrototypeOf(payload, ArrayBuffer);
//
// socket.dispatchEvent(new MessageEvent("message", { data: payload }));
// } else if (payload instanceof Blob) {
// }
}, (code, reason) => {
fakeReadyState = WebSocketFields.CLOSED;
socket.dispatchEvent(new CloseEvent("close", { code, reason }));
@ -146,13 +193,6 @@
// // user is expected to specify user-agent and origin
// // both are in spec
//
// requestHeaders['Host'] = (remote as URL).host;
// // requestHeaders['Origin'] = origin;
// requestHeaders['Pragma'] = 'no-cache';
// requestHeaders['Cache-Control'] = 'no-cache';
// requestHeaders['Upgrade'] = 'websocket';
// // requestHeaders['User-Agent'] = navigator.userAgent;
// requestHeaders['Connection'] = 'Upgrade';
//
// return requestHeaders;
// },
@ -176,16 +216,12 @@
? fakeReadyState
: realReadyState;
};
if (options.readyStateHook)
options.readyStateHook(socket, getReadyState);
else {
// we have to hook .readyState ourselves
Object.defineProperty(socket, 'readyState', {
get: getReadyState,
configurable: true,
enumerable: true,
});
}
/**
* @returns The error that should be thrown if send() were to be called on this socket according to the fake readyState value
*/
@ -194,9 +230,6 @@
if (readyState === WebSocketFields.CONNECTING)
return new DOMException("Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.");
};
if (options.sendErrorHook)
options.sendErrorHook(socket, getSendError);
else {
// we have to hook .send ourselves
// use ...args to avoid giving the number of args a quantity
// no arguments will trip the following error: TypeError: Failed to execute 'send' on 'WebSocket': 1 argument required, but only 0 present.
@ -206,19 +239,12 @@
throw error;
sendData(args[0]);
};
}
if (options.urlHook)
options.urlHook(socket, remote);
else
Object.defineProperty(socket, 'url', {
get: () => remote.toString(),
configurable: true,
enumerable: true,
});
const getProtocol = () => fakeProtocol;
if (options.protocolHook)
options.protocolHook(socket, getProtocol);
else
Object.defineProperty(socket, 'protocol', {
get: getProtocol,
configurable: true,
@ -248,7 +274,7 @@
}
let switcher = findSwitcher();
if (!switcher.active)
throw "invalid";
throw "there are no bare clients";
const client = switcher.active;
if (!client.ready)
await client.init();
@ -259,7 +285,9 @@
headers.Host = urlO.host;
let resp = await client.request(urlO, req.method, body, headers, req.signal);
let responseobj = new Response(statusEmpty.includes(resp.status) ? undefined : resp.body, {
headers: new Headers(resp.headers)
headers: new Headers(resp.headers),
status: resp.status,
statusText: resp.statusText,
});
responseobj.rawHeaders = resp.headers;
responseobj.rawResponse = new Response(resp.body);
@ -290,8 +318,14 @@
}
exports.BareClient = BareClient;
exports.SetSingletonTransport = SetSingletonTransport;
exports.SetTransport = SetTransport;
exports.WebSocketFields = WebSocketFields;
exports.default = BareClient;
exports.findSwitcher = findSwitcher;
exports.maxRedirects = maxRedirects;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=bare.cjs.map

2
dist/bare.cjs.map vendored

File diff suppressed because one or more lines are too long

2
dist/index.d.ts vendored
View file

@ -1,3 +1,5 @@
export * from './BareTypes';
export * from './BareClient';
export * from './Switcher';
export { BareClient as default } from './BareClient';
export { WebSocketFields } from "./snapshot";

116
dist/index.js vendored
View file

@ -16,25 +16,45 @@ const WebSocketFields = {
OPEN: WebSocket.OPEN,
};
self.BCC_VERSION = "2.1.3";
self.BCC_VERSION = "3.0.2";
console.warn("BCC_VERSION: " + self.BCC_VERSION);
if (!("gTransports" in globalThis)) {
globalThis.gTransports = {};
}
class Switcher {
transports = {};
active = null;
channel = new BroadcastChannel("bare-mux");
constructor() {
this.channel.addEventListener("message", ({ data: { type, data } }) => {
console.log(type, data, "ServiceWorker" in globalThis);
switch (type) {
case "setremote":
// this.active = new RemoteClient
break;
case "set":
const { name, config } = data;
this.active = new ((0, eval)(name))(...config);
break;
}
});
}
}
function findSwitcher() {
if (globalThis.gSwitcher)
return globalThis.gSwitcher;
if ("ServiceWorkerGlobalScope" in globalThis) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
let _parent = window;
for (let i = 0; i < 20; i++) {
try {
parent = parent.parent;
if (parent && parent["gSwitcher"]) {
if (_parent == _parent.parent) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
_parent = _parent.parent;
if (_parent && _parent["gSwitcher"]) {
console.warn("found implementation on parent");
globalThis.gSwitcher = parent["gSwitcher"];
return parent["gSwitcher"];
globalThis.gSwitcher = _parent["gSwitcher"];
return _parent["gSwitcher"];
}
}
catch (e) {
@ -44,6 +64,17 @@ function findSwitcher() {
}
throw "unreachable";
}
findSwitcher();
function SetTransport(name, ...config) {
let switcher = findSwitcher();
switcher.active = new ((0, eval)(name))(...config);
switcher.channel.postMessage({ type: "set", data: { name, config } });
}
function SetSingletonTransport(client) {
let switcher = findSwitcher();
switcher.active = client;
switcher.channel.postMessage({ type: "setremote" });
}
/*
* WebSocket helpers
@ -69,7 +100,7 @@ class BareClient {
* Create a BareClient. Calls to fetch and connect will wait for an implementation to be ready.
*/
constructor() { }
createWebSocket(remote, protocols = [], options, origin) {
createWebSocket(remote, protocols = [], webSocketImpl, requestHeaders) {
let switcher = findSwitcher();
let client = switcher.active;
if (!client)
@ -90,7 +121,7 @@ class BareClient {
for (const proto of protocols)
if (!validProtocol(proto))
throw new DOMException(`Failed to construct 'WebSocket': The subprotocol '${proto}' is invalid.`);
let wsImpl = (options.webSocketImpl || WebSocket);
let wsImpl = (webSocketImpl || WebSocket);
const socket = new wsImpl("wss:null", protocols);
let fakeProtocol = '';
let fakeReadyState = WebSocketFields.CONNECTING;
@ -102,21 +133,37 @@ class BareClient {
initialErrorHappened = true;
}
});
const sendData = client.connect(remote, origin, protocols, (protocol) => {
// TODO socket onerror will be broken
requestHeaders['Host'] = (new URL(remote)).host;
// requestHeaders['Origin'] = origin;
requestHeaders['Pragma'] = 'no-cache';
requestHeaders['Cache-Control'] = 'no-cache';
requestHeaders['Upgrade'] = 'websocket';
// requestHeaders['User-Agent'] = navigator.userAgent;
requestHeaders['Connection'] = 'Upgrade';
const sendData = client.connect(remote, origin, protocols, requestHeaders, (protocol) => {
fakeReadyState = WebSocketFields.OPEN;
fakeProtocol = protocol;
socket.meta = {
headers: {
"sec-websocket-protocol": protocol,
}
}; // what the fuck is a meta
socket.dispatchEvent(new Event("open"));
}, (payload) => {
if (typeof payload === "string") {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
console.log(payload);
if (payload.data) {
socket.dispatchEvent(new MessageEvent("message", { data: payload.data }));
return;
}
else if (payload instanceof ArrayBuffer) {
Object.setPrototypeOf(payload, ArrayBuffer);
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
}
else if (payload instanceof Blob) {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
}
// if (typeof payload === "string") {
// } else if (payload instanceof ArrayBuffer) {
// Object.setPrototypeOf(payload, ArrayBuffer);
//
// socket.dispatchEvent(new MessageEvent("message", { data: payload }));
// } else if (payload instanceof Blob) {
// }
}, (code, reason) => {
fakeReadyState = WebSocketFields.CLOSED;
socket.dispatchEvent(new CloseEvent("close", { code, reason }));
@ -140,13 +187,6 @@ class BareClient {
// // user is expected to specify user-agent and origin
// // both are in spec
//
// requestHeaders['Host'] = (remote as URL).host;
// // requestHeaders['Origin'] = origin;
// requestHeaders['Pragma'] = 'no-cache';
// requestHeaders['Cache-Control'] = 'no-cache';
// requestHeaders['Upgrade'] = 'websocket';
// // requestHeaders['User-Agent'] = navigator.userAgent;
// requestHeaders['Connection'] = 'Upgrade';
//
// return requestHeaders;
// },
@ -170,16 +210,12 @@ class BareClient {
? fakeReadyState
: realReadyState;
};
if (options.readyStateHook)
options.readyStateHook(socket, getReadyState);
else {
// we have to hook .readyState ourselves
Object.defineProperty(socket, 'readyState', {
get: getReadyState,
configurable: true,
enumerable: true,
});
}
/**
* @returns The error that should be thrown if send() were to be called on this socket according to the fake readyState value
*/
@ -188,9 +224,6 @@ class BareClient {
if (readyState === WebSocketFields.CONNECTING)
return new DOMException("Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.");
};
if (options.sendErrorHook)
options.sendErrorHook(socket, getSendError);
else {
// we have to hook .send ourselves
// use ...args to avoid giving the number of args a quantity
// no arguments will trip the following error: TypeError: Failed to execute 'send' on 'WebSocket': 1 argument required, but only 0 present.
@ -200,19 +233,12 @@ class BareClient {
throw error;
sendData(args[0]);
};
}
if (options.urlHook)
options.urlHook(socket, remote);
else
Object.defineProperty(socket, 'url', {
get: () => remote.toString(),
configurable: true,
enumerable: true,
});
const getProtocol = () => fakeProtocol;
if (options.protocolHook)
options.protocolHook(socket, getProtocol);
else
Object.defineProperty(socket, 'protocol', {
get: getProtocol,
configurable: true,
@ -242,7 +268,7 @@ class BareClient {
}
let switcher = findSwitcher();
if (!switcher.active)
throw "invalid";
throw "there are no bare clients";
const client = switcher.active;
if (!client.ready)
await client.init();
@ -253,7 +279,9 @@ class BareClient {
headers.Host = urlO.host;
let resp = await client.request(urlO, req.method, body, headers, req.signal);
let responseobj = new Response(statusEmpty.includes(resp.status) ? undefined : resp.body, {
headers: new Headers(resp.headers)
headers: new Headers(resp.headers),
status: resp.status,
statusText: resp.statusText,
});
responseobj.rawHeaders = resp.headers;
responseobj.rawResponse = new Response(resp.body);
@ -283,5 +311,5 @@ class BareClient {
}
}
export { BareClient, WebSocketFields, maxRedirects };
export { BareClient, SetSingletonTransport, SetTransport, WebSocketFields, BareClient as default, findSwitcher, maxRedirects };
//# sourceMappingURL=index.js.map

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View file

@ -45,7 +45,7 @@ const configs = [
output: {
file: `dist/bare.cjs`,
format: 'umd',
name: 'bare',
name: 'BareMux',
sourcemap: true,
exports: 'auto',
},

View file

@ -97,8 +97,8 @@ export class BareClient {
createWebSocket(
remote: string | URL,
protocols: string | string[] | undefined = [],
options: BareWebSocket.Options,
origin: string,
webSocketImpl: WebSocketImpl,
requestHeaders: BareHeaders,
): WebSocket {
let switcher = findSwitcher();
let client = switcher.active;
@ -133,7 +133,7 @@ export class BareClient {
);
let wsImpl = (options.webSocketImpl || WebSocket) as WebSocketImpl;
let wsImpl = (webSocketImpl || WebSocket) as WebSocketImpl;
const socket = new wsImpl("wss:null", protocols);
let fakeProtocol = '';
@ -148,26 +148,46 @@ export class BareClient {
initialErrorHappened = true;
}
});
let initialOnErrorHappenned = false;
// TODO socket onerror will be broken
requestHeaders['Host'] = (new URL(remote)).host;
// requestHeaders['Origin'] = origin;
requestHeaders['Pragma'] = 'no-cache';
requestHeaders['Cache-Control'] = 'no-cache';
requestHeaders['Upgrade'] = 'websocket';
// requestHeaders['User-Agent'] = navigator.userAgent;
requestHeaders['Connection'] = 'Upgrade';
const sendData = client.connect(
remote,
origin,
protocols,
requestHeaders,
(protocol: string) => {
fakeReadyState = WebSocketFields.OPEN;
fakeProtocol = protocol;
(socket as any).meta = {
headers: {
"sec-websocket-protocol": protocol,
}
}; // what the fuck is a meta
socket.dispatchEvent(new Event("open"));
},
(payload) => {
if (typeof payload === "string") {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
} else if (payload instanceof ArrayBuffer) {
Object.setPrototypeOf(payload, ArrayBuffer);
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
} else if (payload instanceof Blob) {
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
console.log(payload);
if ((payload as any).data) {
socket.dispatchEvent(new MessageEvent("message", { data: (payload as any).data }));
return;
}
socket.dispatchEvent(new MessageEvent("message", { data: payload }));
// if (typeof payload === "string") {
// } else if (payload instanceof ArrayBuffer) {
// Object.setPrototypeOf(payload, ArrayBuffer);
//
// socket.dispatchEvent(new MessageEvent("message", { data: payload }));
// } else if (payload instanceof Blob) {
// }
},
(code, reason) => {
fakeReadyState = WebSocketFields.CLOSED;
@ -195,13 +215,6 @@ export class BareClient {
// // user is expected to specify user-agent and origin
// // both are in spec
//
// requestHeaders['Host'] = (remote as URL).host;
// // requestHeaders['Origin'] = origin;
// requestHeaders['Pragma'] = 'no-cache';
// requestHeaders['Cache-Control'] = 'no-cache';
// requestHeaders['Upgrade'] = 'websocket';
// // requestHeaders['User-Agent'] = navigator.userAgent;
// requestHeaders['Connection'] = 'Upgrade';
//
// return requestHeaders;
// },
@ -227,8 +240,6 @@ export class BareClient {
: realReadyState;
};
if (options.readyStateHook) options.readyStateHook(socket, getReadyState);
else {
// we have to hook .readyState ourselves
Object.defineProperty(socket, 'readyState', {
@ -236,7 +247,6 @@ export class BareClient {
configurable: true,
enumerable: true,
});
}
/**
* @returns The error that should be thrown if send() were to be called on this socket according to the fake readyState value
@ -250,8 +260,6 @@ export class BareClient {
);
};
if (options.sendErrorHook) options.sendErrorHook(socket, getSendError);
else {
// we have to hook .send ourselves
// use ...args to avoid giving the number of args a quantity
// no arguments will trip the following error: TypeError: Failed to execute 'send' on 'WebSocket': 1 argument required, but only 0 present.
@ -261,10 +269,7 @@ export class BareClient {
if (error) throw error;
sendData(args[0] as any);
};
}
if (options.urlHook) options.urlHook(socket, remote);
else
Object.defineProperty(socket, 'url', {
get: () => remote.toString(),
configurable: true,
@ -273,8 +278,6 @@ export class BareClient {
const getProtocol = () => fakeProtocol;
if (options.protocolHook) options.protocolHook(socket, getProtocol);
else
Object.defineProperty(socket, 'protocol', {
get: getProtocol,
configurable: true,
@ -322,7 +325,7 @@ export class BareClient {
}
let switcher = findSwitcher();
if (!switcher.active) throw "invalid";
if (!switcher.active) throw "there are no bare clients";
const client = switcher.active;
if (!client.ready) await client.init();
@ -341,7 +344,9 @@ export class BareClient {
let responseobj: BareResponse & Partial<BareResponseFetch> = new Response(
statusEmpty.includes(resp.status) ? undefined : resp.body, {
headers: new Headers(resp.headers as HeadersInit)
headers: new Headers(resp.headers as HeadersInit),
status: resp.status,
statusText: resp.statusText,
}) as BareResponse;
responseobj.rawHeaders = resp.headers;
responseobj.rawResponse = new Response(resp.body);

View file

@ -20,6 +20,7 @@ export interface BareTransport {
url: URL,
origin: string,
protocols: string[],
requestHeaders: BareHeaders,
onopen: (protocol: string) => void,
onmessage: (data: Blob | ArrayBuffer | string) => void,
onclose: (code: number, reason: string) => void,

View file

@ -1,13 +1,8 @@
import { BareTransport } from "./BareTypes";
self.BCC_VERSION = "2.1.3";
self.BCC_VERSION = "3.0.2";
console.warn("BCC_VERSION: " + self.BCC_VERSION);
if (!("gTransports" in globalThis)) {
globalThis.gTransports = {};
}
declare global {
interface ServiceWorkerGlobalScope {
gSwitcher: Switcher;
@ -27,23 +22,48 @@ declare global {
}
class Switcher {
transports: Record<string, BareTransport> = {};
active: BareTransport | null = null;
channel = new BroadcastChannel("bare-mux");
constructor() {
this.channel.addEventListener("message", ({ data: { type, data } }) => {
console.log(type, data, "ServiceWorker" in globalThis);
switch (type) {
case "setremote":
// this.active = new RemoteClient
break;
case "set":
const { name, config } = data;
this.active = new ((0, eval)(name))(...config);
break;
}
});
}
}
export function findSwitcher(): Switcher {
if (globalThis.gSwitcher) return globalThis.gSwitcher;
if ("ServiceWorkerGlobalScope" in globalThis) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
let _parent: any = window;
for (let i = 0; i < 20; i++) {
try {
parent = parent.parent;
if (parent && parent["gSwitcher"]) {
if (_parent == _parent.parent) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
_parent = _parent.parent;
if (_parent && _parent["gSwitcher"]) {
console.warn("found implementation on parent");
globalThis.gSwitcher = parent["gSwitcher"];
return parent["gSwitcher"];
globalThis.gSwitcher = _parent["gSwitcher"];
return _parent["gSwitcher"];
}
} catch (e) {
globalThis.gSwitcher = new Switcher;
return globalThis.gSwitcher;
}
@ -51,17 +71,16 @@ export function findSwitcher(): Switcher {
throw "unreachable";
}
findSwitcher();
export function AddTransport(name: string, client: BareTransport) {
export function SetTransport(name: string, ...config: any[]) {
let switcher = findSwitcher();
switcher.transports[name] = client;
if (!switcher.active)
switcher.active = switcher.transports[name];
switcher.active = new ((0, eval)(name))(...config);
switcher.channel.postMessage({ type: "set", data: { name, config } });
}
export function SetTransport(name: string) {
export function SetSingletonTransport(client: BareTransport) {
let switcher = findSwitcher();
switcher.active = switcher.transports[name];
switcher.active = client;
switcher.channel.postMessage({ type: "setremote" });
}

View file

@ -1,3 +1,5 @@
export * from './BareTypes';
export * from './BareClient';
export * from './Switcher';
export { BareClient as default } from './BareClient';
export { WebSocketFields } from "./snapshot";