1
0
silverbullet/plugos/sqlite/async_sqlite.ts

71 lines
1.9 KiB
TypeScript

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<string, any>): Promise<any> {
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<void> {
return this.request({ type: "init", dbPath: this.dbPath });
}
execute(query: string, ...params: any[]): Promise<number> {
return this.request({ type: "execute", query, params });
}
query(query: string, ...params: any[]): Promise<any[]> {
return this.request({ type: "query", query, params });
}
stop() {
this.worker.terminate();
}
}