Files
game-grid/src/lib/server/db.ts
2026-05-17 15:37:00 -04:00

88 lines
2.9 KiB
TypeScript

import Database from 'better-sqlite3';
import fs from 'node:fs';
import path from 'node:path';
import { env } from '$env/dynamic/private';
let _db: Database.Database | null = null;
export function getDb(): Database.Database {
if (_db) return _db;
const DB_PATH = env.DB_PATH ?? path.join(process.cwd(), 'data', 'game-grid.db');
const dir = path.dirname(DB_PATH);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
_db = new Database(DB_PATH);
_db.pragma('journal_mode = WAL');
_db.pragma('foreign_keys = ON');
initSchema(_db);
return _db;
}
function initSchema(db: Database.Database): void {
db.exec(`
CREATE TABLE IF NOT EXISTS series (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
library TEXT NOT NULL CHECK(library IN ('public','private')),
folder_path TEXT NOT NULL,
has_cover INTEGER NOT NULL DEFAULT 0,
last_scanned_at TEXT NOT NULL DEFAULT (datetime('now')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS games (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
library TEXT NOT NULL CHECK(library IN ('public','private')),
folder_path TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
genre TEXT NOT NULL DEFAULT '',
has_cover INTEGER NOT NULL DEFAULT 0,
has_wide INTEGER NOT NULL DEFAULT 0,
last_scanned_at TEXT NOT NULL DEFAULT (datetime('now')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS game_files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
game_id INTEGER NOT NULL REFERENCES games(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
rel_path TEXT NOT NULL,
platform TEXT NOT NULL,
is_dir INTEGER NOT NULL DEFAULT 0,
file_size INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS screenshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
game_id INTEGER NOT NULL REFERENCES games(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
rel_path TEXT NOT NULL,
sort_order INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE COLLATE NOCASE
);
CREATE TABLE IF NOT EXISTS game_tags (
game_id INTEGER NOT NULL REFERENCES games(id) ON DELETE CASCADE,
tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (game_id, tag_id)
);
`);
const cols = db.prepare('PRAGMA table_info(games)').all() as Array<{ name: string }>;
if (!cols.some((c) => c.name === 'series_id')) {
db.exec(
'ALTER TABLE games ADD COLUMN series_id INTEGER REFERENCES series(id) ON DELETE SET NULL'
);
}
}