import { getSupabaseAdmin } from '@/lib/supabase/admin'; export type AdminMetrics = { totalUsers: number; totalTunnels: number; activeTunnels: number; inactiveTunnels: number; overQuota: number; bytesUsedTotal: number; quotaTotal: number; signups7d: number; signups30d: number; recentlyActive: number; }; type TunnelAgg = { is_active: boolean; bytes_used: number; quota_bytes: number; last_seen_at: string | null; }; export async function computeMetrics(): Promise { const admin = getSupabaseAdmin(); const { data: tunnelsData } = await admin .from('tunnels') .select('is_active, bytes_used, quota_bytes, last_seen_at'); const tunnels = (tunnelsData ?? []) as TunnelAgg[]; const now = Date.now(); const day = 24 * 60 * 60 * 1000; let activeTunnels = 0; let inactiveTunnels = 0; let overQuota = 0; let bytesUsedTotal = 0; let quotaTotal = 0; let recentlyActive = 0; for (const t of tunnels) { if (t.is_active) activeTunnels++; else inactiveTunnels++; if (t.quota_bytes > 0 && t.bytes_used >= t.quota_bytes) overQuota++; bytesUsedTotal += Number(t.bytes_used) || 0; quotaTotal += Number(t.quota_bytes) || 0; if (t.last_seen_at && now - new Date(t.last_seen_at).getTime() <= day) { recentlyActive++; } } let totalUsers = 0; let signups7d = 0; let signups30d = 0; const perPage = 1000; for (let page = 1; page <= 50; page++) { const { data, error } = await admin.auth.admin.listUsers({ page, perPage }); if (error) break; const users = data.users; if (users.length === 0) break; totalUsers += users.length; for (const u of users) { const created = new Date(u.created_at).getTime(); if (now - created <= 7 * day) signups7d++; if (now - created <= 30 * day) signups30d++; } if (users.length < perPage) break; } return { totalUsers, totalTunnels: tunnels.length, activeTunnels, inactiveTunnels, overQuota, bytesUsedTotal, quotaTotal, signups7d, signups30d, recentlyActive, }; }