Spaces:
Runtime error
Runtime error
File size: 4,109 Bytes
cd8bd0a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
import { homedir } from "node:os";
import { execSync } from "node:child_process";
import { pathToFileURL } from "node:url";
import { validateBinaryMagic, platformBinaryLabel } from "./magicBytes.mjs";
const RUNTIME_DIR = join(homedir(), ".omniroute", "runtime");
const BETTER_SQLITE3_VERSION = "better-sqlite3@^12.10.1";
let resolvedCached = null;
/**
* Resolves a SQLite driver through a 5-step fallback chain:
* 1. Bundled better-sqlite3 (optionalDependency)
* 2. Runtime-installed better-sqlite3 in ~/.omniroute/runtime/
* 3. Lazy npm install into runtime dir
* 4. node:sqlite (Node ≥22.5 stdlib)
* 5. sql.js (bundled WASM, always available)
*
* Returns { driver, source } where source is one of:
* "bundled" | "runtime" | "runtime-installed-now" | "node-sqlite" | "sql-js"
*/
export async function loadSqliteRuntime() {
if (resolvedCached) return resolvedCached;
const bundled = await tryLoadBundled();
if (bundled) {
resolvedCached = { driver: bundled, source: "bundled" };
return resolvedCached;
}
const runtimeInstalled = await tryLoadRuntimeInstalled();
if (runtimeInstalled) {
resolvedCached = { driver: runtimeInstalled, source: "runtime" };
return resolvedCached;
}
try {
await installRuntime();
const after = await tryLoadRuntimeInstalled();
if (after) {
resolvedCached = { driver: after, source: "runtime-installed-now" };
return resolvedCached;
}
} catch (err) {
console.warn(`[omniroute] runtime install failed: ${err.message}`);
}
try {
const nodeSqlite = await import("node:sqlite");
resolvedCached = {
driver: { kind: "node-sqlite", DatabaseSync: nodeSqlite.DatabaseSync },
source: "node-sqlite",
};
return resolvedCached;
} catch {}
const sqljs = await import("sql.js");
resolvedCached = {
driver: { kind: "sql-js", initSqlJs: sqljs.default ?? sqljs.initSqlJs },
source: "sql-js",
};
return resolvedCached;
}
async function tryLoadBundled() {
try {
const mod = await import("better-sqlite3");
return { kind: "better-sqlite3", Database: mod.default ?? mod };
} catch {
return null;
}
}
async function tryLoadRuntimeInstalled() {
const runtimeNodeModules = resolve(RUNTIME_DIR, "node_modules");
const pkgRoot = resolve(runtimeNodeModules, "better-sqlite3");
if (!pkgRoot.startsWith(`${runtimeNodeModules}/`)) return null;
if (!existsSync(join(pkgRoot, "package.json"))) return null;
const buildDir = join(pkgRoot, "build", "Release");
if (existsSync(buildDir)) {
const nodeFile = readdirSync(buildDir).find((f) => f.endsWith(".node"));
if (nodeFile) {
const magic = validateBinaryMagic(join(buildDir, nodeFile));
const expected = platformBinaryLabel();
if (!magic || (magic !== expected && magic !== "macho-le" && magic !== "macho-fat")) {
console.warn(
`[omniroute] runtime sqlite binary magic mismatch (${magic} ≠ ${expected}) — skipping`
);
return null;
}
}
}
try {
const mod = await import(/* webpackIgnore: true */ pathToFileURL(pkgRoot).href);
return { kind: "better-sqlite3", Database: mod.default ?? mod };
} catch {
return null;
}
}
function ensureRuntimeDir() {
if (!existsSync(RUNTIME_DIR)) mkdirSync(RUNTIME_DIR, { recursive: true });
const pkg = join(RUNTIME_DIR, "package.json");
if (!existsSync(pkg)) {
writeFileSync(
pkg,
JSON.stringify({ name: "omniroute-runtime", private: true, type: "commonjs" }),
"utf-8"
);
}
}
async function installRuntime() {
ensureRuntimeDir();
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
execSync(
`${npm} install --prefix "${RUNTIME_DIR}" ${BETTER_SQLITE3_VERSION} --no-audit --no-fund --silent`,
{ stdio: ["ignore", "ignore", "pipe"], timeout: 180_000 }
);
}
/** Clears the cached resolved driver (for testing). */
export function clearRuntimeCache() {
resolvedCached = null;
}
|