scripts: add backfill CLI with dry-run default
Wires backfill-canonical-layer.ts to a CLI entry point exposed as `npm run backfill:canonical`. Defaults to --dry-run; requires --apply to actually write. Supports --sport=<uuid> to limit to a single sport. Exits 2 if the backfill reports errors (e.g., surface-Elo conflicts).
This commit is contained in:
parent
8186dbb525
commit
6f3438b5d2
2 changed files with 79 additions and 0 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
"db:generate": "dotenv -- drizzle-kit generate",
|
"db:generate": "dotenv -- drizzle-kit generate",
|
||||||
"db:migrate": "dotenv -- drizzle-kit migrate",
|
"db:migrate": "dotenv -- drizzle-kit migrate",
|
||||||
"db:sync-prod": "bash scripts/sync-prod-db.sh",
|
"db:sync-prod": "bash scripts/sync-prod-db.sh",
|
||||||
|
"backfill:canonical": "dotenv -- tsx scripts/backfill-cli.ts",
|
||||||
"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' dotenv -- tsx watch server.ts",
|
"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' dotenv -- tsx watch server.ts",
|
||||||
"start": "NODE_ENV=production NODE_OPTIONS='--import ./instrument.server.mjs' node dist/server.js",
|
"start": "NODE_ENV=production NODE_OPTIONS='--import ./instrument.server.mjs' node dist/server.js",
|
||||||
"start:production": "NODE_ENV=production NODE_OPTIONS='--import ./instrument.server.mjs' node dist/server.js",
|
"start:production": "NODE_ENV=production NODE_OPTIONS='--import ./instrument.server.mjs' node dist/server.js",
|
||||||
|
|
|
||||||
78
scripts/backfill-cli.ts
Normal file
78
scripts/backfill-cli.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* CLI entry point for the Phase 2 canonical backfill.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* npm run backfill:canonical -- [--dry-run | --apply] [--sport=<uuid>]
|
||||||
|
*
|
||||||
|
* Defaults to --dry-run for safety. No writes will be issued unless
|
||||||
|
* --apply is passed explicitly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { runBackfill } from "./backfill-canonical-layer";
|
||||||
|
import type { BackfillOptions } from "./backfill-canonical-layer";
|
||||||
|
|
||||||
|
function printHelp(): void {
|
||||||
|
console.log(
|
||||||
|
[
|
||||||
|
"Usage: backfill-cli [options]",
|
||||||
|
"",
|
||||||
|
"Options:",
|
||||||
|
" --dry-run Run without writing (default).",
|
||||||
|
" --apply Actually write to the database.",
|
||||||
|
" --sport=<uuid> Only backfill for the given sport id.",
|
||||||
|
" --help Show this message.",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseArgs(): BackfillOptions {
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
const opts: BackfillOptions = { dryRun: true }; // dry-run by default for safety
|
||||||
|
for (const a of args) {
|
||||||
|
if (a === "--apply") {
|
||||||
|
opts.dryRun = false;
|
||||||
|
} else if (a === "--dry-run") {
|
||||||
|
opts.dryRun = true;
|
||||||
|
} else if (a.startsWith("--sport=")) {
|
||||||
|
opts.sportId = a.slice("--sport=".length);
|
||||||
|
} else if (a === "--help" || a === "-h") {
|
||||||
|
printHelp();
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.error(`unknown arg: ${a}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const opts = parseArgs();
|
||||||
|
console.log(
|
||||||
|
`Running backfill (dryRun=${opts.dryRun}, sportId=${opts.sportId ?? "all"})`,
|
||||||
|
);
|
||||||
|
const report = await runBackfill(opts);
|
||||||
|
|
||||||
|
console.log("---");
|
||||||
|
console.log(`tournamentsCreated: ${report.tournamentsCreated}`);
|
||||||
|
console.log(`tournamentsLinked: ${report.tournamentsLinked}`);
|
||||||
|
console.log(`participantsCreated: ${report.participantsCreated}`);
|
||||||
|
console.log(`participantsLinked: ${report.participantsLinked}`);
|
||||||
|
console.log(`tournamentResultsCreated: ${report.tournamentResultsCreated}`);
|
||||||
|
console.log(`surfaceElosCreated: ${report.surfaceElosCreated}`);
|
||||||
|
|
||||||
|
if (report.warnings.length) {
|
||||||
|
console.log("\nWARNINGS:");
|
||||||
|
for (const w of report.warnings) console.log(` ${w}`);
|
||||||
|
}
|
||||||
|
if (report.errors.length) {
|
||||||
|
console.log("\nERRORS:");
|
||||||
|
for (const e of report.errors) console.log(` ${e}`);
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Loading…
Add table
Reference in a new issue