a cache for slack profile pictures and emojis
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100/** * Analytics wrapper utility to eliminate boilerplate in route handlers */
import type { SlackCache } from "../cache";import { addCorsHeaders, corsPreflightResponse } from "./cors";import { fastPathname } from "./fast-url";import { internalErrorResponse } from "./http-errors";
export type AnalyticsRecorder = (statusCode: number) => void;export type RouteHandlerWithAnalytics = ( request: Request, recordAnalytics: AnalyticsRecorder,) => Promise<Response> | Response;
async function runHandler( handler: RouteHandlerWithAnalytics, request: Request, recordAnalytics: AnalyticsRecorder,): Promise<Response> { try { return await handler(request, recordAnalytics); } catch (error) { console.error("API request failed:", error); recordAnalytics(500); return internalErrorResponse(); }}
/** * Creates analytics wrapper with injected cache. * Pre-computes static values at registration time to minimize per-request work. */export function createAnalyticsWrapper(cache: SlackCache) { return function withAnalytics( path: string, _method: string, handler: RouteHandlerWithAnalytics, ) { const isDynamic = path.includes(":"); const skipAnalytics = path === "/health";
// For static paths, pre-bind everything so the recorder is near-zero cost if (!skipAnalytics && !isDynamic) { return async (request: Request): Promise<Response> => { if (request.method === "OPTIONS") return corsPreflightResponse();
const startTime = performance.now(); const userAgent = request.headers.get("user-agent") || ""; const referer = request.headers.get("referer") || undefined;
const recordAnalytics: AnalyticsRecorder = (statusCode) => { cache.recordRequest( path, statusCode, userAgent, performance.now() - startTime, referer, ); };
const response = await runHandler(handler, request, recordAnalytics); return addCorsHeaders(response); }; }
// Skip analytics entirely for health checks if (skipAnalytics) { return async (request: Request): Promise<Response> => { if (request.method === "OPTIONS") return corsPreflightResponse(); const noop: AnalyticsRecorder = () => {}; const response = await runHandler(handler, request, noop); return addCorsHeaders(response); }; }
// Dynamic paths: need URL parsing return async (request: Request): Promise<Response> => { if (request.method === "OPTIONS") return corsPreflightResponse();
const startTime = performance.now(); const userAgent = request.headers.get("user-agent") || ""; const referer = request.headers.get("referer") || undefined;
const recordAnalytics: AnalyticsRecorder = (statusCode) => { cache.recordRequest( fastPathname(request.url), statusCode, userAgent, performance.now() - startTime, referer, ); };
const response = await runHandler(handler, request, recordAnalytics); return addCorsHeaders(response); }; };}