From 0431dd84e7f1a0f485561ee0c8bf37bc0396fb9b Mon Sep 17 00:00:00 2001 From: Jonathan Bailey <127773378+excessivechaos@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:52:06 -0700 Subject: [PATCH] fix(db): preserve native runtime drivers in standalone bundles (#10552) --- src/lib/db/adapters/driverFactory.ts | 3 +- src/lib/db/adapters/runtimeRequire.ts | 36 ++++++++++++++++++++ src/lib/db/omp.ts | 14 ++++---- tests/unit/db-adapters/driverFactory.test.ts | 8 +++++ 4 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/lib/db/adapters/runtimeRequire.ts diff --git a/src/lib/db/adapters/driverFactory.ts b/src/lib/db/adapters/driverFactory.ts index 6de67a37ca..d696d1388d 100644 --- a/src/lib/db/adapters/driverFactory.ts +++ b/src/lib/db/adapters/driverFactory.ts @@ -1,4 +1,4 @@ -import { createRequire } from "node:module"; +import { runtimeRequire as _require } from "./runtimeRequire"; import { existsSync } from "node:fs"; import { createBetterSqliteAdapter } from "./betterSqliteAdapter"; import { createBunSqliteAdapter, type BunSqliteDatabaseLike } from "./bunSqliteAdapter"; @@ -8,7 +8,6 @@ import { } from "./nodeSqliteShared"; import type { SqliteAdapter } from "./types"; -const _require = createRequire(import.meta.url); type DriverLoader = (moduleName: string) => unknown; diff --git a/src/lib/db/adapters/runtimeRequire.ts b/src/lib/db/adapters/runtimeRequire.ts new file mode 100644 index 0000000000..55c1571087 --- /dev/null +++ b/src/lib/db/adapters/runtimeRequire.ts @@ -0,0 +1,36 @@ +// src/lib/db/adapters/runtimeRequire.ts +/** + * Load optional database drivers from the runtime rather than bundling them. + * + * The standalone server is emitted as CommonJS chunks and externalizes the + * native database packages. Keep those requests as static `require()` calls so + * webpack preserves the external boundary. Development and tests run as ESM, + * where `require` is unavailable; the `createRequire(import.meta.url)` fallback + * handles those callers. + */ +import { createRequire } from "node:module"; + +declare const require: NodeRequire | undefined; + +function esmRuntimeRequire(specifier: string): unknown { + return createRequire(import.meta.url)(specifier); +} + +export function runtimeRequire(specifier: string): unknown { + if (typeof require === "function") { + switch (specifier) { + case "better-sqlite3": + return require("better-sqlite3"); + case "node:sqlite": + return require("node:sqlite"); + case "bun:sqlite": + return require("bun:sqlite"); + case "sql.js": + return require("sql.js"); + case "sqlite-vec": + return require("sqlite-vec"); + } + } + + return esmRuntimeRequire(specifier); +} diff --git a/src/lib/db/omp.ts b/src/lib/db/omp.ts index 34c6b071ea..35dff8ec3f 100644 --- a/src/lib/db/omp.ts +++ b/src/lib/db/omp.ts @@ -1,21 +1,19 @@ import os from "os"; import path from "path"; -import { createRequire } from "node:module"; +import { runtimeRequire as _require } from "./adapters/runtimeRequire"; -const _require = createRequire(import.meta.url); -function getDatabaseClass() { +type DatabaseConstructor = typeof import("better-sqlite3"); + +function getDatabaseClass(): DatabaseConstructor | null { try { if (process.versions.bun) { - return _require("bun:sqlite").Database; + return (_require("bun:sqlite") as { Database: DatabaseConstructor }).Database; } - return _require("better-sqlite3"); + return _require("better-sqlite3") as DatabaseConstructor; } catch { return null; } } -const Database = process.versions.bun - ? (_require("bun:sqlite").Database as typeof import("better-sqlite3")) - : (_require("better-sqlite3") as typeof import("better-sqlite3")); function databaseOptions(readonly = false) { return readonly ? { readonly: true } : { readwrite: true, create: true }; diff --git a/tests/unit/db-adapters/driverFactory.test.ts b/tests/unit/db-adapters/driverFactory.test.ts index a191bd8970..f5fc774e3f 100644 --- a/tests/unit/db-adapters/driverFactory.test.ts +++ b/tests/unit/db-adapters/driverFactory.test.ts @@ -4,6 +4,9 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { createRequire } from "node:module"; +import type * as NodePath from "node:path"; +import { runtimeRequire } from "../../../src/lib/db/adapters/runtimeRequire.ts"; + const { createSyncDriverFactory, @@ -33,7 +36,12 @@ function createTempDatabasePath(t: TestContext) { return databasePath; } + describe("driverFactory", () => { + test("runtimeRequire loads Node built-ins outside webpack", () => { + const nodePath = runtimeRequire("node:path") as typeof NodePath; + assert.equal(nodePath.basename("/tmp/omniroute.sqlite"), "omniroute.sqlite"); + }); test("tryOpenSync retorna adapter síncrono ou null", () => { const adapter = tryOpenSync(":memory:"); if (adapter) {