SPB Git
1.4 KB · 12 lines typescript
1/** Synchronous link audit (no worker needed): checks every URL of every public record (or a --sample N subset), writes link_checks rows, prints a summary table. Usage: pnpm links:check [--sample 40] [--slugs a,b] */2import "./_env";3import { sql, closeDb } from "../src/db";4import { linkCheck } from "../src/lib/jobs/handlers";5const args = process.argv.slice(2); const sample = Number(args[args.indexOf("--sample") + 1] || 0); const slugs = args.includes("--slugs") ? args[args.indexOf("--slugs") + 1].split(",") : null;6const rows = await sql<{ id: string; slug: string }[]>`SELECT id, slug FROM tools WHERE visibility='public' AND editorial_status IN ('published','reviewed') ${slugs ? sql`AND slug = ANY(${slugs})` : sql``} ORDER BY ${sample ? sql`random()` : sql`slug`} ${sample ? sql`LIMIT ${sample}` : sql``}`;7const t0 = Date.now(); const out: Record<string, number> = { ok: 0, redirected: 0, broken: 0 }; const broken: string[] = [];8for (const [i, r] of rows.entries()) { const res = (await linkCheck(r.id)) as any; out[res.linkState]++; if (res.linkState === "broken") broken.push(`${r.slug}: ${res.results.filter((x: any) => !x.ok).map((x: any) => `${x.field}=${x.status || x.error}`).join(", ")}`); if (i % 20 === 19) console.log(`  ${i + 1}/${rows.length}`); }9console.log(JSON.stringify({ checked: rows.length, ...out, seconds: Math.round((Date.now() - t0) / 1000), at: new Date().toISOString() }));10for (const b of broken) console.log("BROKEN", b);11await closeDb();12
Files · main
Menu

Theme