Wire in the txt_game_scores database provision and create the players/games tables via a provision-scoped migration so Child 2 can implement the server-side score persistence. - module.yml: requires postgres database (txt_game_scores) with env_map for host/port/user/password/name; empty env keys added so env-sync populates them after provisioning - migrations/package.json: ESM, pg + typescript devdeps - migrations/provision/postgres/000-init-scores.ts: creates players and games tables with idempotent IF NOT EXISTS guards and two supporting indexes (scoreboard sort, history lookup) Server code, Dockerfile, and docker-compose.yml are unchanged — server integration is deferred to the follow-on child task. Task: 3dab55e3-9792-47a0-a4a6-ba7757517314
53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
import pg from "pg";
|
|
|
|
const client = new pg.Client({
|
|
host: process.env.PROVISION_HOST,
|
|
port: parseInt(process.env.PROVISION_PORT ?? "5432"),
|
|
user: process.env.PROVISION_USER,
|
|
password: process.env.PROVISION_PASSWORD,
|
|
database: process.env.PROVISION_DATABASE,
|
|
});
|
|
|
|
await client.connect();
|
|
|
|
try {
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS players (
|
|
id TEXT PRIMARY KEY,
|
|
games_played INT NOT NULL DEFAULT 0,
|
|
games_won INT NOT NULL DEFAULT 0,
|
|
games_lost INT NOT NULL DEFAULT 0,
|
|
best_attempts INT,
|
|
current_streak INT NOT NULL DEFAULT 0,
|
|
best_streak INT NOT NULL DEFAULT 0,
|
|
last_played_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
)
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS games (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
player_id TEXT NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
|
target INT NOT NULL,
|
|
attempts INT NOT NULL,
|
|
won BOOLEAN NOT NULL,
|
|
finished_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
)
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE INDEX IF NOT EXISTS idx_players_scoreboard
|
|
ON players (best_attempts NULLS LAST, last_played_at)
|
|
`);
|
|
|
|
await client.query(`
|
|
CREATE INDEX IF NOT EXISTS idx_games_player_history
|
|
ON games (player_id, finished_at DESC)
|
|
`);
|
|
|
|
console.log("[txt-game migration-000] score schema created");
|
|
} finally {
|
|
await client.end();
|
|
}
|