80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
|
|
/**
|
||
|
|
* 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 <projectId>");
|
||
|
|
|
||
|
|
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<string, unknown>).session_gap_minutes) ||
|
||
|
|
DEFAULT_SESSION_CONSTANTS.sessionGapMinutes,
|
||
|
|
preSessionMinutes:
|
||
|
|
Number((project as Record<string, unknown>).pre_session_minutes) ||
|
||
|
|
DEFAULT_SESSION_CONSTANTS.preSessionMinutes,
|
||
|
|
postSessionMinutes:
|
||
|
|
Number((project as Record<string, unknown>).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); });
|