import type { AnalyticsEvent, EventMiddlewareFn, ScreenMiddlewareFn, ScreenEvent } from '../types'; /** * Enriches every event with a fixed set of extra properties. * * ```ts * analytics.addEventMiddleware( * createPropertyEnricher({ app_version: '2.1.0', environment: 'production' }) * ); * ``` */ export function createPropertyEnricher( properties: Record ): EventMiddlewareFn { return (event, next) => { next({ ...event, properties: { ...properties, ...event.properties }, }); }; } /** * Filters out events that don't pass the predicate. * If the predicate returns false the event is dropped silently. * * ```ts * analytics.addEventMiddleware( * createEventFilter((event) => event.name !== 'internal_debug_event') * ); * ``` */ export function createEventFilter( predicate: (event: AnalyticsEvent) => boolean ): EventMiddlewareFn { return (event, next) => { if (predicate(event)) { next(event); } }; } /** * Transforms event names and/or properties before they reach adapters. * * ```ts * analytics.addEventMiddleware( * createEventTransformer((event) => ({ * ...event, * name: event.name.toLowerCase().replace(/ /g, '_'), * })) * ); * ``` */ export function createEventTransformer( transform: (event: AnalyticsEvent) => AnalyticsEvent ): EventMiddlewareFn { return (event, next) => { next(transform(event)); }; } /** * Adds UTM / attribution properties to every event. * Useful when you capture UTM params from a deep link. * * ```ts * analytics.addEventMiddleware( * createAttributionEnricher({ utm_source: 'email', utm_medium: 'newsletter' }) * ); * ``` */ export function createAttributionEnricher( attribution: Record ): EventMiddlewareFn { return (event, next) => { next({ ...event, properties: { ...event.properties, ...attribution, }, }); }; } /** * Screen middleware: filters out screens that match a blocklist. * * ```ts * analytics.addScreenMiddleware( * createScreenFilter(['Loading', 'Splash']) * ); * ``` */ export function createScreenFilter( blocklist: string[] ): ScreenMiddlewareFn { const blocked = new Set(blocklist.map((s) => s.toLowerCase())); return (event: ScreenEvent, next: (event: ScreenEvent) => void) => { if (!blocked.has(event.name.toLowerCase())) { next(event); } }; } /** * Screen middleware: enriches every screen event with extra properties. */ export function createScreenEnricher( properties: Record ): ScreenMiddlewareFn { return (event: ScreenEvent, next: (event: ScreenEvent) => void) => { next({ ...event, properties: { ...properties, ...event.properties }, }); }; }