const Database = require('better-sqlite3'); import path from 'path'; import fs from 'fs'; const dbPath = path.join(__dirname, '../data/invicanvas.db'); const dbDir = path.dirname(dbPath); if (!fs.existsSync(dbDir)) { fs.mkdirSync(dbDir, { recursive: true }); } export const db = new Database(dbPath); db.pragma('journal_mode = WAL'); db.exec(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, github_id TEXT UNIQUE, username TEXT NOT NULL, display_name TEXT, avatar_url TEXT, email TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS pixels ( x INTEGER NOT NULL, y INTEGER NOT NULL, color TEXT NOT NULL, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (x, y) ); CREATE INDEX IF NOT EXISTS idx_pixels_updated ON pixels(updated_at); `); export function generateUserId(): string { return `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } export function upsertPixels(pixels: { x: number; y: number; color: string }[]): void { const stmt = db.prepare( 'INSERT OR REPLACE INTO pixels (x, y, color, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)' ); const transaction = db.transaction((pixels: any[]) => { for (const pixel of pixels) { stmt.run(pixel.x, pixel.y, pixel.color); } }); transaction(pixels); } export function getAllPixels(): { x: number; y: number; color: string }[] { const stmt = db.prepare('SELECT x, y, color FROM pixels ORDER BY x, y'); return stmt.all() as { x: number; y: number; color: string }[]; }