// Klaviyo router factory. Phase 4 merge: takes the injected redis client and // the env-resolved API key/revision, returns the mounted /api/klaviyo router // (matches Caddy proxy path; no rewrite needed). import express from 'express'; import rateLimit from 'express-rate-limit'; import { requirePermission } from '../../../shared/auth/middleware.js'; import { createEventsRouter } from './events.routes.js'; import { createMetricsRouter } from './metrics.routes.js'; import { createCampaignsRouter } from './campaigns.routes.js'; import { createReportingRouter } from './reporting.routes.js'; export function createKlaviyoRouter({ redis }) { const apiKey = process.env.KLAVIYO_API_KEY; const apiRevision = process.env.KLAVIYO_API_REVISION || '2024-02-15'; if (!apiKey) { // Loud at startup; the routes themselves will 500 on every call without it. console.warn('[klaviyo] KLAVIYO_API_KEY not set — Klaviyo endpoints will fail'); } const router = express.Router(); // Phase 4 carryover from klaviyo-server: throttle the heavy /reporting/campaign-values-reports // endpoint. authenticate() already runs upstream so we don't add a per-user limiter here. const reportingLimiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 10, message: 'Too many requests to reporting endpoint, please try again later', keyGenerator: (req) => `${req.ip}-klaviyo-reporting`, skip: (req) => !req.path.includes('campaign-values-reports'), standardHeaders: true, legacyHeaders: false, }); router.use('/reporting', reportingLimiter); router.use('/events', createEventsRouter(apiKey, apiRevision, redis)); router.use('/metrics', createMetricsRouter(apiKey, apiRevision)); router.use('/campaigns', createCampaignsRouter(apiKey, apiRevision, redis)); router.use('/reporting', createReportingRouter(apiKey, apiRevision, redis)); return router; } // Re-exported so the dashboard server / future tests can attach the // klaviyo_admin gate without reaching into the events router file. export { requirePermission };