feat(db): migrate from lowdb to SQLite with repos pattern
- Add modular DB layer (adapters, migrations, repos, helpers) - Replace localDb/usageDb/requestDetailsDb monoliths with repos - Add Tailscale tunnel integration & status check API - Add /api/cli-tools/all-statuses aggregated endpoint - Add settingsStore (Zustand) and mitm/dbReader - Add DB unit tests (benchmark, concurrent, migration, vs-lowdb)
This commit is contained in:
52
src/lib/db/driver.js
Normal file
52
src/lib/db/driver.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { ensureDirs, DATA_FILE } from "./paths.js";
|
||||
|
||||
// Use global to survive Next.js dev hot-reload (module state resets on reload)
|
||||
if (!global._dbAdapter) global._dbAdapter = { instance: null, initPromise: null, logged: false };
|
||||
const state = global._dbAdapter;
|
||||
|
||||
async function tryBetterSqlite() {
|
||||
try {
|
||||
const { createBetterSqliteAdapter } = await import("./adapters/betterSqliteAdapter.js");
|
||||
return createBetterSqliteAdapter(DATA_FILE);
|
||||
} catch (e) {
|
||||
console.warn(`[DB] better-sqlite3 unavailable: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function trySqlJs() {
|
||||
try {
|
||||
const { createSqlJsAdapter } = await import("./adapters/sqljsAdapter.js");
|
||||
return await createSqlJsAdapter(DATA_FILE);
|
||||
} catch (e) {
|
||||
console.warn(`[DB] sql.js unavailable: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function initAdapter() {
|
||||
ensureDirs();
|
||||
let adapter = await tryBetterSqlite();
|
||||
if (!adapter) adapter = await trySqlJs();
|
||||
if (!adapter) throw new Error("[DB] No SQLite driver available (better-sqlite3 + sql.js both failed)");
|
||||
|
||||
if (!state.logged) {
|
||||
console.log(`[DB] Driver: ${adapter.driver} | file: ${DATA_FILE}`);
|
||||
state.logged = true;
|
||||
}
|
||||
|
||||
const { runMigrationOnce } = await import("./migrate.js");
|
||||
await runMigrationOnce(adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
export async function getAdapter() {
|
||||
if (state.instance) return state.instance;
|
||||
if (!state.initPromise) state.initPromise = initAdapter().then((a) => { state.instance = a; return a; });
|
||||
return state.initPromise;
|
||||
}
|
||||
|
||||
export function getAdapterSync() {
|
||||
if (!state.instance) throw new Error("[DB] adapter not initialized — await getAdapter() first");
|
||||
return state.instance;
|
||||
}
|
||||
Reference in New Issue
Block a user