1
0
peddlers-of-ketran/server/tools/import-games-to-db.ts

110 lines
3.7 KiB
TypeScript

#!/usr/bin/env ts-node
import path from 'path';
import fs from 'fs/promises';
import { initGameDB } from '../routes/games/store';
async function main() {
const gamesDir = path.resolve(__dirname, '../../db/games');
let files: string[] = [];
try {
files = await fs.readdir(gamesDir);
} catch (e) {
console.error('Failed to read games dir', gamesDir, e);
process.exit(2);
}
let db: any;
try {
db = await initGameDB();
} catch (e) {
console.error('Failed to initialize DB', e);
process.exit(3);
}
if (!db || !db.sequelize) {
console.error('DB did not expose sequelize; cannot proceed.');
process.exit(4);
}
for (const f of files) {
// ignore dotfiles and .bk backup files (we don't want to import backups)
if (f.startsWith('.') || f.endsWith('.bk')) continue;
const full = path.join(gamesDir, f);
try {
const stat = await fs.stat(full);
if (!stat.isFile()) continue;
const raw = await fs.readFile(full, 'utf8');
const state = JSON.parse(raw);
// Derive id from filename (strip .json if present)
const idStr = f.endsWith('.json') ? f.slice(0, -5) : f;
const id = isNaN(Number(idStr)) ? idStr : Number(idStr);
// derive a friendly name from the saved state when present
const nameCandidate = (state && (state.name || state.id)) ? String(state.name || state.id) : undefined;
try {
if (typeof id === 'number') {
// numeric filename: use the typed helper
await db.saveGameState(id, state);
console.log(`Saved game id=${id}`);
if (nameCandidate) {
try {
await db.sequelize.query('UPDATE games SET name=:name WHERE id=:id', { replacements: { id, name: nameCandidate } });
} catch (_) {
// ignore name update failure
}
}
} else {
// string filename: try to find an existing row by path and save via id;
// otherwise insert a new row with path and the JSON state.
let found: any[] = [];
try {
found = await db.sequelize.query('SELECT id FROM games WHERE path=:path', {
replacements: { path: idStr },
type: db.Sequelize.QueryTypes.SELECT
});
} catch (qe) {
found = [];
}
if (found && found.length) {
const foundId = found[0].id;
await db.saveGameState(foundId, state);
console.log(`Saved game path=${idStr} -> id=${foundId}`);
if (nameCandidate) {
try {
await db.sequelize.query('UPDATE games SET name=:name WHERE id=:id', { replacements: { id: foundId, name: nameCandidate } });
} catch (_) {
// ignore
}
}
} else {
// ensure state column exists before inserting a new row
try {
await db.sequelize.query('ALTER TABLE games ADD COLUMN state TEXT');
} catch (_) {
// ignore
}
const payload = JSON.stringify(state);
if (nameCandidate) {
await db.sequelize.query('INSERT INTO games (path, state, name) VALUES(:path, :state, :name)', { replacements: { path: idStr, state: payload, name: nameCandidate } });
} else {
await db.sequelize.query('INSERT INTO games (path, state) VALUES(:path, :state)', { replacements: { path: idStr, state: payload } });
}
console.log(`Inserted game path=${idStr}`);
}
}
} catch (e) {
console.error('Failed to save game', idStr, e);
}
} catch (e) {
console.error('Failed to read/parse', full, e);
}
}
console.log('Import complete');
process.exit(0);
}
main();