import Database from "better-sqlite3"; import path from "node:path"; type Row = Record; let _db: Database.Database | null = null; function dbPath(): string { const raw = process.env.ALPACLAUDIA_DB || "../data/alpaclaudia.db"; return path.isAbsolute(raw) ? raw : path.resolve(process.cwd(), raw); } function getDb(): Database.Database | null { if (_db) return _db; try { _db = new Database(dbPath(), { readonly: true, fileMustExist: true }); return _db; } catch { return null; } } export function recentTicks(limit = 300): Row[] { const db = getDb(); if (!db) return []; return db .prepare(`SELECT id, ts, equity, cash, buying_power, mode FROM ticks ORDER BY id DESC LIMIT ?`) .all(limit) as Row[]; } export function recentIntents(limit = 200): Row[] { const db = getDb(); if (!db) return []; return db .prepare( `SELECT id, ts, strategy, symbol, side, qty, order_type, limit_price, trail_percent, details_json, submitted, alpaca_order_id, status FROM order_intents ORDER BY id DESC LIMIT ?` ) .all(limit) as Row[]; } export function intentsSince(iso: string): Row[] { const db = getDb(); if (!db) return []; return db .prepare( `SELECT id, ts, strategy, symbol, side, qty, order_type, limit_price, trail_percent, details_json, submitted, alpaca_order_id, status FROM order_intents WHERE ts >= ? ORDER BY id DESC` ) .all(iso) as Row[]; } export function recentEvents(limit = 100): Row[] { const db = getDb(); if (!db) return []; return db .prepare(`SELECT id, ts, kind, payload_json FROM events ORDER BY id DESC LIMIT ?`) .all(limit) as Row[]; } export function dbStatus(): { ok: boolean; path: string; error?: string } { const p = dbPath(); try { const db = getDb(); if (!db) return { ok: false, path: p, error: "could not open db" }; return { ok: true, path: p }; } catch (e: unknown) { return { ok: false, path: p, error: e instanceof Error ? e.message : String(e) }; } }