/** * Standalone recompute helper. * Not part of the product — this is a CLI shim that performs the same flow * as the integration flow without pulling in server-only modules. */ import PocketBase from "pocketbase"; import { DEFAULT_SESSION_CONSTANTS, } from "../src/lib/metrics/sessions"; import { computeProjectMetrics, } from "../src/lib/metrics/compute"; const PB_URL = process.env.NEXT_PUBLIC_PB_URL!; async function main() { const projectId = process.argv[2]; if (!projectId) throw new Error("Usage: tsx scripts/compute.ts "); const pb = new PocketBase(PB_URL); pb.autoCancellation(false); await pb.collection("_superusers").authWithPassword( process.env.PB_SUPERUSER_EMAIL!, process.env.PB_SUPERUSER_PASSWORD! ); const commits = await pb.collection("commits").getFullList({ filter: `project = "${projectId}"`, fields: "type,scope,authored_at,is_merge", }); const project = await pb.collection("projects").getOne(projectId); const constants = { sessionGapMinutes: Number((project as Record).session_gap_minutes) || DEFAULT_SESSION_CONSTANTS.sessionGapMinutes, preSessionMinutes: Number((project as Record).pre_session_minutes) || DEFAULT_SESSION_CONSTANTS.preSessionMinutes, postSessionMinutes: Number((project as Record).post_session_minutes) || DEFAULT_SESSION_CONSTANTS.postSessionMinutes, }; const metrics = computeProjectMetrics( commits.map((c) => ({ type: c.type ?? "other", scope: c.scope ?? "", authoredAt: c.authored_at, isMerge: Boolean(c.is_merge), })), constants ); console.log("Recomputed:", metrics.totalCommits, "commits,", metrics.monthly.length, "months"); console.log("Monthly:"); for (const mo of metrics.monthly) { console.log(" ", mo); } const payload = { project: projectId, computed_at: new Date().toISOString(), payload: metrics, }; const existing = await pb .collection("project_metrics") .getFirstListItem(`project = "${projectId}"`) .catch(() => null); if (existing) { await pb.collection("project_metrics").update(existing.id, payload); } else { await pb.collection("project_metrics").create(payload); } console.log("Stored."); } main().catch((e) => { console.error(e); process.exit(1); });