fix(desktop): hide bun:sqlite import from Node.js/Electron ESM loader
Uses new Function() to prevent the static ESM loader from seeing the bun: protocol import at parse time. In Electron/Node.js, the import() call is evaluated at runtime and gracefully returns null when bun:sqlite is unavailable. Fixes #3829, likely fixes #3762
This commit is contained in:
@@ -13,7 +13,9 @@ describe("scheduleDeferredModelOverride bun:sqlite unavailable", () => {
|
|||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(hasStaticBunSqliteImport).toBe(false)
|
expect(hasStaticBunSqliteImport).toBe(false)
|
||||||
expect(source).toContain('await import("bun:sqlite").catch(() => null)')
|
// new Function() hides the bun: import from Node.js/Electron static ESM loader
|
||||||
|
expect(source).toContain("new Function(\"return import('bun:sqlite')\")")
|
||||||
|
expect(source).toContain("typeof globalThis.Bun === \"undefined\"")
|
||||||
expect(source).toContain("bun:sqlite unavailable")
|
expect(source).toContain("bun:sqlite unavailable")
|
||||||
expect(source).toContain("return")
|
expect(source).toContain("return")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,24 @@ import { log } from "../shared"
|
|||||||
|
|
||||||
type BunDatabase = import("bun:sqlite").Database
|
type BunDatabase = import("bun:sqlite").Database
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely import bun:sqlite only when running in Bun runtime.
|
||||||
|
* Uses new Function() to hide the import from Node.js/Electron's static parser,
|
||||||
|
* which would fail on bun: protocol resolution before .catch() could run.
|
||||||
|
*/
|
||||||
|
async function importBunSqlite(): Promise<typeof import("bun:sqlite") | null> {
|
||||||
|
if (typeof globalThis.Bun === "undefined") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// new Function() prevents Node.js ESM loader from seeing the bun: import at parse time
|
||||||
|
const dynamicImport = new Function("return import('bun:sqlite')") as () => Promise<typeof import("bun:sqlite")>
|
||||||
|
return await dynamicImport()
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getDbPath(): string {
|
function getDbPath(): string {
|
||||||
return join(getDataDir(), "opencode", "opencode.db")
|
return join(getDataDir(), "opencode", "opencode.db")
|
||||||
}
|
}
|
||||||
@@ -114,7 +132,7 @@ export function scheduleDeferredModelOverride(
|
|||||||
variant?: string,
|
variant?: string,
|
||||||
): void {
|
): void {
|
||||||
queueMicrotask(async () => {
|
queueMicrotask(async () => {
|
||||||
const sqliteModule = await import("bun:sqlite").catch(() => null)
|
const sqliteModule = await importBunSqlite()
|
||||||
const Database = sqliteModule?.Database
|
const Database = sqliteModule?.Database
|
||||||
if (typeof Database !== "function") {
|
if (typeof Database !== "function") {
|
||||||
log("[ultrawork-db-override] bun:sqlite unavailable, skipping deferred override", { messageId })
|
log("[ultrawork-db-override] bun:sqlite unavailable, skipping deferred override", { messageId })
|
||||||
@@ -147,4 +165,4 @@ export function scheduleDeferredModelOverride(
|
|||||||
db.close()
|
db.close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user