import { describe, it, beforeEach, afterEach, after } from "node:test"; import assert from "node:assert/strict"; import path from "node:path"; import fs from "node:fs"; import os from "node:os"; import Database from "better-sqlite3"; const fileTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "omni-dbvm-test-")); const moduleDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "omni-dbvm-module-")); process.env.DATA_DIR = moduleDataDir; const coreDb = await import("../../src/lib/db/core.ts"); const versionManagerDb = await import("../../src/lib/db/versionManager.ts"); const SCHEMA = ` CREATE TABLE IF NOT EXISTS version_manager ( id INTEGER PRIMARY KEY AUTOINCREMENT, tool TEXT NOT NULL UNIQUE, current_version TEXT, installed_version TEXT, pinned_version TEXT, binary_path TEXT, status TEXT NOT NULL DEFAULT 'not_installed', pid INTEGER, port INTEGER DEFAULT 8317, api_key TEXT, management_key TEXT, auto_update INTEGER NOT NULL DEFAULT 1, auto_start INTEGER NOT NULL DEFAULT 0, last_health_check TEXT, last_update_check TEXT, health_status TEXT DEFAULT 'unknown', config_overrides TEXT, error_message TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); `; let testDb; let testDbPath; beforeEach(() => { testDbPath = path.join(fileTmpDir, `test-${Date.now()}.db`); testDb = new Database(testDbPath); testDb.exec(SCHEMA); }); afterEach(() => { testDb.close(); try { fs.unlinkSync(testDbPath); } catch {} }); after(() => { if (fs.existsSync(fileTmpDir)) fs.rmSync(fileTmpDir, { recursive: true, force: true }); }); async function resetModuleStorage() { coreDb.resetDbInstance(); fs.rmSync(moduleDataDir, { recursive: true, force: true }); fs.mkdirSync(moduleDataDir, { recursive: true }); } function upsertTool(db, data) { db.prepare( ` INSERT INTO version_manager ( tool, current_version, installed_version, pinned_version, binary_path, status, pid, port, api_key, management_key, auto_update, auto_start, health_status, config_overrides, error_message, created_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now')) ON CONFLICT(tool) DO UPDATE SET current_version = excluded.current_version, installed_version = excluded.installed_version, pinned_version = excluded.pinned_version, binary_path = excluded.binary_path, status = excluded.status, pid = excluded.pid, port = excluded.port, api_key = excluded.api_key, management_key = excluded.management_key, auto_update = excluded.auto_update, auto_start = excluded.auto_start, health_status = excluded.health_status, config_overrides = excluded.config_overrides, error_message = excluded.error_message, updated_at = datetime('now') ` ).run( data.tool, data.currentVersion ?? null, data.installedVersion ?? null, data.pinnedVersion ?? null, data.binaryPath ?? null, data.status ?? "not_installed", data.pid ?? null, data.port ?? 8317, data.apiKey ?? null, data.managementKey ?? null, data.autoUpdate !== undefined ? (data.autoUpdate ? 1 : 0) : 1, data.autoStart !== undefined ? (data.autoStart ? 1 : 0) : 0, data.healthStatus ?? "unknown", data.configOverrides !== undefined ? data.configOverrides ? JSON.stringify(data.configOverrides) : null : null, data.errorMessage ?? null ); return db.prepare("SELECT * FROM version_manager WHERE tool = ?").get(data.tool); } function parseConfigOverrides(value) { if (!value || typeof value !== "string" || value.trim() === "") return null; try { const parsed = JSON.parse(value); return typeof parsed === "object" && parsed !== null ? parsed : null; } catch { return null; } } function toTool(row) { if (!row) return null; return { id: row.id, tool: row.tool, currentVersion: row.current_version, installedVersion: row.installed_version, pinnedVersion: row.pinned_version, binaryPath: row.binary_path, status: row.status, pid: row.pid, port: row.port, apiKey: row.api_key, managementKey: row.management_key, autoUpdate: row.auto_update === 1, autoStart: row.auto_start === 1, lastHealthCheck: row.last_health_check, lastUpdateCheck: row.last_update_check, healthStatus: row.health_status, configOverrides: parseConfigOverrides(row.config_overrides), errorMessage: row.error_message, createdAt: row.created_at, updatedAt: row.updated_at, }; } describe("db/versionManager (logic)", () => { describe("upsertVersionManagerTool", () => { it("should insert a new tool and read it back", () => { const tool = toTool( upsertTool(testDb, { tool: "cliproxyapi", installedVersion: "6.9.7", binaryPath: "/tmp/bin/cliproxyapi", status: "installed", }) ); assert.equal(tool.tool, "cliproxyapi"); assert.equal(tool.installedVersion, "6.9.7"); assert.equal(tool.binaryPath, "/tmp/bin/cliproxyapi"); assert.equal(tool.status, "installed"); assert.equal(tool.port, 8317); assert.equal(tool.autoUpdate, true); assert.equal(tool.autoStart, false); assert.equal(tool.healthStatus, "unknown"); assert.ok(tool.id > 0); }); it("should update on conflict (upsert)", () => { upsertTool(testDb, { tool: "test-tool", status: "installed" }); const tool = toTool( upsertTool(testDb, { tool: "test-tool", installedVersion: "7.0.0", status: "running" }) ); assert.equal(tool.installedVersion, "7.0.0"); assert.equal(tool.status, "running"); }); it("should store boolean fields as 0/1", () => { const tool = toTool( upsertTool(testDb, { tool: "bool-test", autoUpdate: false, autoStart: true }) ); assert.equal(tool.autoUpdate, false); assert.equal(tool.autoStart, true); }); it("should store config overrides as JSON", () => { const tool = toTool(upsertTool(testDb, { tool: "cfg", configOverrides: { port: 9999 } })); assert.deepEqual(tool.configOverrides, { port: 9999 }); }); it("should handle null config overrides", () => { const tool = toTool(upsertTool(testDb, { tool: "null-cfg" })); assert.equal(tool.configOverrides, null); }); it("should handle pid and error message", () => { const tool = toTool( upsertTool(testDb, { tool: "pid-test", pid: 12345, errorMessage: "err" }) ); assert.equal(tool.pid, 12345); assert.equal(tool.errorMessage, "err"); }); }); describe("getVersionManagerTool", () => { it("should return null for non-existent tool", () => { assert.equal( toTool(testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("ghost")), null ); }); it("should return tool by name", () => { upsertTool(testDb, { tool: "findme", installedVersion: "1.0.0" }); const tool = toTool( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("findme") ); assert.equal(tool.installedVersion, "1.0.0"); }); }); describe("getVersionManagerStatus", () => { it("should return all tools", () => { upsertTool(testDb, { tool: "a" }); upsertTool(testDb, { tool: "b" }); assert.equal(testDb.prepare("SELECT * FROM version_manager").all().length, 2); }); it("should return empty when no tools", () => { assert.equal(testDb.prepare("SELECT * FROM version_manager").all().length, 0); }); }); describe("updateVersionManagerTool (partial)", () => { it("should update pinnedVersion and autoUpdate", () => { upsertTool(testDb, { tool: "upd", status: "installed" }); testDb .prepare( "UPDATE version_manager SET pinned_version = ?, auto_update = ?, updated_at = datetime('now') WHERE tool = ?" ) .run("6.8.0", 0, "upd"); const tool = toTool( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("upd") ); assert.equal(tool.pinnedVersion, "6.8.0"); assert.equal(tool.autoUpdate, false); assert.equal(tool.status, "installed"); }); it("should set fields to null", () => { upsertTool(testDb, { tool: "nulls", installedVersion: "1.0.0", pid: 42 }); testDb .prepare("UPDATE version_manager SET installed_version = NULL, pid = NULL WHERE tool = ?") .run("nulls"); const tool = toTool( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("nulls") ); assert.equal(tool.installedVersion, null); assert.equal(tool.pid, null); }); }); describe("deleteVersionManagerTool", () => { it("should delete existing tool", () => { upsertTool(testDb, { tool: "del" }); assert.equal( testDb.prepare("DELETE FROM version_manager WHERE tool = ?").run("del").changes, 1 ); assert.equal( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("del"), undefined ); }); it("should return 0 changes for non-existent", () => { assert.equal( testDb.prepare("DELETE FROM version_manager WHERE tool = ?").run("ghost").changes, 0 ); }); }); describe("updateToolHealth", () => { it("should update health_status and last_health_check", () => { upsertTool(testDb, { tool: "h" }); const r = testDb .prepare( "UPDATE version_manager SET health_status = ?, last_health_check = datetime('now') WHERE tool = ?" ) .run("healthy", "h"); assert.equal(r.changes, 1); const tool = toTool(testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("h")); assert.equal(tool.healthStatus, "healthy"); assert.ok(tool.lastHealthCheck); }); it("should return 0 changes for non-existent", () => { assert.equal( testDb .prepare("UPDATE version_manager SET health_status = ? WHERE tool = ?") .run("healthy", "ghost").changes, 0 ); }); }); describe("updateToolVersion", () => { it("should update current_version", () => { upsertTool(testDb, { tool: "v1" }); testDb .prepare("UPDATE version_manager SET current_version = ? WHERE tool = ?") .run("7.0.0", "v1"); assert.equal( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("v1").current_version, "7.0.0" ); }); it("should update installed_version", () => { upsertTool(testDb, { tool: "v2" }); testDb .prepare("UPDATE version_manager SET installed_version = ? WHERE tool = ?") .run("7.0.0", "v2"); assert.equal( testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("v2").installed_version, "7.0.0" ); }); }); describe("setToolStatus", () => { it("should update status with pid", () => { upsertTool(testDb, { tool: "s1" }); testDb .prepare("UPDATE version_manager SET status = ?, pid = ?, error_message = ? WHERE tool = ?") .run("running", 9999, "ok", "s1"); const row = testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("s1"); assert.equal(row.status, "running"); assert.equal(row.pid, 9999); assert.equal(row.error_message, "ok"); }); it("should update status without pid", () => { upsertTool(testDb, { tool: "s2" }); testDb .prepare("UPDATE version_manager SET status = ?, error_message = ? WHERE tool = ?") .run("error", "crashed", "s2"); const row = testDb.prepare("SELECT * FROM version_manager WHERE tool = ?").get("s2"); assert.equal(row.status, "error"); }); it("should return 0 for non-existent", () => { assert.equal( testDb .prepare("UPDATE version_manager SET status = ? WHERE tool = ?") .run("running", "ghost").changes, 0 ); }); }); describe("parseConfigOverrides", () => { it("should parse valid JSON", () => { assert.deepEqual(parseConfigOverrides('{"key":"val"}'), { key: "val" }); }); it("should return null for invalid JSON", () => { assert.equal(parseConfigOverrides("not-json"), null); assert.equal(parseConfigOverrides(""), null); assert.equal(parseConfigOverrides(null), null); assert.equal(parseConfigOverrides("123"), null); }); }); }); describe("db/versionManager (module coverage)", () => { beforeEach(async () => { await resetModuleStorage(); }); after(async () => { coreDb.resetDbInstance(); fs.rmSync(moduleDataDir, { recursive: true, force: true }); }); it("round-trips inserts, updates and status listings through the production module", async () => { const inserted = await versionManagerDb.upsertVersionManagerTool({ tool: "cliproxyapi", installedVersion: "6.9.7", binaryPath: "/tmp/cliproxyapi", status: "installed", autoUpdate: false, autoStart: true, configOverrides: { port: 9999 }, }); assert.equal(inserted.tool, "cliproxyapi"); assert.equal(inserted.autoUpdate, false); assert.equal(inserted.autoStart, true); assert.deepEqual(inserted.configOverrides, { port: 9999 }); const updated = await versionManagerDb.updateVersionManagerTool("cliproxyapi", { installedVersion: "7.0.0", configOverrides: { port: 8317, host: "127.0.0.1" }, apiKey: null, ignoredField: "noop", }); assert.equal(updated.installedVersion, "7.0.0"); assert.deepEqual(updated.configOverrides, { port: 8317, host: "127.0.0.1" }); const status = await versionManagerDb.getVersionManagerStatus(); const cliproxy = status.find((row) => row.tool === "cliproxyapi"); assert.ok(cliproxy, "expected cliproxyapi entry in status listing"); assert.equal(cliproxy.tool, "cliproxyapi"); }); it("parses invalid config overrides defensively and returns null for missing updates", async () => { const db = coreDb.getDbInstance(); db.prepare( ` INSERT INTO version_manager (tool, status, config_overrides, created_at, updated_at) VALUES (?, ?, ?, datetime('now'), datetime('now')) ` ).run("broken-tool", "installed", "{not-json"); const loaded = await versionManagerDb.getVersionManagerTool("broken-tool"); assert.equal(loaded.configOverrides, null); assert.equal( await versionManagerDb.updateVersionManagerTool("ghost", { status: "running" }), null ); }); it("updates health/version/status fields and deletes tools", async () => { await versionManagerDb.upsertVersionManagerTool({ tool: "managed-tool", status: "installed", }); assert.equal(await versionManagerDb.updateToolHealth("managed-tool", "healthy"), true); assert.equal( await versionManagerDb.updateToolVersion("managed-tool", "current_version", "1.2.3"), true ); assert.equal( await versionManagerDb.updateToolVersion("managed-tool", "installed_version", "1.2.0"), true ); assert.equal(await versionManagerDb.setToolStatus("managed-tool", "running", 4321, "ok"), true); assert.equal(await versionManagerDb.setToolStatus("managed-tool", "error"), true); const stored = await versionManagerDb.getVersionManagerTool("managed-tool"); assert.equal(stored.currentVersion, "1.2.3"); assert.equal(stored.installedVersion, "1.2.0"); assert.equal(stored.status, "error"); assert.equal(await versionManagerDb.updateToolHealth("ghost", "healthy"), false); assert.equal(await versionManagerDb.setToolStatus("ghost", "running"), false); assert.equal(await versionManagerDb.deleteVersionManagerTool("managed-tool"), true); assert.equal(await versionManagerDb.deleteVersionManagerTool("managed-tool"), false); }); });