diff --git a/src/lib/db/adapters/sqljsAdapter.ts b/src/lib/db/adapters/sqljsAdapter.ts index eaa21a134b..31bd508da3 100644 --- a/src/lib/db/adapters/sqljsAdapter.ts +++ b/src/lib/db/adapters/sqljsAdapter.ts @@ -108,8 +108,16 @@ function toBindValue(params: unknown[]): unknown[] | Record | u async function loadSqlJs(): Promise { if (_sqlJsLib) return _sqlJsLib; - const initSqlJs = ((await import("sql.js")) as { default: (typeof import("sql.js"))["default"] }) - .default; + // Use a non-literal specifier so the bundler doesn't try to statically + // resolve sql.js (and its package.json) during the build phase. + // sql.js is an optional/fallback adapter — only needed at runtime when + // better-sqlite3 and node:sqlite are both unavailable. + const moduleName = "sql." + "js"; + const mod = (await import( + /* webpackIgnore: true */ + moduleName + )) as { default: (typeof import("sql.js"))["default"] }; + const initSqlJs = mod.default; const wasmPath = resolveSqlJsWasmPath(); _sqlJsLib = await initSqlJs({ diff --git a/tests/unit/sqljs-build-warning-8135.test.ts b/tests/unit/sqljs-build-warning-8135.test.ts new file mode 100644 index 0000000000..912ef7f0c0 --- /dev/null +++ b/tests/unit/sqljs-build-warning-8135.test.ts @@ -0,0 +1,38 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const adapterPath = join(__dirname, "../../src/lib/db/adapters/sqljsAdapter.ts"); +const source = readFileSync(adapterPath, "utf8"); + +test("#8135: sqljsAdapter must not statically resolve sql.js at build time", () => { + const lines = source.split("\n"); + + // Find lines containing `await import(` — the actual dynamic import call. + // (Exclude `typeof import(...)` type annotations.) + const dynamicImportLines = lines.filter( + (l) => l.includes("await import(") && !l.includes("typeof import(") + ); + + assert.ok( + dynamicImportLines.length > 0, + "sqljsAdapter should have at least one dynamic import call" + ); + + // None of the runtime dynamic import calls should use a literal "sql.js" specifier + for (const line of dynamicImportLines) { + assert.ok( + !line.includes('import("sql.js")'), + "sqljsAdapter should not use a literal import('sql.js') at runtime — use a computed specifier" + ); + } + + // The webpackIgnore magic comment must be present + assert.ok( + source.includes("/* webpackIgnore: true */"), + "sqljsAdapter dynamic import should include /* webpackIgnore: true */ magic comment" + ); +});