import { badRequest, forbidden } from "../errors";
import { billingAccountFor } from "../metering/access";
import { periodOf } from "../metering/record";
import { usageSummary } from "../metering/summary";
import { requireAccountScope } from "./http";
import type { ApiContext } from "./http";
const PERIOD = /^\d{4}-(0[1-9]|1[0-2])$/;
function periodParam(ctx: ApiContext): string {
const period = ctx.url.searchParams.get("period") ?? periodOf();
if (!PERIOD.test(period)) throw badRequest("period must be YYYY-MM");
return period;
}
/** Billing data is account-level: repo-scoped tokens (fine-grained PATs, agent tokens) may not read it (INT-A15/AZ-A5). */
export async function getUserUsage(ctx: ApiContext): Promise<Response> {
requireAccountScope(ctx);
const account = await billingAccountFor(ctx.viewer, null);
return Response.json(await usageSummary(account.accountId, periodParam(ctx)));
}
export async function getOrgUsage(ctx: ApiContext, org: string): Promise<Response> {
requireAccountScope(ctx);
let name: string;
try {
name = decodeURIComponent(org);
} catch {
throw badRequest("Invalid organization name");
}
const account = await billingAccountFor(ctx.viewer, name);
if (!account.canView) throw forbidden("Only owners can view usage for this organization");
return Response.json(await usageSummary(account.accountId, periodParam(ctx)));
}