kaboot/server/src/db/connection.ts

134 lines
5.4 KiB
TypeScript

import Database, { Database as DatabaseType } from 'better-sqlite3';
import { readFileSync, mkdirSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const DB_PATH = process.env.DATABASE_PATH || join(__dirname, '../../../data/kaboot.db');
mkdirSync(dirname(DB_PATH), { recursive: true });
export const db: DatabaseType = new Database(DB_PATH);
db.pragma('journal_mode = WAL');
db.pragma('foreign_keys = ON');
const schema = readFileSync(join(__dirname, 'schema.sql'), 'utf-8');
db.exec(schema);
const runMigrations = () => {
const tableInfo = db.prepare("PRAGMA table_info(quizzes)").all() as { name: string }[];
const hasGameConfig = tableInfo.some(col => col.name === 'game_config');
if (!hasGameConfig) {
db.exec("ALTER TABLE quizzes ADD COLUMN game_config TEXT");
console.log("Migration: Added game_config to quizzes");
}
const userTableInfo = db.prepare("PRAGMA table_info(users)").all() as { name: string }[];
const hasDefaultConfig = userTableInfo.some(col => col.name === 'default_game_config');
if (!hasDefaultConfig) {
db.exec("ALTER TABLE users ADD COLUMN default_game_config TEXT");
console.log("Migration: Added default_game_config to users");
}
const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='game_sessions'").get();
if (!tables) {
db.exec(`
CREATE TABLE game_sessions (
pin TEXT PRIMARY KEY,
host_peer_id TEXT NOT NULL,
host_secret TEXT NOT NULL,
quiz_data TEXT NOT NULL,
game_config TEXT NOT NULL,
game_state TEXT NOT NULL DEFAULT 'LOBBY',
current_question_index INTEGER NOT NULL DEFAULT 0,
players_data TEXT NOT NULL DEFAULT '[]',
first_correct_player_id TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_game_sessions_updated ON game_sessions(updated_at);
`);
console.log("Migration: Created game_sessions table");
}
const sessionTableInfo = db.prepare("PRAGMA table_info(game_sessions)").all() as { name: string }[];
const hasFirstCorrect = sessionTableInfo.some(col => col.name === "first_correct_player_id");
if (!hasFirstCorrect) {
db.exec("ALTER TABLE game_sessions ADD COLUMN first_correct_player_id TEXT");
console.log("Migration: Added first_correct_player_id to game_sessions");
}
const userTableInfo2 = db.prepare("PRAGMA table_info(users)").all() as { name: string }[];
const hasColorScheme = userTableInfo2.some(col => col.name === "color_scheme");
if (!hasColorScheme) {
db.exec("ALTER TABLE users ADD COLUMN color_scheme TEXT DEFAULT 'blue'");
console.log("Migration: Added color_scheme to users");
}
const hasGeminiKey = userTableInfo2.some(col => col.name === "gemini_api_key");
if (!hasGeminiKey) {
db.exec("ALTER TABLE users ADD COLUMN gemini_api_key TEXT");
console.log("Migration: Added gemini_api_key to users");
}
const hasAiProvider = userTableInfo2.some(col => col.name === "ai_provider");
if (!hasAiProvider) {
db.exec("ALTER TABLE users ADD COLUMN ai_provider TEXT DEFAULT 'gemini'");
console.log("Migration: Added ai_provider to users");
}
const hasOpenRouterKey = userTableInfo2.some(col => col.name === "openrouter_api_key");
if (!hasOpenRouterKey) {
db.exec("ALTER TABLE users ADD COLUMN openrouter_api_key TEXT");
console.log("Migration: Added openrouter_api_key to users");
}
const hasOpenRouterModel = userTableInfo2.some(col => col.name === "openrouter_model");
if (!hasOpenRouterModel) {
db.exec("ALTER TABLE users ADD COLUMN openrouter_model TEXT");
console.log("Migration: Added openrouter_model to users");
}
const hasOpenAIKey = userTableInfo2.some(col => col.name === "openai_api_key");
if (!hasOpenAIKey) {
db.exec("ALTER TABLE users ADD COLUMN openai_api_key TEXT");
console.log("Migration: Added openai_api_key to users");
}
const hasOpenAIModel = userTableInfo2.some(col => col.name === "openai_model");
if (!hasOpenAIModel) {
db.exec("ALTER TABLE users ADD COLUMN openai_model TEXT");
console.log("Migration: Added openai_model to users");
}
const hasGeminiModel = userTableInfo2.some(col => col.name === "gemini_model");
if (!hasGeminiModel) {
db.exec("ALTER TABLE users ADD COLUMN gemini_model TEXT");
console.log("Migration: Added gemini_model to users");
}
const quizTableInfo = db.prepare("PRAGMA table_info(quizzes)").all() as { name: string }[];
const hasShareToken = quizTableInfo.some(col => col.name === "share_token");
if (!hasShareToken) {
db.exec("ALTER TABLE quizzes ADD COLUMN share_token TEXT");
console.log("Migration: Added share_token to quizzes");
}
const hasIsShared = quizTableInfo.some(col => col.name === "is_shared");
if (!hasIsShared) {
db.exec("ALTER TABLE quizzes ADD COLUMN is_shared INTEGER DEFAULT 0");
console.log("Migration: Added is_shared to quizzes");
}
const shareTokenIndex = db.prepare("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_quizzes_share_token'").get();
if (!shareTokenIndex) {
db.exec("CREATE UNIQUE INDEX idx_quizzes_share_token ON quizzes(share_token)");
console.log("Migration: Created unique index on quizzes.share_token");
}
};
runMigrations();
console.log(`Database initialized at ${DB_PATH}`);