a cache for slack profile pictures and emojis
1/**
2 * Analytics wrapper utility to eliminate boilerplate in route handlers
3 */
4
5// Cache will be injected by the route system
6
7export type AnalyticsRecorder = (statusCode: number) => Promise<void>;
8export type RouteHandlerWithAnalytics = (request: Request, recordAnalytics: AnalyticsRecorder) => Promise<Response> | Response;
9
10/**
11 * Creates analytics wrapper with injected cache
12 */
13export function createAnalyticsWrapper(cache: any) {
14 return function withAnalytics(
15 path: string,
16 method: string,
17 handler: RouteHandlerWithAnalytics
18 ) {
19 return async (request: Request): Promise<Response> => {
20 const startTime = Date.now();
21
22 const recordAnalytics: AnalyticsRecorder = async (statusCode: number) => {
23 const userAgent = request.headers.get("user-agent") || "";
24 const ipAddress =
25 request.headers.get("x-forwarded-for") ||
26 request.headers.get("x-real-ip") ||
27 "unknown";
28
29 // Use the actual request URL for dynamic paths, fallback to provided path
30 const analyticsPath = path.includes(":") ? request.url : path;
31
32 await cache.recordRequest(
33 analyticsPath,
34 method,
35 statusCode,
36 userAgent,
37 ipAddress,
38 Date.now() - startTime,
39 );
40 };
41
42 return handler(request, recordAnalytics);
43 };
44 };
45}
46
47/**
48 * Type-safe analytics wrapper that automatically infers path and method
49 */
50export function createAnalyticsHandler(
51 path: string,
52 method: string
53) {
54 return (handler: RouteHandlerWithAnalytics) =>
55 withAnalytics(path, method, handler);
56}