import { mkdir } from "node:fs/promises"; import { dirname } from "node:path"; import { drizzle } from "drizzle-orm/libsql"; import { createClient } from "@libsql/client"; import * as schema from "./skill-registry-schema.js"; import { resolveSkillRegistryDbPath } from "../home-paths.js"; export type SkillRegistryDb = ReturnType>; let _db: SkillRegistryDb | null = null; const CREATE_SKILLS_TABLE = ` CREATE TABLE IF NOT EXISTS skills ( id TEXT PRIMARY KEY, source_id TEXT NOT NULL, name TEXT NOT NULL, description TEXT, source_url TEXT, active_version_id TEXT, removed_at INTEGER, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL )`; const CREATE_SKILL_VERSIONS_TABLE = ` CREATE TABLE IF NOT EXISTS skill_versions ( id TEXT PRIMARY KEY, skill_id TEXT NOT NULL, version TEXT NOT NULL, fetched_at INTEGER NOT NULL, cache_dir TEXT )`; const CREATE_SKILL_FILES_TABLE = ` CREATE TABLE IF NOT EXISTS skill_files ( id TEXT PRIMARY KEY, version_id TEXT NOT NULL, path TEXT NOT NULL, kind TEXT NOT NULL, size_bytes INTEGER )`; const CREATE_COMMUNITY_RATINGS_TABLE = ` CREATE TABLE IF NOT EXISTS community_ratings ( id TEXT PRIMARY KEY, skill_id TEXT NOT NULL, fetched_at INTEGER NOT NULL, average_rating REAL, rating_count INTEGER, source TEXT )`; export async function getSkillRegistryDb(): Promise { if (_db !== null) return _db; const dbPath = resolveSkillRegistryDbPath(); await mkdir(dirname(dbPath), { recursive: true }); const client = createClient({ url: `file:${dbPath}` }); _db = drizzle({ client, schema }); await client.execute(CREATE_SKILLS_TABLE); await client.execute(CREATE_SKILL_VERSIONS_TABLE); await client.execute(CREATE_SKILL_FILES_TABLE); await client.execute(CREATE_COMMUNITY_RATINGS_TABLE); return _db; } /** Reset the singleton — used for test cleanup */ export function resetSkillRegistryDb(): void { _db = null; }