/** * @fileoverview Statistics endpoints for Aurora API. * Provides dashboard statistics and activity aggregation data. */ import type { RouteContext, RouteModule } from "./types"; import { jsonResponse, errorResponse, withErrorHandling } from "./utils"; // Cache for activity stats (heavy aggregation) let activityPromise: Promise | null = null; let lastActivityFetch: number = 0; const ACTIVITY_CACHE_TTL = 5 * 60 * 1000; // 5 minutes /** * Stats routes handler. * * Endpoints: * - GET /api/stats - Full dashboard statistics * - GET /api/stats/activity - Activity aggregation with caching */ async function handler(ctx: RouteContext): Promise { const { pathname, method } = ctx; /** * @route GET /api/stats * @description Returns comprehensive dashboard statistics including * bot info, user counts, economy data, and leaderboards. * @response 200 - Full dashboard stats object * @response 500 - Error fetching statistics */ if (pathname === "/api/stats" && method === "GET") { return withErrorHandling(async () => { // Import the stats function from wherever it's defined // This will be passed in during initialization const { getFullDashboardStats } = await import("./stats.helper.ts"); const stats = await getFullDashboardStats(); return jsonResponse(stats); }, "fetch dashboard stats"); } /** * @route GET /api/stats/activity * @description Returns activity aggregation data with 5-minute caching. * Heavy query, results are cached to reduce database load. * @response 200 - Array of activity data points * @response 500 - Error fetching activity statistics * * @example * // Response * [ * { "date": "2024-02-08", "commands": 150, "users": 25 }, * { "date": "2024-02-07", "commands": 200, "users": 30 } * ] */ if (pathname === "/api/stats/activity" && method === "GET") { return withErrorHandling(async () => { const now = Date.now(); // If we have a valid cache, return it if (activityPromise && (now - lastActivityFetch < ACTIVITY_CACHE_TTL)) { const data = await activityPromise; return jsonResponse(data); } // Otherwise, trigger a new fetch (deduplicated by the promise) if (!activityPromise || (now - lastActivityFetch >= ACTIVITY_CACHE_TTL)) { activityPromise = (async () => { const { dashboardService } = await import("@shared/modules/dashboard/dashboard.service"); return await dashboardService.getActivityAggregation(); })(); lastActivityFetch = now; } const activity = await activityPromise; return jsonResponse(activity); }, "fetch activity stats"); } return null; } export const statsRoutes: RouteModule = { name: "stats", handler };