import { PLAN_LIMITS } from "@fetcha/core"; import { db, fetchRequests, sql } from "@fetcha/db"; import type { ApiPrincipal } from "../auth"; import { monthlyUsage } from "../limits"; export function meResponse(p: ApiPrincipal) { return { project: { id: p.projectId, name: p.projectName }, organization: { id: p.organizationId, name: p.organizationName, plan: p.plan }, key: { id: p.keyId, name: p.keyName, mode: p.mode, scopes: p.scopes }, }; } export async function usageResponse(p: ApiPrincipal) { const usage = await monthlyUsage(p); const limits = PLAN_LIMITS[p.plan]; const start = new Date(); start.setUTCDate(1); start.setUTCHours(0, 0, 0, 0); const [agg] = await db .select({ total: sql`count(*)::int`, ok: sql`count(*) filter (where ${fetchRequests.status} = 'success')::int`, bytes: sql`coalesce(sum(${fetchRequests.bytesIn} + ${fetchRequests.bytesOut}), 0)::float`, p50: sql`coalesce(percentile_cont(0.5) within group (order by ${fetchRequests.latencyMs}), 0)::float`, p95: sql`coalesce(percentile_cont(0.95) within group (order by ${fetchRequests.latencyMs}), 0)::float`, }) .from(fetchRequests) .where(sql`${fetchRequests.projectId} = ${p.projectId} and ${fetchRequests.createdAt} >= ${start}`); return { period_start: start.toISOString(), plan: { id: p.plan, label: limits.label, monthly_requests: limits.monthly_requests, concurrency: limits.concurrency }, organization: { requests: usage.requests, spend_usd: round(usage.spendUsd) }, project: { requests: usage.projectRequests, spend_usd: round(usage.projectSpendUsd), successful_requests: agg?.ok ?? 0, success_rate: agg?.total ? round((agg.ok / agg.total) * 100, 1) : null, bandwidth_bytes: agg?.bytes ?? 0, latency_p50_ms: Math.round(agg?.p50 ?? 0), latency_p95_ms: Math.round(agg?.p95 ?? 0), }, remaining_requests: limits.monthly_requests >= Number.MAX_SAFE_INTEGER ? null : Math.max(0, limits.monthly_requests - usage.requests), browser: { enabled: true, concurrency: limits.browser_concurrency }, crawl: { max_pages: limits.crawl_max_pages, concurrent_jobs: limits.crawl_concurrent_jobs }, }; } function round(n: number, d = 4): number { const f = 10 ** d; return Math.round(n * f) / f; }