import initSqlJs from 'sql.js'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import fs from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const DB_PATH = join(__dirname, '../data/messages.db'); let db = null; export async function initDatabase() { const SQL = await initSqlJs(); // Load existing database or create new one let dbBuffer; if (fs.existsSync(DB_PATH)) { dbBuffer = fs.readFileSync(DB_PATH); db = new SQL.Database(dbBuffer); } else { db = new SQL.Database(); } // Create tables db.run(` CREATE TABLE IF NOT EXISTS messages ( id TEXT PRIMARY KEY, channel_id TEXT NOT NULL, author_id TEXT NOT NULL, author_name TEXT NOT NULL, content TEXT NOT NULL, created_at INTEGER NOT NULL, fetched_at INTEGER NOT NULL ) `); db.run(`CREATE INDEX IF NOT EXISTS idx_channel ON messages(channel_id)`); db.run(`CREATE INDEX IF NOT EXISTS idx_created_at ON messages(created_at)`); db.run(`CREATE INDEX IF NOT EXISTS idx_fetched_at ON messages(fetched_at)`); saveDatabase(); } function saveDatabase() { const data = db.export(); const buffer = Buffer.from(data); fs.writeFileSync(DB_PATH, buffer); } export function saveMessage(message) { db.run( `INSERT OR REPLACE INTO messages (id, channel_id, author_id, author_name, content, created_at, fetched_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, [ message.id, message.channelId, message.authorId, message.authorName, message.content, message.createdAt, Date.now(), ] ); saveDatabase(); } export function saveMessages(messages) { db.run('BEGIN TRANSACTION'); const stmt = db.prepare( `INSERT OR REPLACE INTO messages (id, channel_id, author_id, author_name, content, created_at, fetched_at) VALUES (?, ?, ?, ?, ?, ?, ?)` ); for (const msg of messages) { stmt.run([ msg.id, msg.channelId, msg.authorId, msg.authorName, msg.content, msg.createdAt, Date.now(), ]); } stmt.free(); db.run('COMMIT'); saveDatabase(); } export function getMessagesByChannel(channelId, limit = 50) { const stmt = db.prepare( `SELECT * FROM messages WHERE channel_id = ? ORDER BY created_at DESC LIMIT ?` ); stmt.bind([channelId, limit]); const results = []; while (stmt.step()) { const row = stmt.getAsObject(); results.push(row); } stmt.free(); return results; } export function getAllChannels() { const stmt = db.prepare( `SELECT DISTINCT channel_id, author_name as last_author FROM messages ORDER BY fetched_at DESC` ); const results = []; while (stmt.step()) { results.push(stmt.getAsObject()); } stmt.free(); return results; } export function getAllMessages(limit = 50) { const stmt = db.prepare( `SELECT * FROM messages ORDER BY created_at DESC LIMIT ?` ); stmt.bind([limit]); const results = []; while (stmt.step()) { const row = stmt.getAsObject(); results.push(row); } stmt.free(); return results; } export function getLatestMessageTime(channelId) { const stmt = db.prepare( `SELECT MAX(created_at) as latest FROM messages WHERE channel_id = ?` ); stmt.bind([channelId]); let result = null; if (stmt.step()) { result = stmt.getAsObject(); } stmt.free(); return result?.latest || 0; } export { db };