import { readerFromStreamReader } from "https://deno.land/std@0.223.0/io/mod.ts";
import { httpClient } from "https://esm.town/v/pomdtr/http_client";
import { disposable } from "https://esm.town/v/postpostscript/disposable";
export const workerURL = new URL(import.meta.url);
workerURL.searchParams.set("worker", "1");
export async function fetchWorker(opts: {
url: string;
handler?: string;
}) {
const worker = disposable(
new Worker(workerURL.toString(), {
type: "module",
}),
(worker) => worker.terminate(),
);
const { resolve, promise } = Promise.withResolvers();
worker.onmessage = resolve;
worker.postMessage({
code: "setup",
...opts,
});
await promise;
const resolvers: {
[id: string]: (value: Response) => void;
} = {};
worker.onmessage = (e) => {
const {
id,
response: {
status,
headers,
body,
},
} = e.data;
const response = new Response(body, {
status,
headers,
});
resolvers[id](response);
};
return {
fetch: async (input: URL | RequestInfo, init?: RequestInit) => {
const req = new Request(input, init);
const body: ArrayBuffer | null = req.body
? await req.blob().then(blob => blob.arrayBuffer())
: null;
const id = crypto.randomUUID();
const { resolve, promise } = Promise.withResolvers<Response>();
resolvers[id] = resolve;
worker.postMessage({
code: "request",
id,
request: {
url: req.url,
body,
init: {
method: req.method,
headers: Object.fromEntries(req.headers.entries()),
},
},
});
return promise;
},
instance: worker,
terminate: () => worker.terminate(),
[Symbol.dispose]: () => worker.terminate(),
};
}
export function setupWorker() {
let handler: (req: Request) => Promise<Response>;
self.onmessage = async (e) => {
if (e.data.code === "setup") {
const module = await import(e.data.url);
handler = module[e.data.handler ?? "default"];
self.postMessage({
code: "ready",
});
}
if (e.data.code === "request") {
const {
id,