import { BareMuxConnection } from "@mercuryworkshop/bare-mux";
import { defaultStore } from "./storage";
import { SettingsVals, WispServers } from "./values";
import { log } from "./index";
const createScript = (src: string, defer?: boolean): HTMLScriptElement => {
const script = document.createElement('script') as HTMLScriptElement;
script.src = src;
if (defer) script.defer = defer;
return script;
};
function* createProxyScripts() {
const uv = createScript("/uv/uv.bundle.js", true);
yield uv;
const uvConfig = createScript("/uv/uv.config.js", true);
yield uvConfig;
const sj = createScript("/scram/scramjet.all.js", true);
yield sj;
};
const checkProxyScripts = (): Promise<void> => {
return new Promise((resolve) => {
const checkScript = setInterval(() => {
if (typeof __uv$config !== "undefined" && typeof $scramjetLoadController !== "undefined") {
clearInterval(checkScript);
resolve();
}
}, 100);
});
};
const createBareMuxConn = (worker: string): Promise<BareMuxConnection> => {
return new Promise<BareMuxConnection>((resolve) => {
const conn = new BareMuxConnection(worker);
resolve(conn);
});
};
const setTransport = (conn: BareMuxConnection, transport?: "libcurl" | "epoxy"): Promise<void> => {
const server = defaultStore.getVal(SettingsVals.proxy.wispServer);
return new Promise((resolve) => {
log({ type: 'info', bg: false, prefix: false }, `Set transport: ${transport ? transport : "libcurl"}`);
log({ type: 'info', bg: false, prefix: false }, `Set wisp server at: ${server ? WispServers[server]: WispServers.default }`);
if (transport === "epoxy") return resolve(conn.setTransport("/epoxy/index.mjs", [ { wisp: server ? WispServers[server] : WispServers.default }]));
if (transport === "libcurl") return resolve(conn.setTransport("/libcurl/index.mjs", [ { wisp: server ? WispServers[server] : WispServers.default }]));
});
};
type SWInit = {
serviceWorker: ServiceWorkerRegistration;
sj: ScramjetController;
bareMuxConn: BareMuxConnection;
}
class SW {
#init!: SWInit;
#ready: boolean = false;
static #instances = new Set();
constructor(conn: BareMuxConnection) {
SW.#instances.add(this);
const sj = (): ScramjetController => {
const { ScramjetController } = $scramjetLoadController();
const sj = new ScramjetController({
prefix: '/~/scramjet',
files: {
wasm: "/scram/scramjet.wasm.wasm",
all: "/scram/scramjet.all.js",
sync: "/scram/scramjet.sync.js"
},
flags: {
rewriterLogs: false
}
});
return sj;
}
if ("serviceWorker" in navigator) {
(async () => { await navigator.serviceWorker.getRegistrations() })();
const scram = sj();
(async () => await scram.init())();
navigator.serviceWorker.ready.then(async (reg) => {
log({ type: 'info', prefix: true, bg: false }, 'ServiceWorker ready and active!');
this.#init = { serviceWorker: reg, sj: scram, bareMuxConn: conn };
this.#ready = true;
});
navigator.serviceWorker.register("/sw.js", { scope: '/' });
}
else {
throw new Error('Your browser is not supported! This website uses Service Workers heavily.');
}
}
static *getInstances() {
for (const value of SW.#instances.keys()) {
yield value as SW;
}
}
setSWInfo(items: SWInit): void {
this.#init = { serviceWorker: items.serviceWorker, sj: items.sj, bareMuxConn: items.bareMuxConn };
this.#ready = true;
}
getSWInfo(): Promise<SWInit> {
return new Promise((resolve) => {
const checkState = setInterval(() => {
if (this.#ready) {
clearInterval(checkState);
resolve(this.#init);
}
}, 100);
});
}
}
export { createScript, createProxyScripts, checkProxyScripts, createBareMuxConn, setTransport, SW };