import type Database from 'better-sqlite3'; const initialized = new WeakSet(); export function ensureGameFileSchema(handle: Database.Database): void { if (initialized.has(handle)) return; handle.exec(` CREATE TABLE IF NOT EXISTS game_file_libraries ( id TEXT PRIMARY KEY, name TEXT NOT NULL COLLATE NOCASE UNIQUE, game TEXT NOT NULL CHECK(game IN ('t5','t6')), description TEXT NOT NULL, created_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS game_file_versions ( id TEXT PRIMARY KEY, library_id TEXT NOT NULL REFERENCES game_file_libraries(id), version TEXT NOT NULL, description TEXT NOT NULL, dlc TEXT NOT NULL, state TEXT NOT NULL CHECK(state IN ('importing','ready','failed')), size_bytes INTEGER NOT NULL DEFAULT 0, manifest TEXT NOT NULL DEFAULT '[]', manifest_sha256 TEXT, created_at TEXT NOT NULL, published_at TEXT, storage_location TEXT NOT NULL, source_host_id TEXT NOT NULL, source_volume TEXT NOT NULL, error TEXT, operation_id TEXT, UNIQUE(library_id, version) ); CREATE TABLE IF NOT EXISTS host_library_caches ( host_id TEXT NOT NULL, version_id TEXT NOT NULL REFERENCES game_file_versions(id), status TEXT NOT NULL CHECK(status IN ('missing','downloading','verifying','ready','failed','outdated')), bytes_downloaded INTEGER NOT NULL DEFAULT 0, bytes_total INTEGER NOT NULL DEFAULT 0, manifest_sha256 TEXT, error TEXT, updated_at TEXT NOT NULL, operation_id TEXT, PRIMARY KEY(host_id, version_id) ); CREATE TABLE IF NOT EXISTS game_file_entries ( version_id TEXT NOT NULL REFERENCES game_file_versions(id), path TEXT NOT NULL, size INTEGER NOT NULL, sha256 TEXT NOT NULL, PRIMARY KEY(version_id,path) ); CREATE TABLE IF NOT EXISTS game_file_upload_entries ( version_id TEXT NOT NULL REFERENCES game_file_versions(id), path TEXT NOT NULL, size INTEGER NOT NULL, last_modified INTEGER NOT NULL, PRIMARY KEY(version_id,path) ); INSERT OR IGNORE INTO game_file_entries(version_id,path,size,sha256) SELECT v.id,json_extract(f.value,'$.path'),json_extract(f.value,'$.size'),json_extract(f.value,'$.sha256') FROM game_file_versions v,json_each(v.manifest) f; CREATE TRIGGER IF NOT EXISTS game_file_versions_immutable BEFORE UPDATE ON game_file_versions WHEN OLD.state = 'ready' BEGIN SELECT RAISE(ABORT, 'Published game-file versions are immutable'); END; `); initialized.add(handle); }