From 873c229275222e0dff0ee5b72181c5e12b4feedf Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 6 Oct 2025 11:34:21 -0700 Subject: [PATCH] Continuing... --- server/routes/games.ts | 7 ++-- server/routes/games/store.ts | 70 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 server/routes/games/store.ts diff --git a/server/routes/games.ts b/server/routes/games.ts index d77429d..230732e 100755 --- a/server/routes/games.ts +++ b/server/routes/games.ts @@ -31,10 +31,13 @@ const debug = { // normalizeIncoming imported from './games/utils.ts' -let gameDB; +import { initGameDB } from './games/store.js'; -require("../db/games").then(function(db) { +let gameDB: any; +initGameDB().then((db) => { gameDB = db; +}).catch((e) => { + console.error('Failed to initialize game DB', e); }); // shuffleArray imported from './games/utils.ts' diff --git a/server/routes/games/store.ts b/server/routes/games/store.ts new file mode 100644 index 0000000..04a2537 --- /dev/null +++ b/server/routes/games/store.ts @@ -0,0 +1,70 @@ +import type { GameState } from './state.js'; + +/** + * Thin game DB initializer / accessor. + * This currently returns the underlying db module (for runtime compatibility) + * and is the single place to add typed helper methods for game persistence. + */ +export async function initGameDB(): Promise { + // dynamic import to preserve original runtime ordering + // path is relative to this file (routes/games) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - dynamic import of runtime DB module; resolved at runtime inside container + const mod = await import('../db/games'); + // If the module uses default export, prefer it + const db = (mod && (mod.default || mod)); + + // attach typed helper placeholders (will be implemented incrementally) + if (!db.getGameById) { + db.getGameById = async (id: string | number): Promise => { + // fallback: try to query by id using raw SQL if sequelize is available + if (db && db.sequelize) { + try { + const rows = await db.sequelize.query('SELECT state FROM games WHERE id=:id', { + replacements: { id }, + type: db.Sequelize.QueryTypes.SELECT + }); + if (rows && rows.length) { + const r = rows[0] as any; + // state may be stored as text or JSON + if (typeof r.state === 'string') { + try { + return JSON.parse(r.state) as GameState; + } catch (e) { + return null; + } + } + return r.state as GameState; + } + } catch (e) { + // ignore and fallthrough + } + } + return null; + }; + } + + if (!db.saveGameState) { + db.saveGameState = async (id: string | number, state: GameState): Promise => { + if (db && db.sequelize) { + const payload = JSON.stringify(state); + try { + await db.sequelize.query('UPDATE games SET state=:state WHERE id=:id', { + replacements: { id, state: payload } + }); + } catch (e) { + // if update failed, attempt insert + try { + await db.sequelize.query('INSERT INTO games (id, state) VALUES(:id, :state)', { + replacements: { id, state: payload } + }); + } catch (err) { + // swallow; callers should handle missing persistence + } + } + } + }; + } + + return db; +}