--- title: "SQLite Runtime Resolution" --- # SQLite Runtime Resolution OmniRoute resolves its SQLite driver at startup through a 5-step fallback chain: 1. **Bundled `better-sqlite3`** (via `dependencies` in `package.json`) — fastest, native binary, installed by `npm install` when build tools are present. 2. **Runtime-installed `better-sqlite3`** (in `~/.omniroute/runtime/`) — installed lazily on first run **OR** by `scripts/build/postinstall.mjs → scripts/postinstall.mjs`. Validates native `.node` magic bytes (ELF / Mach-O / PE) before loading to guard against corrupt or wrong-platform binaries. 3. **`node:sqlite`** (Node ≥22.5 stdlib) — no native build needed; used when both better-sqlite3 paths fail. Limited feature set. 4. **`sql.js`** (WASM) — final fallback. Works everywhere but is slower and writes data on an interval rather than synchronously. ## Why this complexity? - **Windows EBUSY**: `npm install -g omniroute@latest` can fail if the previous version's `better_sqlite3.node` is locked by a running process. The runtime install in `~/.omniroute/runtime/` sidesteps the global npm cache. - **No build tools**: Some environments (corporate Windows without VS Build Tools, minimal Docker images) cannot compile `better-sqlite3`. The runtime installer resolves a pre-built binary from the npm registry; the fallback drivers ensure OmniRoute still boots even if that fails. - **Air-gapped systems**: If the npm registry is unreachable, `node:sqlite` or `sql.js` guarantee baseline functionality. ## Magic-byte validation Before loading a runtime-installed `.node` file, OmniRoute reads the first 8 bytes and matches against known platform magics: | Platform | Bytes (hex) | Label | | --------------------- | ------------- | ----------- | | Linux | `7F 45 4C 46` | `elf` | | macOS 64-bit BE | `FE ED FA CF` | `macho` | | macOS 64-bit LE | `CF FA ED FE` | `macho-le` | | macOS fat (universal) | `CA FE BA BE` | `macho-fat` | | Windows | `4D 5A` (MZ) | `pe` | A mismatched magic → file is ignored, fallback continues to the next step. ## Checking the active driver ```typescript import { getDriverInfo } from "@/lib/db/core"; const info = getDriverInfo(); // { source: "bundled" | "runtime" | "runtime-installed-now" | "node-sqlite" | "sql-js", // kind: "better-sqlite3" | "node-sqlite" | "sql-js" } ``` ## Manual control ```bash # Skip postinstall warm-up (for fast CI installs) OMNIROUTE_SKIP_POSTINSTALL=1 npm install -g omniroute # Force-reinstall runtime better-sqlite3 rm -rf ~/.omniroute/runtime omniroute # will reinstall on next start # Check what driver is active omniroute config db-info # (if CLI command exists) ``` ## Reference Implementation: - `bin/cli/runtime/magicBytes.mjs` — binary magic-byte validation helpers - `bin/cli/runtime/sqliteRuntime.mjs` — 5-step runtime resolver + lazy installer - `bin/cli/runtime/index.mjs` — startup orchestrator (`warmUpRuntimes()`) - `scripts/postinstall.mjs` — npm post-install hook (non-fatal warm-up) - `src/lib/db/core.ts` — `ensureDbInitialized()` / `getDriverInfo()` exports