From ec038e72408b17bded706c1f1f929e6f98a59cbc Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Tue, 20 Jan 2026 09:52:24 -0600 Subject: [PATCH] feat(04-01): implement graph database helpers - Add getSQL() for cached sql.js WASM initialization - Add loadGraphDatabase() to create or load graph.db - Add persistDatabase() to export in-memory DB to disk - Singleton pattern avoids repeated WASM init overhead Co-Authored-By: Claude Opus 4.5 --- hooks/gsd-intel-index.js | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/hooks/gsd-intel-index.js b/hooks/gsd-intel-index.js index a02bf2386..6360bb8fe 100755 --- a/hooks/gsd-intel-index.js +++ b/hooks/gsd-intel-index.js @@ -25,6 +25,50 @@ CREATE INDEX IF NOT EXISTS source_idx ON edges(source); CREATE INDEX IF NOT EXISTS target_idx ON edges(target); `; +// Singleton SQL instance (async init, reuse across calls) +let sqlInstance = null; + +/** + * Get or initialize sql.js instance + * Caches the SQL constructor for reuse + */ +async function getSQL() { + if (!sqlInstance) { + sqlInstance = await initSqlJs(); + } + return sqlInstance; +} + +/** + * Load or create the graph database + * Returns { db, dbPath } for operations and persistence + */ +async function loadGraphDatabase() { + const SQL = await getSQL(); + const dbPath = path.join(process.cwd(), '.planning', 'intel', 'graph.db'); + + let db; + if (fs.existsSync(dbPath)) { + const buffer = fs.readFileSync(dbPath); + db = new SQL.Database(buffer); + } else { + db = new SQL.Database(); + db.run(GRAPH_SCHEMA); + } + + return { db, dbPath }; +} + +/** + * Persist database to disk + * Must call after every write operation + */ +function persistDatabase(db, dbPath) { + const data = db.export(); + const buffer = Buffer.from(data); + fs.writeFileSync(dbPath, buffer); +} + // JS/TS file extensions to index const INDEXABLE_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];