import { AssetBundle } from "../asset_bundle/bundle.ts"; import workerBundleJson from "./worker_bundle.json" assert { type: "json" }; const workerBundle = new AssetBundle(workerBundleJson); export class AsyncSQLite { worker: Worker; requestId = 0; outstandingRequests = new Map< number, { resolve: (val: any) => void; reject: (error: Error) => void } >(); constructor(readonly dbPath: string) { const workerHref = URL.createObjectURL( new Blob([ workerBundle.readFileSync("worker.js"), ], { type: "application/javascript", }), ); this.worker = new Worker( workerHref, { type: "module", }, ); this.worker.addEventListener("message", (event: MessageEvent) => { const { data } = event; // console.log("Got data back", data); const { id, result, error } = data; const req = this.outstandingRequests.get(id); if (!req) { console.error("Invalid request id", id); return; } if (result !== undefined) { req.resolve(result); } else if (error) { req.reject(new Error(error)); } this.outstandingRequests.delete(id); }); } private request(message: Record): Promise { this.requestId++; return new Promise((resolve, reject) => { this.outstandingRequests.set(this.requestId, { resolve, reject }); // console.log("Sending request", message); this.worker.postMessage({ ...message, id: this.requestId }); }); } init(): Promise { return this.request({ type: "init", dbPath: this.dbPath }); } execute(query: string, ...params: any[]): Promise { return this.request({ type: "execute", query, params }); } query(query: string, ...params: any[]): Promise { return this.request({ type: "query", query, params }); } stop() { this.worker.terminate(); } }