/ server / api / external / stats.get.ts
stats.get.ts
 1  import { PrismaClient } from "@prisma/client";
 2  import { H3Event } from "h3";
 3  import { TimeRangeEnum } from "~~/lib/stats";
 4  import type { TimeRange } from "~~/lib/stats";
 5  import { z } from "zod";
 6  import { calculateStats } from "~~/server/utils/stats";
 7  import { handleApiError} from "~~/server/utils/logging";
 8  
 9  const prisma = new PrismaClient();
10  
11  const apiKeySchema = z.string().uuid();
12  
13  export default defineEventHandler(async (event: H3Event) => {
14    try {
15      const authHeader = getHeader(event, "authorization");
16      if (!authHeader || !authHeader.startsWith("Bearer ")) {
17        throw handleApiError(401, "External Stats API: Missing or invalid API key format in header.", "API key is missing or improperly formatted.");
18      }
19  
20      const apiKey = authHeader.substring(7);
21      const validationResult = apiKeySchema.safeParse(apiKey);
22  
23      if (!validationResult.success) {
24        throw handleApiError(401, `External Stats API: Invalid API key format. Key prefix: ${apiKey.substring(0,4)}...`, "Invalid API key format.");
25      }
26  
27      const user = await prisma.user.findUnique({
28        where: { apiKey },
29        select: { id: true, apiKey: true },
30      });
31  
32      if (!user || user.apiKey !== apiKey) {
33        throw handleApiError(401, `External Stats API: Invalid API key. Key prefix: ${apiKey.substring(0,4)}...`, "Invalid API key.");
34      }
35  
36      const query = getQuery(event);
37      const timeRange = String(query.timeRange || "today");
38      const midnightOffsetSeconds = query.midnightOffsetSeconds ? Number(query.midnightOffsetSeconds) : undefined;
39  
40      if (!Object.values(TimeRangeEnum).includes(timeRange as any)) {
41        throw handleApiError(400, `External Stats API: Invalid timeRange value: ${timeRange}. User ID: ${user.id}`, "Invalid time range specified.");
42      }
43  
44      return await calculateStats(user.id, timeRange as TimeRange, midnightOffsetSeconds);
45    } catch (error: any) {
46      if (error && typeof error === "object" && error.statusCode) throw error;
47      const detailedMessage = error instanceof Error ? error.message : "An unknown error occurred fetching external stats.";
48      const apiKeyPrefix = getHeader(event, "authorization")?.substring(7,11) || "UNKNOWN";
49      throw handleApiError(500, `External Stats API: Failed to fetch statistics. API Key prefix: ${apiKeyPrefix}... Error: ${detailedMessage}`, "Failed to fetch statistics.");
50    }
51  });