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}