UNPKG

pmarket-cli

Version:
113 lines (111 loc) 4.2 kB
import Database from 'better-sqlite3'; import { join } from 'path'; const CACHE_DB = 'cache.db'; const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour export class CacheService { db; constructor(configService) { const dbPath = join(configService.getConfigDir(), CACHE_DB); this.db = new Database(dbPath); this.initializeSchema(); } initializeSchema() { this.db.exec(` CREATE TABLE IF NOT EXISTS markets ( condition_id TEXT PRIMARY KEY, question TEXT, description TEXT, category TEXT, end_date_iso TEXT, active INTEGER, closed INTEGER, yes_token_id TEXT, no_token_id TEXT, yes_outcome TEXT, no_outcome TEXT, cached_at INTEGER ); CREATE TABLE IF NOT EXISTS cache_metadata ( key TEXT PRIMARY KEY, value TEXT ); CREATE INDEX IF NOT EXISTS idx_markets_question ON markets(question); CREATE INDEX IF NOT EXISTS idx_markets_active ON markets(active, closed); `); } isCacheValid() { const stmt = this.db.prepare('SELECT value FROM cache_metadata WHERE key = ?'); const row = stmt.get('last_full_refresh'); if (!row) { return false; } const lastRefresh = parseInt(row.value, 10); return Date.now() - lastRefresh < CACHE_TTL_MS; } getCachedMarkets(filter) { let query = 'SELECT * FROM markets WHERE active = 1 AND closed = 0'; const params = []; if (filter) { query += ' AND LOWER(question) LIKE ?'; params.push(`%${filter.toLowerCase()}%`); } const stmt = this.db.prepare(query); return stmt.all(...params); } cacheMarkets(markets) { const insertStmt = this.db.prepare(` INSERT OR REPLACE INTO markets (condition_id, question, description, category, end_date_iso, active, closed, yes_token_id, no_token_id, yes_outcome, no_outcome, cached_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); const now = Date.now(); const insertMany = this.db.transaction((markets) => { for (const market of markets) { insertStmt.run(market.condition_id, market.question, market.description, market.category, market.end_date_iso, market.active ? 1 : 0, market.closed ? 1 : 0, market.tokens[0]?.token_id ?? '', market.tokens[1]?.token_id ?? '', market.tokens[0]?.outcome ?? 'Yes', market.tokens[1]?.outcome ?? 'No', now); } }); insertMany(markets); const metaStmt = this.db.prepare('INSERT OR REPLACE INTO cache_metadata (key, value) VALUES (?, ?)'); metaStmt.run('last_full_refresh', now.toString()); } clearCache() { this.db.exec('DELETE FROM markets'); this.db.exec('DELETE FROM cache_metadata'); } getMarketCount() { const stmt = this.db.prepare('SELECT COUNT(*) as count FROM markets'); const row = stmt.get(); return row.count; } getCacheAge() { const stmt = this.db.prepare('SELECT value FROM cache_metadata WHERE key = ?'); const row = stmt.get('last_full_refresh'); if (!row) { return null; } const lastRefresh = parseInt(row.value, 10); const ageMs = Date.now() - lastRefresh; const minutes = Math.floor(ageMs / (1000 * 60)); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) { return `${days} day${days > 1 ? 's' : ''} ago`; } else if (hours > 0) { return `${hours} hour${hours > 1 ? 's' : ''} ago`; } else if (minutes > 0) { return `${minutes} minute${minutes > 1 ? 's' : ''} ago`; } else { return 'just now'; } } hasCache() { return this.getMarketCount() > 0; } close() { this.db.close(); } } //# sourceMappingURL=cache.service.js.map