import { init, Renderer } from "takumi-js/wasm/no-init"; import type { WorkerRequest, WorkerResult } from "./types"; import { renderExport } from "./render"; let rendererPromise: Promise | undefined; async function getRenderer(origin: string) { rendererPromise ??= (async () => { const response = await fetch(new URL("/takumi.wasm", origin), { signal: AbortSignal.timeout(15000), }); if (!response.ok) throw new Error("Unable to load image renderer"); await init({ module_or_path: await response.arrayBuffer() }); const renderer = new Renderer(); try { const fonts = await Promise.all( [ { name: "Anuphan", path: "/Anuphan.ttf" }, { name: "Genshin Overview", path: "/zh-cn.ttf" }, { name: "Kanit Overview", path: "/Kanit-SemiBold.ttf", weight: 600, style: "normal" as const, }, { name: "Kanit Poster", path: "/Kanit-ExtraBoldItalic.ttf", weight: 800, style: "italic" as const, }, ].map(async ({ path, ...descriptor }) => { const font = await fetch(new URL(path, origin), { signal: AbortSignal.timeout(15000), }); if (!font.ok) throw new Error("Unable to load export fonts"); return { ...descriptor, data: new Uint8Array(await font.arrayBuffer()), }; }), ); for (const font of fonts) await renderer.registerFont(font); return renderer; } catch (error) { renderer.free(); throw error; } })().catch((error) => { rendererPromise = undefined; throw error; }); return rendererPromise; } let queue = Promise.resolve(); self.onmessage = ({ data }: MessageEvent) => { queue = queue.then(async () => { try { const renderer = await getRenderer(data.origin); const image = await renderExport(renderer, data.request, data.origin); const bytes = image.buffer as ArrayBuffer; self.postMessage({ id: data.id, bytes } satisfies WorkerResult, { transfer: [bytes], }); } catch (error) { self.postMessage({ id: data.id, error: error instanceof Error ? error.message : "Image export failed", } satisfies WorkerResult); } }); };