const Database = require('better-sqlite3'); const path = require('path'); const fs = require('fs'); const dbPath = process.env.DB_PATH || path.join(__dirname, 'data', 'jackbox.db'); const dbDir = path.dirname(dbPath); // Ensure data directory exists with proper permissions try { if (!fs.existsSync(dbDir)) { fs.mkdirSync(dbDir, { recursive: true, mode: 0o777 }); } // Also ensure the directory is writable fs.accessSync(dbDir, fs.constants.W_OK); } catch (err) { console.error(`Error with database directory ${dbDir}:`, err.message); console.error('Please ensure the directory exists and is writable'); process.exit(1); } const db = new Database(dbPath); // Enable foreign keys db.pragma('foreign_keys = ON'); // Create tables function initializeDatabase() { // Games table db.exec(` CREATE TABLE IF NOT EXISTS games ( id INTEGER PRIMARY KEY AUTOINCREMENT, pack_name TEXT NOT NULL, title TEXT NOT NULL, min_players INTEGER NOT NULL, max_players INTEGER NOT NULL, length_minutes INTEGER, has_audience INTEGER DEFAULT 0, family_friendly INTEGER DEFAULT 0, game_type TEXT, secondary_type TEXT, play_count INTEGER DEFAULT 0, popularity_score INTEGER DEFAULT 0, enabled INTEGER DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // Sessions table db.exec(` CREATE TABLE IF NOT EXISTS sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, closed_at DATETIME, is_active INTEGER DEFAULT 1, notes TEXT ) `); // Session games table db.exec(` CREATE TABLE IF NOT EXISTS session_games ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id INTEGER NOT NULL, game_id INTEGER NOT NULL, played_at DATETIME DEFAULT CURRENT_TIMESTAMP, manually_added INTEGER DEFAULT 0, status TEXT DEFAULT 'played', FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE, FOREIGN KEY (game_id) REFERENCES games(id) ON DELETE CASCADE ) `); // Add status column if it doesn't exist (for existing databases) try { db.exec(`ALTER TABLE session_games ADD COLUMN status TEXT DEFAULT 'played'`); } catch (err) { // Column already exists, ignore error } // Add favor_bias column to games if it doesn't exist try { db.exec(`ALTER TABLE games ADD COLUMN favor_bias INTEGER DEFAULT 0`); } catch (err) { // Column already exists, ignore error } // Packs table for pack-level favoriting db.exec(` CREATE TABLE IF NOT EXISTS packs ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, favor_bias INTEGER DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // Populate packs table with unique pack names from games db.exec(` INSERT OR IGNORE INTO packs (name) SELECT DISTINCT pack_name FROM games `); // Chat logs table db.exec(` CREATE TABLE IF NOT EXISTS chat_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id INTEGER NOT NULL, chatter_name TEXT NOT NULL, message TEXT NOT NULL, timestamp DATETIME NOT NULL, parsed_vote TEXT, FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE ) `); console.log('Database initialized successfully'); } initializeDatabase(); module.exports = db;