UNPKG

@gati-framework/runtime

Version:

Gati runtime execution engine for running handler-based applications

141 lines 4.48 kB
import fs from 'fs'; import path from 'path'; export class SQLiteTimelineStore { db; constructor(dbPath = ':memory:') { // Ensure directory exists if not memory if (dbPath !== ':memory:') { const dir = path.dirname(dbPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } try { // Dynamic import to avoid hard dependency on better-sqlite3 const Database = require('better-sqlite3'); this.db = new Database(dbPath); this.init(); } catch (e) { throw new Error('better-sqlite3 is not installed. Please install it or use JSONTimelineStore.'); } } init() { this.db.exec(` CREATE TABLE IF NOT EXISTS timeline ( id TEXT PRIMARY KEY, timestamp INTEGER NOT NULL, type TEXT NOT NULL, actor TEXT NOT NULL, payload TEXT, diff TEXT, parents TEXT ); CREATE INDEX IF NOT EXISTS idx_timestamp ON timeline(timestamp); CREATE INDEX IF NOT EXISTS idx_type_actor ON timeline(type, actor); `); } async append(item) { const stmt = this.db.prepare(` INSERT INTO timeline (id, timestamp, type, actor, payload, diff, parents) VALUES (?, ?, ?, ?, ?, ?, ?) `); stmt.run(item.id, item.timestamp, item.type, item.actor, JSON.stringify(item.payload), item.diff ? JSON.stringify(item.diff) : null, JSON.stringify(item.parents)); } async getLatest(type, id) { const row = this.db.prepare(` SELECT * FROM timeline WHERE type = ? ORDER BY timestamp DESC LIMIT 1 `).get(type); if (!row) return null; return this.mapRow(row); } async query(filter) { let sql = 'SELECT * FROM timeline WHERE 1=1'; const params = []; if (filter.from) { sql += ' AND timestamp >= ?'; params.push(filter.from); } if (filter.to) { sql += ' AND timestamp <= ?'; params.push(filter.to); } if (filter.type) { sql += ' AND type = ?'; params.push(filter.type); } if (filter.actor) { sql += ' AND actor = ?'; params.push(filter.actor); } sql += ' ORDER BY timestamp ASC'; const rows = this.db.prepare(sql).all(...params); return rows.map(this.mapRow); } async close() { if (this.db) { this.db.close(); } } mapRow(row) { return { id: row.id, timestamp: row.timestamp, type: row.type, actor: row.actor, payload: JSON.parse(row.payload), diff: row.diff ? JSON.parse(row.diff) : undefined, parents: JSON.parse(row.parents), }; } } export class JSONTimelineStore { items = []; filePath = null; constructor(filePath) { if (filePath) { this.filePath = filePath; const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } if (fs.existsSync(filePath)) { const content = fs.readFileSync(filePath, 'utf-8'); this.items = content.trim().split('\n').map(line => JSON.parse(line)); } } } async append(item) { this.items.push(item); if (this.filePath) { fs.appendFileSync(this.filePath, JSON.stringify(item) + '\n'); } } async getLatest(type, id) { // Simple in-memory search for (let i = this.items.length - 1; i >= 0; i--) { if (this.items[i].type === type) { return this.items[i]; } } return null; } async query(filter) { return this.items.filter(item => { if (filter.from && item.timestamp < filter.from) return false; if (filter.to && item.timestamp > filter.to) return false; if (filter.type && item.type !== filter.type) return false; if (filter.actor && item.actor !== filter.actor) return false; return true; }); } async close() { // No-op for JSON store } } //# sourceMappingURL=timeline-store.js.map