@tracelog/lib 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/cjs/handlers/click.handler.js +1 -1
- package/dist/cjs/handlers/performance.handler.js +1 -1
- package/dist/cjs/types/test-bridge.types.d.ts +9 -9
- package/dist/cjs/utils/browser/qa-mode.utils.js +1 -1
- package/dist/cjs/utils/emitter.utils.d.ts +1 -1
- package/dist/cjs/utils/network/url.utils.d.ts +1 -1
- package/dist/esm/handlers/click.handler.js +1 -1
- package/dist/esm/handlers/performance.handler.js +1 -1
- package/dist/esm/types/test-bridge.types.d.ts +9 -9
- package/dist/esm/utils/browser/qa-mode.utils.js +1 -1
- package/dist/esm/utils/emitter.utils.d.ts +1 -1
- package/dist/esm/utils/network/url.utils.d.ts +1 -1
- package/package.json +9 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracelog.esm.js","sources":["../../src/constants/config.constants.ts","../../src/types/config.types.ts","../../src/types/device.types.ts","../../src/types/emitter.types.ts","../../src/types/event.types.ts","../../src/types/mode.types.ts","../../src/types/validation-error.types.ts","../../src/utils/logging.utils.ts","../../src/utils/browser/device-detector.utils.ts","../../src/constants/storage.constants.ts","../../src/constants/performance.constants.ts","../../src/constants/error.constants.ts","../../src/utils/browser/qa-mode.utils.ts","../../src/utils/browser/utm-params.utils.ts","../../src/utils/data/uuid.utils.ts","../../src/utils/network/url.utils.ts","../../src/utils/security/sanitize.utils.ts","../../src/utils/validations/config-validations.utils.ts","../../src/utils/validations/type-guards.utils.ts","../../src/utils/validations/metadata-validations.utils.ts","../../src/utils/validations/event-validations.utils.ts","../../src/utils/emitter.utils.ts","../../src/managers/state.manager.ts","../../src/managers/sender.manager.ts","../../src/managers/event.manager.ts","../../src/managers/user.manager.ts","../../src/managers/session.manager.ts","../../src/handlers/session.handler.ts","../../src/handlers/page-view.handler.ts","../../src/handlers/click.handler.ts","../../src/handlers/scroll.handler.ts","../../src/integrations/google-analytics.integration.ts","../../src/managers/storage.manager.ts","../../src/handlers/performance.handler.ts","../../src/handlers/error.handler.ts","../../src/app.ts","../../src/api.ts","../../src/app.constants.ts","../../src/public-api.ts","../../node_modules/web-vitals/dist/web-vitals.js"],"sourcesContent":["/**\n * Consolidated configuration constants for TraceLog\n * This file centralizes all timing, limits, browser, and initialization constants\n */\n\n// ============================================================================\n// SESSION & TIMING\n// ============================================================================\n\nexport const DEFAULT_SESSION_TIMEOUT = 15 * 60 * 1000; // 15 minutes\nexport const DUPLICATE_EVENT_THRESHOLD_MS = 500; // 500ms\nexport const EVENT_SENT_INTERVAL_MS = 10000; // 10 seconds\n\n// Throttling and debouncing\nexport const SCROLL_DEBOUNCE_TIME_MS = 250;\nexport const DEFAULT_VISIBILITY_TIMEOUT_MS = 2000;\n\n// Event expiry\nexport const EVENT_EXPIRY_HOURS = 24;\nexport const EVENT_PERSISTENCE_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// ============================================================================\n// LIMITS & RETRIES\n// ============================================================================\n\nexport const MAX_EVENTS_QUEUE_LENGTH = 100;\nexport const MAX_RETRIES = 3;\nexport const RETRY_DELAY_MS = 5000;\nexport const REQUEST_TIMEOUT_MS = 10000;\nexport const MAX_METADATA_SIZE = 5000;\n\n// Motion and interaction thresholds\nexport const DEFAULT_MOTION_THRESHOLD = 2;\nexport const SIGNIFICANT_SCROLL_DELTA = 10;\nexport const MIN_SCROLL_DEPTH_CHANGE = 5;\nexport const SCROLL_MIN_EVENT_INTERVAL_MS = 500;\nexport const MAX_SCROLL_EVENTS_PER_SESSION = 120;\n\n// Sampling and rate limits\nexport const DEFAULT_SAMPLING_RATE = 1;\nexport const MIN_SAMPLING_RATE = 0;\nexport const MAX_SAMPLING_RATE = 1;\nexport const RATE_LIMIT_WINDOW_MS = 1000; // 1 second window\nexport const MAX_EVENTS_PER_SECOND = 200; // Maximum 200 events per second\n\n// Queue and batch limits\nexport const BATCH_SIZE_THRESHOLD = 50;\nexport const MAX_PENDING_EVENTS_BUFFER = 100; // Maximum events to buffer before session init\n\n// Session timeout validation limits\nexport const MIN_SESSION_TIMEOUT_MS = 30000; // 30 seconds minimum\nexport const MAX_SESSION_TIMEOUT_MS = 86400000; // 24 hours maximum\n\n// Custom event validation limits\nexport const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;\nexport const MAX_CUSTOM_EVENT_STRING_SIZE = 8 * 1024; // 8KB\nexport const MAX_CUSTOM_EVENT_KEYS = 10;\nexport const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;\nexport const MAX_NESTED_OBJECT_KEYS = 20; // Maximum keys in nested objects within arrays\n\n// Text content limits\nexport const MAX_TEXT_LENGTH = 255; // For click tracking text content\n\n// Data sanitization limits\nexport const MAX_STRING_LENGTH = 1000;\nexport const MAX_ARRAY_LENGTH = 100;\nexport const MAX_OBJECT_DEPTH = 3;\n\n// Precision for numeric metrics\nexport const PRECISION_TWO_DECIMALS = 2 as const;\n\n// Sync XHR timeout\nexport const SYNC_XHR_TIMEOUT_MS = 2000; // 2 seconds\n\n// Event fingerprint management\nexport const MAX_FINGERPRINTS = 1000; // Maximum fingerprints stored before cleanup\nexport const FINGERPRINT_CLEANUP_MULTIPLIER = 10; // Cleanup fingerprints older than 10x threshold\nexport const MAX_FINGERPRINTS_HARD_LIMIT = 2000; // Hard limit for aggressive cleanup\n\n// ============================================================================\n// BROWSER & HTML\n// ============================================================================\n\nexport const HTML_DATA_ATTR_PREFIX = 'data-tlog';\n\n// Interactive element selectors for click tracking\nexport const INTERACTIVE_SELECTORS = [\n 'button',\n 'a',\n 'input[type=\"button\"]',\n 'input[type=\"submit\"]',\n 'input[type=\"reset\"]',\n 'input[type=\"checkbox\"]',\n 'input[type=\"radio\"]',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[routerLink]',\n '[ng-click]',\n '[data-action]',\n '[data-click]',\n '[data-navigate]',\n '[data-toggle]',\n '[onclick]',\n '.btn',\n '.button',\n '.clickable',\n '.nav-link',\n '.menu-item',\n '[data-testid]',\n '[tabindex=\"0\"]',\n] as const;\n\n// UTM parameters for tracking\nexport const UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];\n\n// ============================================================================\n// ============================================================================\n// INITIALIZATION\n// ============================================================================\n\nexport const INITIALIZATION_MAX_CONCURRENT_RETRIES = 20;\nexport const INITIALIZATION_CONCURRENT_RETRY_DELAY_MS = 50;\nexport const INITIALIZATION_TIMEOUT_MS = 10000;\n\n// ============================================================================\n// SESSION MANAGEMENT\n// ============================================================================\n\nexport const SESSION_SYNC_TIMEOUT_MS = 2000;\nexport const SESSION_MAX_RETRY_ATTEMPTS = 3;\nexport const SESSION_CLEANUP_DELAY_MS = 100;\n\n// Cross-tab coordination\nexport const CROSS_TAB_INITIALIZATION_LOCK_TIMEOUT_MS = 5000;\nexport const TAB_HEARTBEAT_INTERVAL_MS = 5000; // 5 seconds\nexport const TAB_ELECTION_TIMEOUT_MS = 2000; // 2 seconds\nexport const TAB_CLEANUP_DELAY_MS = 1000; // 1 second\n\n// Session recovery\nexport const SESSION_RECOVERY_WINDOW_MULTIPLIER = 2; // 2x session timeout\nexport const MAX_SESSION_RECOVERY_ATTEMPTS = 3;\nexport const MAX_SESSION_RECOVERY_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours max\nexport const MIN_SESSION_RECOVERY_WINDOW_MS = 2 * 60 * 1000; // 2 minutes minimum\n\n// ============================================================================\n// SCROLL SUPPRESSION\n// ============================================================================\n\nexport const SCROLL_SUPPRESS_MULTIPLIER = 2;\n\n// ============================================================================\n// NETWORK TIMING\n// ============================================================================\n\nexport const RETRY_BACKOFF_INITIAL = 1000; // 1 second\nexport const RETRY_BACKOFF_MAX = 30_000; // 30 seconds\nexport const RATE_LIMIT_INTERVAL = 1000; // 1 second\nexport const MAX_RETRY_ATTEMPTS = 10;\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n// Validation error messages - standardized across all layers\nexport const VALIDATION_MESSAGES = {\n MISSING_PROJECT_ID: 'Project ID is required',\n PROJECT_ID_EMPTY_AFTER_TRIM: 'Project ID is required',\n INVALID_SESSION_TIMEOUT: `Session timeout must be between ${MIN_SESSION_TIMEOUT_MS}ms (30 seconds) and ${MAX_SESSION_TIMEOUT_MS}ms (24 hours)`,\n INVALID_SAMPLING_RATE: 'Sampling rate must be between 0 and 1',\n INVALID_ERROR_SAMPLING_RATE: 'Error sampling must be between 0 and 1',\n INVALID_TRACELOG_PROJECT_ID: 'TraceLog project ID is required when integration is enabled',\n INVALID_CUSTOM_API_URL: 'Custom API URL is required when integration is enabled',\n INVALID_GOOGLE_ANALYTICS_ID: 'Google Analytics measurement ID is required when integration is enabled',\n INVALID_SCROLL_CONTAINER_SELECTORS: 'Scroll container selectors must be valid CSS selectors',\n INVALID_GLOBAL_METADATA: 'Global metadata must be an object',\n INVALID_SENSITIVE_QUERY_PARAMS: 'Sensitive query params must be an array of strings',\n} as const;\n\n// ============================================================================\n// SECURITY\n// ============================================================================\n\n// XSS protection patterns\nexport const XSS_PATTERNS = [\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n /javascript:/gi,\n /on\\w+\\s*=/gi,\n /<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi,\n /<embed\\b[^>]*>/gi,\n /<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi,\n] as const;\n","import { MetadataType } from './common.types';\n\nexport interface Config {\n /** Session inactivity timeout in milliseconds. @default 900000 */\n sessionTimeout?: number;\n /** Metadata appended to every tracked event. */\n globalMetadata?: Record<string, MetadataType>;\n /** Selectors defining custom scroll containers to monitor. */\n scrollContainerSelectors?: string | string[];\n /** Query parameters to remove before tracking URLs. */\n sensitiveQueryParams?: string[];\n /** Error event sampling rate between 0 and 1. */\n errorSampling?: number;\n /** Event sampling rate between 0 and 1. */\n samplingRate?: number;\n /** Optional configuration for third-party integrations. */\n integrations?: {\n /** TraceLog integration options. */\n tracelog?: {\n /** Required project ID TraceLog SaaS integration. */\n projectId: string;\n };\n /** Custom integration options. */\n custom?: {\n /** Endpoint for collecting events. */\n collectApiUrl: string;\n /** Allow HTTP URLs (not recommended for production). @default false */\n allowHttp?: boolean;\n };\n /** Google Analytics integration options. */\n googleAnalytics?: {\n /** Required measurement ID for Google Analytics. */\n measurementId: string;\n };\n };\n}\n\nexport enum SpecialApiUrl {\n Localhost = 'localhost:8080',\n Fail = 'localhost:9999',\n}\n","export enum DeviceType {\n Mobile = 'mobile',\n Tablet = 'tablet',\n Desktop = 'desktop',\n Unknown = 'unknown',\n}\n","import { EventData } from './event.types';\nimport { BaseEventsQueueDto } from './queue.types';\n\nexport type EmitterCallback<T = any> = (data: T) => void;\n\nexport enum EmitterEvent {\n EVENT = 'event',\n QUEUE = 'queue',\n}\n\nexport interface EmitterMap {\n [EmitterEvent.EVENT]: EventData;\n [EmitterEvent.QUEUE]: BaseEventsQueueDto;\n}\n","import { MetadataType } from './common.types';\nimport { SessionEndReason } from './session.types';\n\nexport type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB' | 'LONG_TASK';\n\nexport enum EventType {\n PAGE_VIEW = 'page_view',\n CLICK = 'click',\n SCROLL = 'scroll',\n SESSION_START = 'session_start',\n SESSION_END = 'session_end',\n CUSTOM = 'custom',\n WEB_VITALS = 'web_vitals',\n ERROR = 'error',\n}\n\nexport enum ScrollDirection {\n UP = 'up',\n DOWN = 'down',\n}\n\nexport enum ErrorType {\n JS_ERROR = 'js_error',\n PROMISE_REJECTION = 'promise_rejection',\n}\n\nexport interface ScrollData {\n depth: number;\n direction: ScrollDirection;\n}\n\nexport interface ClickData {\n x: number;\n y: number;\n relativeX: number;\n relativeY: number;\n id?: string;\n class?: string;\n tag?: string;\n text?: string;\n href?: string;\n title?: string;\n alt?: string;\n role?: string;\n ariaLabel?: string;\n dataAttributes?: Record<string, string>;\n}\n\nexport type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;\n\nexport interface ClickTrackingElementData {\n element: HTMLElement;\n name: string;\n value?: string;\n}\n\nexport interface CustomEventData {\n name: string;\n metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n}\n\nexport interface WebVitalsData {\n type: WebVitalType;\n value: number;\n}\n\nexport interface ErrorData {\n type: ErrorType;\n message: string;\n filename?: string;\n line?: number;\n column?: number;\n}\n\nexport interface UTM {\n source?: string;\n medium?: string;\n campaign?: string;\n term?: string;\n content?: string;\n}\n\nexport interface PageViewData {\n referrer?: string;\n title?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}\n\nexport interface EventData {\n id: string;\n type: EventType;\n page_url: string;\n timestamp: number;\n referrer?: string;\n from_page_url?: string;\n scroll_data?: ScrollData;\n click_data?: ClickData;\n custom_event?: CustomEventData;\n web_vitals?: WebVitalsData;\n page_view?: PageViewData;\n session_end_reason?: SessionEndReason;\n error_data?: ErrorData;\n utm?: UTM;\n}\n","/**\n * App modes for the TraceLog Library\n */\nexport enum Mode {\n QA = 'qa',\n}\n","/**\n * Custom error classes for TraceLog validation errors\n * Provides better error handling and consistency across validation layers\n */\n\n/**\n * Base class for all TraceLog validation errors\n */\nexport abstract class TraceLogValidationError extends Error {\n constructor(\n message: string,\n public readonly errorCode: string,\n public readonly layer: 'config' | 'app' | 'runtime',\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when app configuration validation fails\n */\nexport class AppConfigValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'APP_CONFIG_INVALID', layer);\n }\n}\n\n/**\n * Thrown when session timeout validation fails\n */\nexport class SessionTimeoutValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SESSION_TIMEOUT_INVALID', layer);\n }\n}\n\n/**\n * Thrown when sampling rate validation fails\n */\nexport class SamplingRateValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SAMPLING_RATE_INVALID', layer);\n }\n}\n\n/**\n * Thrown when integrations validation fails\n */\nexport class IntegrationValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'INTEGRATION_INVALID', layer);\n }\n}\n\n/**\n * Thrown when initialization exceeds the maximum allowed timeout\n */\nexport class InitializationTimeoutError extends TraceLogValidationError {\n constructor(\n message: string,\n public readonly timeoutMs: number,\n layer: 'config' | 'app' | 'runtime' = 'runtime',\n ) {\n super(message, 'INITIALIZATION_TIMEOUT', layer);\n }\n}\n","export const formatLogMsg = (msg: string, error?: unknown): string => {\n if (error) {\n // In production, sanitize error messages to avoid exposing sensitive paths\n if (process.env.NODE_ENV !== 'dev' && error instanceof Error) {\n // Remove file paths and line numbers from error messages\n const sanitizedMessage = error.message.replace(/\\s+at\\s+.*$/gm, '').replace(/\\(.*?:\\d+:\\d+\\)/g, '');\n return `[TraceLog] ${msg}: ${sanitizedMessage}`;\n }\n return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : 'Unknown error'}`;\n }\n\n return `[TraceLog] ${msg}`;\n};\n\n/**\n * Safe logging utility that respects production environment\n *\n * @param type - Log level (info, warn, error, debug)\n * @param msg - Message to log\n * @param extra - Optional extra data\n *\n * Production behavior:\n * - debug: Never logged in production\n * - info: Only logged if showToClient=true\n * - warn: Always logged (important for debugging production issues)\n * - error: Always logged\n * - Stack traces are sanitized\n * - Data objects are sanitized\n */\nexport const log = (\n type: 'info' | 'warn' | 'error' | 'debug',\n msg: string,\n extra?: { error?: unknown; data?: Record<string, unknown>; showToClient?: boolean },\n): void => {\n const { error, data, showToClient = false } = extra ?? {};\n const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;\n const method = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';\n\n // Production logging strategy:\n // - Development: Log everything\n // - Production:\n // - debug: never logged\n // - info: only if showToClient=true\n // - warn: always logged (critical for debugging)\n // - error: always logged\n const isProduction = process.env.NODE_ENV !== 'dev';\n\n if (isProduction) {\n // Never log debug in production\n if (type === 'debug') {\n return;\n }\n\n // Log info only if explicitly flagged\n if (type === 'info' && !showToClient) {\n return;\n }\n\n // warn and error always logged in production\n }\n\n // In production, sanitize data to avoid exposing sensitive information\n if (isProduction && data !== undefined) {\n const sanitizedData = sanitizeLogData(data);\n console[method](formattedMsg, sanitizedData);\n } else if (data !== undefined) {\n console[method](formattedMsg, data);\n } else {\n console[method](formattedMsg);\n }\n};\n\n/**\n * Sanitizes log data in production to prevent sensitive information leakage\n * Simple approach: redact sensitive keys only\n */\nconst sanitizeLogData = (data: Record<string, unknown>): Record<string, unknown> => {\n const sanitized: Record<string, unknown> = {};\n const sensitiveKeys = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'sessionid', 'session_id'];\n\n for (const [key, value] of Object.entries(data)) {\n const lowerKey = key.toLowerCase();\n\n // Redact sensitive keys\n if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {\n sanitized[key] = '[REDACTED]';\n } else {\n sanitized[key] = value;\n }\n }\n\n return sanitized;\n};\n","import { DeviceType } from '../../types/device.types';\nimport { log } from '../logging.utils';\n\nlet coarsePointerQuery: MediaQueryList | undefined;\nlet noHoverQuery: MediaQueryList | undefined;\n\nconst initMediaQueries = (): void => {\n if (typeof window !== 'undefined' && !coarsePointerQuery) {\n coarsePointerQuery = window.matchMedia('(pointer: coarse)');\n noHoverQuery = window.matchMedia('(hover: none)');\n }\n};\n\ninterface NavigatorWithUserAgentData extends Navigator {\n userAgentData?: {\n mobile: boolean;\n platform?: string;\n };\n}\n\n/**\n * Detects the device type based on screen size, user agent, and browser capabilities\n * @returns The detected device type\n */\nexport const getDeviceType = (): DeviceType => {\n try {\n const nav = navigator as NavigatorWithUserAgentData;\n\n if (nav.userAgentData && typeof nav.userAgentData.mobile === 'boolean') {\n if (nav.userAgentData.platform && /ipad|tablet/i.test(nav.userAgentData.platform)) {\n return DeviceType.Tablet;\n }\n\n const result = nav.userAgentData.mobile ? DeviceType.Mobile : DeviceType.Desktop;\n return result;\n }\n\n initMediaQueries();\n\n const width = window.innerWidth;\n const hasCoarsePointer = coarsePointerQuery?.matches ?? false;\n const hasNoHover = noHoverQuery?.matches ?? false;\n const hasTouchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const ua = navigator.userAgent.toLowerCase();\n const isMobileUA = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(ua);\n const isTabletUA = /tablet|ipad|android(?!.*mobile)/.test(ua);\n\n if (width <= 767 || (isMobileUA && hasTouchSupport)) {\n return DeviceType.Mobile;\n }\n\n if ((width >= 768 && width <= 1024) || isTabletUA || (hasCoarsePointer && hasNoHover && hasTouchSupport)) {\n return DeviceType.Tablet;\n }\n\n return DeviceType.Desktop;\n } catch (error) {\n log('warn', 'Device detection failed, defaulting to desktop', { error });\n\n return DeviceType.Desktop;\n }\n};\n","export const STORAGE_BASE_KEY = 'tlog';\nexport const QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;\nexport const USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;\n\nexport const QUEUE_KEY = (id: string): string => (id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`);\nexport const SESSION_STORAGE_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;\n\n// Cross-tab session management storage keys\nexport const CROSS_TAB_SESSION_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:cross_tab_session` : `${STORAGE_BASE_KEY}:cross_tab_session`;\nexport const TAB_INFO_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:tab_info` : `${STORAGE_BASE_KEY}:tab_info`;\n\nexport const TAB_SPECIFIC_INFO_KEY = (projectId: string, tabId: string): string =>\n `${STORAGE_BASE_KEY}:${projectId}:tab:${tabId}:info`;\nexport const SESSION_RECOVERY_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:recovery` : `${STORAGE_BASE_KEY}:recovery`;\n\n// BroadcastChannel name for cross-tab communication\nexport const BROADCAST_CHANNEL_NAME = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;\n","/**\n * Performance monitoring and web vitals constants for TraceLog\n * Centralizes thresholds and configuration for performance tracking\n */\n\nimport { WebVitalType } from '../types';\n\n// ============================================================================\n// WEB VITALS THRESHOLDS\n// ============================================================================\n\n/**\n * Web Vitals thresholds in milliseconds (except CLS which is unitless)\n * These define the minimum values required to report a web vital metric\n *\n * Based on Core Web Vitals standards:\n * - LCP (Largest Contentful Paint): 4000ms threshold (poor threshold)\n * - FCP (First Contentful Paint): 1800ms threshold (good threshold)\n * - CLS (Cumulative Layout Shift): 0.25 threshold (unitless, needs improvement threshold)\n * - INP (Interaction to Next Paint): 200ms threshold (good threshold)\n * - TTFB (Time to First Byte): 800ms threshold (good/needs improvement boundary, aligned with Web Vitals standard)\n * - LONG_TASK: 50ms threshold for long task detection\n */\nexport const WEB_VITALS_THRESHOLDS: Record<WebVitalType, number> = {\n LCP: 4000,\n FCP: 1800,\n CLS: 0.25,\n INP: 200,\n TTFB: 800,\n LONG_TASK: 50,\n} as const;\n\n// ============================================================================\n// PERFORMANCE MONITORING LIMITS\n// ============================================================================\n\n/**\n * Long task throttling interval in milliseconds\n * Prevents excessive long task events from being sent\n */\nexport const LONG_TASK_THROTTLE_MS = 1000;\n\n/**\n * Precision for performance metric values\n * All performance metrics are rounded to 2 decimal places\n */\nexport const PERFORMANCE_PRECISION_DECIMALS = 2 as const;\n","/**\n * Error handling and PII sanitization constants for TraceLog\n * Centralizes patterns and limits for error tracking and data protection\n */\n\n// ============================================================================\n// PII SANITIZATION PATTERNS\n// ============================================================================\n\n/**\n * Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)\n * These patterns are used to replace sensitive information with [REDACTED] in error messages\n */\nexport const PII_PATTERNS = [\n // Email addresses\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/gi,\n\n // US Phone numbers (various formats)\n /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n\n // Credit card numbers (16 digits with optional separators)\n /\\b\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/g,\n\n // IBAN (International Bank Account Number)\n /\\b[A-Z]{2}\\d{2}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/gi,\n\n // API keys/tokens (sk_test_, sk_live_, pk_test_, pk_live_, etc.)\n /\\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\\b/gi,\n\n // Bearer tokens (JWT-like patterns - matches complete and partial tokens)\n /Bearer\\s+[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)?(?:\\.[A-Za-z0-9_-]+)?/gi,\n\n // Passwords in connection strings (protocol://user:password@host)\n /:\\/\\/[^:/]+:([^@]+)@/gi,\n] as const;\n\n// ============================================================================\n// ERROR TRACKING LIMITS\n// ============================================================================\n\n/**\n * Maximum length for error messages before truncation\n * Prevents extremely long error messages from consuming excessive storage\n */\nexport const MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Time window for error suppression in milliseconds\n * Prevents duplicate errors from flooding the system within this timeframe\n */\nexport const ERROR_SUPPRESSION_WINDOW_MS = 5_000; // 5 seconds\n\n/**\n * Maximum number of unique errors to track for suppression\n * Prevents memory usage from growing indefinitely\n */\nexport const MAX_TRACKED_ERRORS = 50;\n\n/**\n * Hard limit for error tracking before aggressive cleanup\n * If this limit is exceeded, the entire error map is cleared\n */\nexport const MAX_TRACKED_ERRORS_HARD_LIMIT = MAX_TRACKED_ERRORS * 2;\n\n// ============================================================================\n// ERROR SAMPLING\n// ============================================================================\n\n/**\n * Default error sampling rate\n * Controls what percentage of errors are actually reported\n */\nexport const DEFAULT_ERROR_SAMPLING_RATE = 0.1; // 10% of errors\n","import { QA_MODE_KEY } from '@/constants';\nimport { log } from '../logging.utils';\n\nconst QA_MODE_PARAM = 'tlog_mode';\nconst QA_MODE_VALUE = 'qa';\n\n/**\n * Detects if QA mode should be active based on URL query parameter or sessionStorage\n *\n * Detection flow:\n * 1. Check if already active in sessionStorage\n * 2. Check for ?tlog_mode=qa query parameter\n * 3. If found in URL:\n * - Persist to sessionStorage\n * - Clean param from URL\n *\n * @returns True if QA mode is active, false otherwise\n */\nexport const detectQaMode = (): boolean => {\n const stored = sessionStorage.getItem(QA_MODE_KEY);\n\n if (stored === 'true') {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const modeParam = params.get(QA_MODE_PARAM);\n const isQaMode = modeParam === QA_MODE_VALUE;\n\n if (isQaMode) {\n sessionStorage.setItem(QA_MODE_KEY, 'true');\n\n params.delete(QA_MODE_PARAM);\n\n const newSearch = params.toString();\n const newUrl = `${window.location.pathname}${newSearch ? '?' + newSearch : ''}${window.location.hash}`;\n\n try {\n window.history.replaceState({}, '', newUrl);\n } catch (error) {\n log('warn', 'History API not available, cannot replace URL', { error });\n }\n\n console.log(\n '%c[TraceLog] QA Mode ACTIVE',\n 'background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;',\n );\n }\n\n return isQaMode;\n};\n","import { UTM_PARAMS } from '../../constants';\nimport { UTM } from '../../types/event.types';\n\n/**\n * Extracts UTM parameters from the current URL\n * @returns UTM parameters object or undefined if none found\n */\nexport const getUTMParameters = (): UTM | undefined => {\n const urlParams = new URLSearchParams(window.location.search);\n const utmParams: Partial<Record<keyof UTM, string>> = {};\n\n UTM_PARAMS.forEach((param) => {\n const value = urlParams.get(param);\n\n if (value) {\n const key = param.split('utm_')[1] as keyof UTM;\n utmParams[key] = value;\n }\n });\n\n const result = Object.keys(utmParams).length ? utmParams : undefined;\n\n return result;\n};\n","/**\n * Generates a RFC4122 compliant UUID v4 using native crypto API with fallback\n * @returns A UUID string\n */\nexport const generateUUID = (): string => {\n // Use native crypto.randomUUID() if available (modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * Generates a unique event ID optimized for high-frequency event tracking\n *\n * Uses a simple hybrid approach:\n * - Timestamp for temporal ordering\n * - Random component for uniqueness across tabs/processes\n *\n * Format: {timestamp}-{random}\n * Example: \"1704067200000-a3f9c2b1\"\n *\n * @returns Unique event ID string\n */\nexport const generateEventId = (): string => {\n const timestamp = Date.now();\n\n // Generate 8 random hex chars (32 bits entropy)\n let random = '';\n try {\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const bytes = crypto.getRandomValues(new Uint8Array(4));\n if (bytes) {\n random = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n }\n } catch {\n // crypto failed, use fallback\n }\n\n // Fallback to Math.random if crypto unavailable\n if (!random) {\n random = Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, '0');\n }\n\n return `${timestamp}-${random}`;\n};\n","import { Config } from '@/types';\nimport { log } from '../logging.utils';\n\n/**\n * Validates if a URL is valid and optionally allows HTTP URLs\n * @param url - The URL to validate\n * @param allowHttp - Whether to allow HTTP URLs (default: false)\n * @returns True if the URL is valid, false otherwise\n */\nconst isValidUrl = (url: string, allowHttp = false): boolean => {\n try {\n const parsed = new URL(url);\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n return isHttps || (allowHttp && isHttp);\n } catch {\n return false;\n }\n};\n\n/**\n * Generates an API URL based on project ID and current domain\n * @param id - The project ID\n * @returns The generated API URL\n */\nexport const getCollectApiUrl = (config: Config): string => {\n if (config.integrations?.tracelog?.projectId) {\n const url = new URL(window.location.href);\n const host = url.hostname;\n const parts = host.split('.');\n\n if (parts.length === 0) {\n throw new Error('Invalid URL');\n }\n\n const projectId = config.integrations.tracelog.projectId;\n const cleanDomain = parts.slice(-2).join('.');\n const collectApiUrl = `https://${projectId}.${cleanDomain}/collect`;\n const isValid = isValidUrl(collectApiUrl);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n const collectApiUrl = config.integrations?.custom?.collectApiUrl;\n\n if (collectApiUrl) {\n const allowHttp = config.integrations?.custom?.allowHttp ?? false;\n const isValid = isValidUrl(collectApiUrl, allowHttp);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n return '';\n};\n\n/**\n * Normalizes a URL by removing sensitive query parameters\n * @param url - The URL to normalize\n * @param sensitiveQueryParams - Array of parameter names to remove\n * @returns The normalized URL\n */\nexport const normalizeUrl = (url: string, sensitiveQueryParams: string[] = []): string => {\n try {\n const urlObject = new URL(url);\n const searchParams = urlObject.searchParams;\n\n let hasChanged = false;\n const removedParams: string[] = [];\n\n sensitiveQueryParams.forEach((param) => {\n if (searchParams.has(param)) {\n searchParams.delete(param);\n hasChanged = true;\n removedParams.push(param);\n }\n });\n\n if (!hasChanged && url.includes('?')) {\n return url;\n }\n\n urlObject.search = searchParams.toString();\n const result = urlObject.toString();\n\n return result;\n } catch (error) {\n log('warn', 'URL normalization failed, returning original', { error, data: { url: url.slice(0, 100) } });\n\n return url;\n }\n};\n","import { MAX_ARRAY_LENGTH, MAX_OBJECT_DEPTH, MAX_STRING_LENGTH, XSS_PATTERNS } from '../../constants';\nimport { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\n\n/**\n * Sanitizes a string value to prevent XSS attacks\n * @param value - The string to sanitize\n * @returns The sanitized string\n */\nexport const sanitizeString = (value: string): string => {\n if (!value || typeof value !== 'string' || value.trim().length === 0) {\n return '';\n }\n\n let sanitized = value;\n\n // Limit string length\n if (value.length > MAX_STRING_LENGTH) {\n sanitized = value.slice(0, Math.max(0, MAX_STRING_LENGTH));\n // Silent truncation - this is expected behavior for long strings\n }\n\n // Remove potential XSS patterns\n let xssPatternMatches = 0;\n for (const pattern of XSS_PATTERNS) {\n const beforeReplace = sanitized;\n sanitized = sanitized.replace(pattern, '');\n if (beforeReplace !== sanitized) {\n xssPatternMatches++;\n }\n }\n\n if (xssPatternMatches > 0) {\n log('warn', 'XSS patterns detected and removed', {\n data: {\n patternMatches: xssPatternMatches,\n originalValue: value.slice(0, 100),\n },\n });\n }\n\n // Basic HTML entity encoding for critical characters\n sanitized = sanitized\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''')\n .replaceAll('/', '/');\n\n const result = sanitized.trim();\n\n return result;\n};\n\n/**\n * Sanitizes any value recursively with depth protection\n * @param value - The value to sanitize\n * @param depth - Current recursion depth\n * @returns The sanitized value\n */\nconst sanitizeValue = (value: unknown, depth = 0): unknown => {\n // Prevent infinite recursion\n if (depth > MAX_OBJECT_DEPTH) {\n // Silent depth limit - prevents stack overflow\n return null;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return sanitizeString(value);\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < -Number.MAX_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {\n // Silent normalization - invalid numbers become 0\n return 0;\n }\n\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (Array.isArray(value)) {\n const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);\n\n // Silent array length limit\n const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);\n\n // Silent filter - empty arrays are valid results\n return sanitizedArray;\n }\n\n if (typeof value === 'object') {\n const sanitizedObject: Record<string, unknown> = {};\n const entries = Object.entries(value);\n const limitedEntries = entries.slice(0, 20);\n\n // Silent object keys limit\n for (const [key, value_] of limitedEntries) {\n const sanitizedKey = sanitizeString(key);\n\n if (sanitizedKey) {\n const sanitizedValue = sanitizeValue(value_, depth + 1);\n\n if (sanitizedValue !== null) {\n sanitizedObject[sanitizedKey] = sanitizedValue;\n }\n }\n }\n\n return sanitizedObject;\n }\n\n return null;\n};\n\n/**\n * Sanitizes user metadata for custom events\n * @param metadata - The metadata to sanitize\n * @returns The sanitized metadata\n */\nexport const sanitizeMetadata = (metadata: unknown): Record<string, MetadataType> => {\n if (typeof metadata !== 'object' || metadata === null) {\n return {};\n }\n\n try {\n const sanitized = sanitizeValue(metadata);\n const result =\n typeof sanitized === 'object' && sanitized !== null ? (sanitized as Record<string, MetadataType>) : {};\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] Metadata sanitization failed: ${errorMessage}`);\n }\n};\n","import {\n MAX_SESSION_TIMEOUT_MS,\n MIN_SESSION_TIMEOUT_MS,\n DEFAULT_SESSION_TIMEOUT,\n VALIDATION_MESSAGES,\n} from '../../constants';\nimport { Config } from '../../types';\nimport {\n AppConfigValidationError,\n SessionTimeoutValidationError,\n SamplingRateValidationError,\n IntegrationValidationError,\n} from '../../types/validation-error.types';\nimport { log } from '../logging.utils';\n\n/**\n * Validates the app configuration object (before normalization)\n * This validates the structure and basic types but allows for normalization afterward\n * @param config - The app configuration to validate\n * @throws {ProjectIdValidationError} If project ID validation fails\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAppConfig = (config?: Config): void => {\n if (config !== undefined && (config === null || typeof config !== 'object')) {\n throw new AppConfigValidationError('Configuration must be an object', 'config');\n }\n\n if (!config) {\n return;\n }\n\n if (config.sessionTimeout !== undefined) {\n if (\n typeof config.sessionTimeout !== 'number' ||\n config.sessionTimeout < MIN_SESSION_TIMEOUT_MS ||\n config.sessionTimeout > MAX_SESSION_TIMEOUT_MS\n ) {\n throw new SessionTimeoutValidationError(VALIDATION_MESSAGES.INVALID_SESSION_TIMEOUT, 'config');\n }\n }\n\n if (config.globalMetadata !== undefined) {\n if (typeof config.globalMetadata !== 'object' || config.globalMetadata === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_GLOBAL_METADATA, 'config');\n }\n }\n\n if (config.scrollContainerSelectors !== undefined) {\n validateScrollContainerSelectors(config.scrollContainerSelectors);\n }\n\n if (config.integrations) {\n validateIntegrations(config.integrations);\n }\n\n if (config.sensitiveQueryParams !== undefined) {\n if (!Array.isArray(config.sensitiveQueryParams)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SENSITIVE_QUERY_PARAMS, 'config');\n }\n\n for (const param of config.sensitiveQueryParams) {\n if (typeof param !== 'string') {\n throw new AppConfigValidationError('All sensitive query params must be strings', 'config');\n }\n }\n }\n\n if (config.errorSampling !== undefined) {\n if (typeof config.errorSampling !== 'number' || config.errorSampling < 0 || config.errorSampling > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_ERROR_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.samplingRate !== undefined) {\n if (typeof config.samplingRate !== 'number' || config.samplingRate < 0 || config.samplingRate > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_SAMPLING_RATE, 'config');\n }\n }\n};\n\n/**\n * Validates CSS selector syntax without executing querySelector (XSS prevention)\n * @param selector - CSS selector to validate\n * @returns True if the selector syntax is valid\n */\nconst isValidCssSelectorSyntax = (selector: string): boolean => {\n // Prevent dangerous characters that could indicate XSS attempts\n if (selector.includes('<') || selector.includes('>') || /on\\w+\\s*=/i.test(selector)) {\n return false;\n }\n\n // Safe CSS selector pattern - allows common selector syntax\n const safePattern = /^[a-zA-Z0-9\\-_#.[\\]=\"':, >+~*()]+$/;\n if (!safePattern.test(selector)) {\n return false;\n }\n\n // Check for balanced parentheses\n let parenthesesCount = 0;\n for (const char of selector) {\n if (char === '(') parenthesesCount++;\n if (char === ')') parenthesesCount--;\n if (parenthesesCount < 0) return false;\n }\n if (parenthesesCount !== 0) return false;\n\n // Check for balanced square brackets\n let bracketsCount = 0;\n for (const char of selector) {\n if (char === '[') bracketsCount++;\n if (char === ']') bracketsCount--;\n if (bracketsCount < 0) return false;\n }\n if (bracketsCount !== 0) return false;\n\n return true;\n};\n\n/**\n * Validates scroll container selectors\n * @param selectors - CSS selectors to validate\n */\nconst validateScrollContainerSelectors = (selectors: string | string[]): void => {\n const selectorsArray = Array.isArray(selectors) ? selectors : [selectors];\n\n for (const selector of selectorsArray) {\n if (typeof selector !== 'string' || selector.trim() === '') {\n log('error', 'Invalid scroll container selector', {\n showToClient: true,\n data: {\n selector,\n type: typeof selector,\n isEmpty: selector === '' || (typeof selector === 'string' && selector.trim() === ''),\n },\n });\n\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SCROLL_CONTAINER_SELECTORS, 'config');\n }\n\n // Validate CSS selector syntax using regex-based validation (XSS prevention)\n // This validates syntax WITHOUT executing document.querySelector()\n if (!isValidCssSelectorSyntax(selector)) {\n log('error', 'Invalid or potentially unsafe CSS selector', {\n showToClient: true,\n data: {\n selector,\n reason: 'Failed security validation',\n },\n });\n\n throw new AppConfigValidationError('Invalid or potentially unsafe CSS selector', 'config');\n }\n }\n};\n\n/**\n * Validates integrations configuration\n * @param integrations - Integrations configuration to validate\n */\nconst validateIntegrations = (integrations: Config['integrations']): void => {\n if (!integrations) {\n return;\n }\n\n if (integrations.tracelog) {\n if (\n !integrations.tracelog.projectId ||\n typeof integrations.tracelog.projectId !== 'string' ||\n integrations.tracelog.projectId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_TRACELOG_PROJECT_ID, 'config');\n }\n }\n\n if (integrations.custom) {\n if (\n !integrations.custom.collectApiUrl ||\n typeof integrations.custom.collectApiUrl !== 'string' ||\n integrations.custom.collectApiUrl.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_CUSTOM_API_URL, 'config');\n }\n\n if (integrations.custom.allowHttp !== undefined && typeof integrations.custom.allowHttp !== 'boolean') {\n throw new IntegrationValidationError('allowHttp must be a boolean', 'config');\n }\n\n const collectApiUrl = integrations.custom.collectApiUrl.trim();\n\n if (!collectApiUrl.startsWith('http://') && !collectApiUrl.startsWith('https://')) {\n throw new IntegrationValidationError('Custom API URL must start with \"http://\" or \"https://\"', 'config');\n }\n\n const allowHttp = integrations.custom.allowHttp ?? false;\n\n if (!allowHttp && collectApiUrl.startsWith('http://')) {\n throw new IntegrationValidationError(\n 'Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)',\n 'config',\n );\n }\n }\n\n if (integrations.googleAnalytics) {\n if (\n !integrations.googleAnalytics.measurementId ||\n typeof integrations.googleAnalytics.measurementId !== 'string' ||\n integrations.googleAnalytics.measurementId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_GOOGLE_ANALYTICS_ID, 'config');\n }\n\n const measurementId = integrations.googleAnalytics.measurementId.trim();\n\n if (!measurementId.match(/^(G-|UA-)/)) {\n throw new IntegrationValidationError('Google Analytics measurement ID must start with \"G-\" or \"UA-\"', 'config');\n }\n }\n};\n\n/**\n * Validates and normalizes the app configuration\n * This is the primary validation entry point that ensures consistent behavior\n * @param config - The app configuration to validate and normalize\n * @returns The normalized configuration\n * @throws {ProjectIdValidationError} If project ID validation fails after normalization\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAndNormalizeConfig = (config?: Config): Config => {\n validateAppConfig(config);\n\n const normalizedConfig: Config = {\n ...(config ?? {}),\n sessionTimeout: config?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,\n globalMetadata: config?.globalMetadata ?? {},\n sensitiveQueryParams: config?.sensitiveQueryParams ?? [],\n errorSampling: config?.errorSampling ?? 1,\n samplingRate: config?.samplingRate ?? 1,\n };\n\n // Normalize integrations\n if (normalizedConfig.integrations?.custom) {\n normalizedConfig.integrations.custom = {\n ...normalizedConfig.integrations.custom,\n allowHttp: normalizedConfig.integrations.custom.allowHttp ?? false,\n };\n }\n\n return normalizedConfig;\n};\n","import { MAX_NESTED_OBJECT_KEYS } from '../../constants';\n\n/**\n * Validates if an item in an array is a valid nested object\n * @param item - The item to validate\n * @returns True if the item is a valid nested object\n */\nconst isValidArrayItem = (item: unknown): boolean => {\n if (typeof item === 'string') {\n return true;\n }\n\n // Allow objects with primitive fields only (one level deep)\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const entries = Object.entries(item);\n\n // Check key count limit\n if (entries.length > MAX_NESTED_OBJECT_KEYS) {\n return false;\n }\n\n // All values must be primitives (no nested objects or arrays)\n for (const [, value] of entries) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n};\n\n/**\n * Checks if an object contains only primitive fields, string arrays, or arrays of flat objects\n * @param object - The object to check\n * @returns True if the object contains only valid fields\n */\nexport const isOnlyPrimitiveFields = (object: Record<string, unknown>): boolean => {\n if (typeof object !== 'object' || object === null) {\n return false;\n }\n\n for (const value of Object.values(object)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type === 'string' || type === 'number' || type === 'boolean') {\n continue;\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n\n // Determine array type from first item\n const firstItem = value[0];\n const isStringArray = typeof firstItem === 'string';\n\n // All items must be of the same type (all strings OR all objects)\n if (isStringArray) {\n if (!value.every((item) => typeof item === 'string')) {\n return false;\n }\n } else {\n // Must be all objects\n if (!value.every((item) => isValidArrayItem(item))) {\n return false;\n }\n }\n\n continue;\n }\n\n return false;\n }\n\n return true;\n};\n","import {\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_STRING_LENGTH,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { sanitizeMetadata } from '../security/sanitize.utils';\nimport { isOnlyPrimitiveFields } from './type-guards.utils';\n\n/**\n * Validates an event name\n * @param eventName - The event name to validate\n * @returns Validation result with error message if invalid\n */\nexport const isValidEventName = (eventName: string): { valid: boolean; error?: string } => {\n if (typeof eventName !== 'string') {\n return {\n valid: false,\n error: 'Event name must be a string',\n };\n }\n\n if (eventName.length === 0) {\n return {\n valid: false,\n error: 'Event name cannot be empty',\n };\n }\n\n if (eventName.length > MAX_CUSTOM_EVENT_NAME_LENGTH) {\n return {\n valid: false,\n error: `Event name is too long (max ${MAX_CUSTOM_EVENT_NAME_LENGTH} characters)`,\n };\n }\n\n if (eventName.includes('<') || eventName.includes('>') || eventName.includes('&')) {\n return {\n valid: false,\n error: 'Event name contains invalid characters',\n };\n }\n\n const reservedWords = ['constructor', 'prototype', '__proto__', 'eval', 'function', 'var', 'let', 'const'];\n\n if (reservedWords.includes(eventName.toLowerCase())) {\n return {\n valid: false,\n error: 'Event name cannot be a reserved word',\n };\n }\n\n return { valid: true };\n};\n\n/**\n * Validates a single metadata object\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata object to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nconst validateSingleMetadata = (\n eventName: string,\n metadata: Record<string, unknown>,\n type?: 'globalMetadata' | 'customEvent',\n): { valid: boolean; error?: string; sanitizedMetadata?: Record<string, MetadataType> } => {\n const sanitizedMetadata = sanitizeMetadata(metadata);\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n if (!isOnlyPrimitiveFields(sanitizedMetadata)) {\n return {\n valid: false,\n error: `${intro}: object has invalid types. Valid types are string, number, boolean or string arrays.`,\n };\n }\n\n let jsonString: string;\n\n try {\n jsonString = JSON.stringify(sanitizedMetadata);\n } catch {\n return {\n valid: false,\n error: `${intro}: object contains circular references or cannot be serialized.`,\n };\n }\n\n if (jsonString.length > MAX_CUSTOM_EVENT_STRING_SIZE) {\n return {\n valid: false,\n error: `${intro}: object is too large (max ${MAX_CUSTOM_EVENT_STRING_SIZE / 1024} KB).`,\n };\n }\n\n const keyCount = Object.keys(sanitizedMetadata).length;\n\n if (keyCount > MAX_CUSTOM_EVENT_KEYS) {\n return {\n valid: false,\n error: `${intro}: object has too many keys (max ${MAX_CUSTOM_EVENT_KEYS} keys).`,\n };\n }\n\n for (const [key, value] of Object.entries(sanitizedMetadata)) {\n if (Array.isArray(value)) {\n if (value.length > MAX_CUSTOM_EVENT_ARRAY_SIZE) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" is too large (max ${MAX_CUSTOM_EVENT_ARRAY_SIZE} items).`,\n };\n }\n\n for (const item of value) {\n if (typeof item === 'string' && item.length > 500) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" contains strings that are too long (max 500 characters).`,\n };\n }\n }\n }\n\n if (typeof value === 'string' && value.length > MAX_STRING_LENGTH) {\n return {\n valid: false,\n error: `${intro}: property \"${key}\" is too long (max ${MAX_STRING_LENGTH} characters).`,\n };\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata,\n };\n};\n\n/**\n * Validates metadata for events (supports both objects and arrays of objects)\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isValidMetadata = (\n eventName: string,\n metadata: Record<string, unknown> | Record<string, unknown>[],\n type?: 'globalMetadata' | 'customEvent',\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n if (Array.isArray(metadata)) {\n const sanitizedArray: Record<string, MetadataType>[] = [];\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n for (let i = 0; i < metadata.length; i++) {\n const item = metadata[i];\n\n if (typeof item !== 'object' || item === null || Array.isArray(item)) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} must be an object.`,\n };\n }\n\n const itemValidation = validateSingleMetadata(eventName, item, type);\n\n if (!itemValidation.valid) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} is invalid: ${itemValidation.error}`,\n };\n }\n\n if (itemValidation.sanitizedMetadata) {\n sanitizedArray.push(itemValidation.sanitizedMetadata);\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata: sanitizedArray,\n };\n }\n\n return validateSingleMetadata(eventName, metadata, type);\n};\n","import { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\nimport { isValidEventName, isValidMetadata } from './metadata-validations.utils';\n\n/**\n * Validates a complete event with name and optional metadata\n * @param eventName - The event name to validate\n * @param metadata - Optional metadata to validate\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isEventValid = (\n eventName: string,\n metadata?: Record<string, unknown> | Record<string, unknown>[],\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n const nameValidation = isValidEventName(eventName);\n\n if (!nameValidation.valid) {\n log('error', 'Event name validation failed', {\n showToClient: true,\n data: { eventName, error: nameValidation.error },\n });\n\n return nameValidation;\n }\n\n if (!metadata) {\n return { valid: true };\n }\n\n const metadataValidation = isValidMetadata(eventName, metadata, 'customEvent');\n\n if (!metadataValidation.valid) {\n log('error', 'Event metadata validation failed', {\n showToClient: true,\n data: {\n eventName,\n error: metadataValidation.error,\n },\n });\n }\n\n return metadataValidation;\n};\n","import { EmitterCallback, EmitterMap } from '@/types';\n\nexport class Emitter {\n private readonly listeners: Map<string, EmitterCallback[]> = new Map();\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n\n this.listeners.get(event)!.push(callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n const index = callbacks.indexOf(callback);\n\n if (index > -1) {\n callbacks.splice(index, 1);\n }\n }\n }\n\n emit<K extends keyof EmitterMap>(event: K, data: EmitterMap[K]): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n callbacks.forEach((callback) => callback(data));\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { State } from '../types';\n\nconst globalState: State = {} as State;\n\nexport function getGlobalState(): Readonly<State> {\n return globalState;\n}\n\nexport function resetGlobalState(): void {\n Object.keys(globalState).forEach((key) => {\n delete globalState[key as keyof State];\n });\n}\n\nexport abstract class StateManager {\n protected get<T extends keyof State>(key: T): State[T] {\n return globalState[key];\n }\n\n protected set<T extends keyof State>(key: T, value: State[T]): void {\n globalState[key] = value;\n }\n\n protected getState(): Readonly<State> {\n return { ...globalState };\n }\n}\n","import { QUEUE_KEY, EVENT_EXPIRY_HOURS, MAX_RETRIES, RETRY_DELAY_MS, REQUEST_TIMEOUT_MS } from '../constants';\nimport { PersistedQueueData, BaseEventsQueueDto, SpecialApiUrl } from '../types';\nimport { log } from '../utils';\nimport { StorageManager } from './storage.manager';\nimport { StateManager } from './state.manager';\n\ninterface SendCallbacks {\n onSuccess?: (eventCount?: number, events?: any[], body?: BaseEventsQueueDto) => void;\n onFailure?: () => void;\n}\n\nexport class SenderManager extends StateManager {\n private readonly storeManager: StorageManager;\n private retryTimeoutId: number | null = null;\n private retryCount = 0;\n private isRetrying = false;\n\n constructor(storeManager: StorageManager) {\n super();\n this.storeManager = storeManager;\n }\n\n private getQueueStorageKey(): string {\n const userId = this.get('userId') || 'anonymous';\n return QUEUE_KEY(userId);\n }\n\n sendEventsQueueSync(body: BaseEventsQueueDto): boolean {\n if (this.shouldSkipSend()) {\n this.resetRetryState();\n\n return true;\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure (sync)', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const success = this.sendQueueSyncInternal(body);\n\n if (success) {\n this.resetRetryState();\n }\n\n return success;\n }\n\n async sendEventsQueue(body: BaseEventsQueueDto, callbacks?: SendCallbacks): Promise<boolean> {\n if (!this.shouldSkipSend()) {\n const persisted = this.persistEvents(body);\n\n if (!persisted) {\n log('warn', 'Failed to persist events, attempting immediate send');\n }\n }\n\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n callbacks?.onSuccess?.(body.events.length, body.events, body);\n } else {\n this.scheduleRetry(body, callbacks);\n callbacks?.onFailure?.();\n }\n\n return success;\n }\n\n async recoverPersistedEvents(callbacks?: SendCallbacks): Promise<void> {\n try {\n const persistedData = this.getPersistedData();\n\n if (!persistedData || !this.isDataRecent(persistedData) || persistedData.events.length === 0) {\n this.clearPersistedEvents();\n return;\n }\n\n const body = this.createRecoveryBody(persistedData);\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n callbacks?.onSuccess?.(persistedData.events.length, persistedData.events, body);\n } else {\n this.scheduleRetry(body, callbacks);\n callbacks?.onFailure?.();\n }\n } catch (error) {\n log('error', 'Failed to recover persisted events', { error });\n this.clearPersistedEvents();\n }\n }\n\n persistEventsForRecovery(body: BaseEventsQueueDto): boolean {\n return this.persistEvents(body);\n }\n\n async sendEventsQueueAsync(body: BaseEventsQueueDto): Promise<boolean> {\n return this.sendEventsQueue(body);\n }\n\n stop(): void {\n this.clearRetryTimeout();\n this.resetRetryState();\n }\n\n private async send(body: BaseEventsQueueDto): Promise<boolean> {\n if (this.shouldSkipSend()) {\n return this.simulateSuccessfulSend();\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const { url, payload } = this.prepareRequest(body);\n\n try {\n const response = await this.sendWithTimeout(url, payload);\n\n return response.ok;\n } catch (error) {\n log('error', 'Send request failed', {\n error,\n data: {\n events: body.events.length,\n url: url.replace(/\\/\\/[^/]+/, '//[DOMAIN]'),\n },\n });\n\n return false;\n }\n }\n\n private async sendWithTimeout(url: string, payload: string): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n body: payload,\n keepalive: true,\n credentials: 'include',\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private sendQueueSyncInternal(body: BaseEventsQueueDto): boolean {\n const { url, payload } = this.prepareRequest(body);\n const blob = new Blob([payload], { type: 'application/json' });\n\n if (this.isSendBeaconAvailable()) {\n const success = navigator.sendBeacon(url, blob);\n\n if (success) {\n return true;\n }\n log('warn', 'sendBeacon failed, persisting events for recovery');\n } else {\n log('warn', 'sendBeacon not available, persisting events for recovery');\n }\n\n this.persistEventsForRecovery(body);\n\n return false;\n }\n\n private prepareRequest(body: BaseEventsQueueDto): { url: string; payload: string } {\n // Enrich payload with metadata for sendBeacon() fallback\n // sendBeacon() doesn't send custom headers, so we include referer in payload\n const enrichedBody = {\n ...body,\n _metadata: {\n referer: typeof window !== 'undefined' ? window.location.href : undefined,\n timestamp: Date.now(),\n },\n };\n\n return {\n url: this.get('collectApiUrl'),\n payload: JSON.stringify(enrichedBody),\n };\n }\n\n private getPersistedData(): PersistedQueueData | null {\n try {\n const storageKey = this.getQueueStorageKey();\n const persistedDataString = this.storeManager.getItem(storageKey);\n\n if (persistedDataString) {\n return JSON.parse(persistedDataString);\n }\n } catch (error) {\n log('warn', 'Failed to parse persisted data', { error });\n this.clearPersistedEvents();\n }\n\n return null;\n }\n\n private isDataRecent(data: PersistedQueueData): boolean {\n if (!data.timestamp || typeof data.timestamp !== 'number') {\n return false;\n }\n\n const ageInHours = (Date.now() - data.timestamp) / (1000 * 60 * 60);\n const isRecent = ageInHours < EVENT_EXPIRY_HOURS;\n\n return isRecent;\n }\n\n private createRecoveryBody(data: PersistedQueueData): BaseEventsQueueDto {\n return {\n user_id: data.userId,\n session_id: data.sessionId,\n device: data.device,\n events: data.events,\n ...(data.global_metadata && { global_metadata: data.global_metadata }),\n };\n }\n\n private persistEvents(body: BaseEventsQueueDto): boolean {\n try {\n const persistedData: PersistedQueueData = {\n userId: body.user_id,\n sessionId: body.session_id,\n device: body.device,\n events: body.events,\n timestamp: Date.now(),\n ...(body.global_metadata && { global_metadata: body.global_metadata }),\n };\n\n const storageKey = this.getQueueStorageKey();\n this.storeManager.setItem(storageKey, JSON.stringify(persistedData));\n\n return !!this.storeManager.getItem(storageKey);\n } catch (error) {\n log('warn', 'Failed to persist events', { error });\n return false;\n }\n }\n\n private clearPersistedEvents(): void {\n try {\n const key = this.getQueueStorageKey();\n this.storeManager.removeItem(key);\n } catch (error) {\n log('warn', 'Failed to clear persisted events', { error });\n }\n }\n\n private resetRetryState(): void {\n this.retryCount = 0;\n this.isRetrying = false;\n this.clearRetryTimeout();\n }\n\n private scheduleRetry(body: BaseEventsQueueDto, originalCallbacks?: SendCallbacks): void {\n if (this.retryTimeoutId !== null || this.isRetrying) {\n return;\n }\n\n if (this.retryCount >= MAX_RETRIES) {\n log('warn', 'Max retries reached, giving up', { data: { retryCount: this.retryCount } });\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onFailure?.();\n return;\n }\n\n const retryDelay = RETRY_DELAY_MS * Math.pow(2, this.retryCount); // Exponential backoff\n\n this.isRetrying = true;\n\n this.retryTimeoutId = window.setTimeout(async () => {\n this.retryTimeoutId = null;\n\n this.retryCount++;\n\n try {\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onSuccess?.(body.events.length);\n } else if (this.retryCount >= MAX_RETRIES) {\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onFailure?.();\n } else {\n this.scheduleRetry(body, originalCallbacks);\n }\n } finally {\n this.isRetrying = false;\n }\n }, retryDelay);\n }\n\n private shouldSkipSend(): boolean {\n return !this.get('collectApiUrl');\n }\n\n private async simulateSuccessfulSend(): Promise<boolean> {\n const delay = Math.random() * 400 + 100;\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return true;\n }\n\n private isSendBeaconAvailable(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n }\n\n private clearRetryTimeout(): void {\n if (this.retryTimeoutId !== null) {\n clearTimeout(this.retryTimeoutId);\n this.retryTimeoutId = null;\n }\n }\n}\n","import {\n EVENT_SENT_INTERVAL_MS,\n MAX_EVENTS_QUEUE_LENGTH,\n DUPLICATE_EVENT_THRESHOLD_MS,\n RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SECOND,\n MAX_PENDING_EVENTS_BUFFER,\n} from '../constants/config.constants';\nimport { BaseEventsQueueDto, EmitterEvent, EventData, EventType, Mode } from '../types';\nimport { getUTMParameters, log, Emitter, generateEventId } from '../utils';\nimport { SenderManager } from './sender.manager';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { GoogleAnalyticsIntegration } from '../integrations/google-analytics.integration';\n\nexport class EventManager extends StateManager {\n private readonly googleAnalytics: GoogleAnalyticsIntegration | null;\n private readonly dataSender: SenderManager;\n private readonly emitter: Emitter | null;\n\n private eventsQueue: EventData[] = [];\n private pendingEventsBuffer: Partial<EventData>[] = [];\n private lastEventFingerprint: string | null = null;\n private lastEventTime = 0;\n private sendIntervalId: number | null = null;\n private rateLimitCounter = 0;\n private rateLimitWindowStart = 0;\n\n constructor(\n storeManager: StorageManager,\n googleAnalytics: GoogleAnalyticsIntegration | null = null,\n emitter: Emitter | null = null,\n ) {\n super();\n\n this.googleAnalytics = googleAnalytics;\n this.dataSender = new SenderManager(storeManager);\n this.emitter = emitter;\n }\n\n async recoverPersistedEvents(): Promise<void> {\n await this.dataSender.recoverPersistedEvents({\n onSuccess: (_eventCount, recoveredEvents, body) => {\n if (recoveredEvents && recoveredEvents.length > 0) {\n const eventIds = recoveredEvents.map((e) => e.id);\n this.removeProcessedEvents(eventIds);\n\n if (body) {\n this.emitEventsQueue(body);\n }\n }\n },\n onFailure: async () => {\n log('warn', 'Failed to recover persisted events');\n },\n });\n }\n\n track({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n }: Partial<EventData>): void {\n if (!type) {\n log('error', 'Event type is required - event will be ignored');\n return;\n }\n\n // Check session BEFORE rate limiting to avoid consuming quota for buffered events\n if (!this.get('sessionId')) {\n // Protect against unbounded buffer growth during initialization delays\n if (this.pendingEventsBuffer.length >= MAX_PENDING_EVENTS_BUFFER) {\n // Drop oldest event (FIFO) to make room for new one\n this.pendingEventsBuffer.shift();\n log('warn', 'Pending events buffer full - dropping oldest event', {\n data: { maxBufferSize: MAX_PENDING_EVENTS_BUFFER },\n });\n }\n\n this.pendingEventsBuffer.push({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n });\n\n return;\n }\n\n // Rate limiting check (except for critical events)\n // Applied AFTER session check to only rate-limit processable events\n const isCriticalEvent = type === EventType.SESSION_START || type === EventType.SESSION_END;\n if (!isCriticalEvent && !this.checkRateLimit()) {\n // Rate limit exceeded - drop event silently\n // Logging would itself cause performance issues\n return;\n }\n\n const eventType = type as EventType;\n const isSessionStart = eventType === EventType.SESSION_START;\n\n const currentPageUrl = (page_url as string) || this.get('pageUrl');\n const payload = this.buildEventPayload({\n type: eventType,\n page_url: currentPageUrl,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n });\n\n if (!isCriticalEvent && !this.shouldSample()) {\n return;\n }\n\n if (isSessionStart) {\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n log('error', 'Session start event requires sessionId - event will be ignored');\n return;\n }\n\n if (this.get('hasStartSession')) {\n log('warn', 'Duplicate session_start detected', {\n data: { sessionId: currentSessionId },\n });\n\n return;\n }\n\n this.set('hasStartSession', true);\n }\n\n if (this.isDuplicateEvent(payload)) {\n return;\n }\n\n if (this.get('mode') === Mode.QA && eventType === EventType.CUSTOM && custom_event) {\n console.log('[TraceLog] Event', {\n name: custom_event.name,\n ...(custom_event.metadata && { metadata: custom_event.metadata }),\n });\n\n this.emitEvent(payload);\n\n return;\n }\n\n this.addToQueue(payload);\n }\n\n stop(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n\n this.eventsQueue = [];\n this.pendingEventsBuffer = [];\n this.lastEventFingerprint = null;\n this.lastEventTime = 0;\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = 0;\n\n this.dataSender.stop();\n }\n\n async flushImmediately(): Promise<boolean> {\n return this.flushEvents(false);\n }\n\n flushImmediatelySync(): boolean {\n return this.flushEvents(true) as boolean;\n }\n\n getQueueLength(): number {\n return this.eventsQueue.length;\n }\n\n flushPendingEvents(): void {\n if (this.pendingEventsBuffer.length === 0) {\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n if (!currentSessionId) {\n // Keep events in buffer for future retry - do NOT discard\n // This prevents data loss during legitimate race conditions\n log('warn', 'Cannot flush pending events: session not initialized - keeping in buffer', {\n data: { bufferedEventCount: this.pendingEventsBuffer.length },\n });\n\n return;\n }\n\n // Create copy before clearing to avoid infinite recursion\n const bufferedEvents = [...this.pendingEventsBuffer];\n this.pendingEventsBuffer = [];\n\n // Process all buffered events now that session exists\n bufferedEvents.forEach((event) => {\n this.track(event);\n });\n }\n\n private clearSendInterval(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n }\n\n private flushEvents(isSync: boolean): boolean | Promise<boolean> {\n if (this.eventsQueue.length === 0) {\n return isSync ? true : Promise.resolve(true);\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n if (isSync) {\n const success = this.dataSender.sendEventsQueueSync(body);\n\n if (success) {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n }\n\n return success;\n } else {\n return this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n log('warn', 'Async flush failed', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n }\n\n private async sendEventsQueue(): Promise<void> {\n if (!this.get('sessionId') || this.eventsQueue.length === 0) {\n return;\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n await this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.emitEventsQueue(body);\n },\n onFailure: async () => {\n log('warn', 'Events send failed, keeping in queue', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n\n private buildEventsPayload(): BaseEventsQueueDto {\n const eventMap = new Map<string, EventData>();\n const order: string[] = [];\n\n for (const event of this.eventsQueue) {\n const signature = this.createEventSignature(event);\n\n if (!eventMap.has(signature)) {\n order.push(signature);\n }\n\n eventMap.set(signature, event);\n }\n\n const events = order\n .map((signature) => eventMap.get(signature))\n .filter((event): event is EventData => Boolean(event))\n .sort((a, b) => a.timestamp - b.timestamp);\n\n return {\n user_id: this.get('userId'),\n session_id: this.get('sessionId') as string,\n device: this.get('device'),\n events,\n ...(this.get('config')?.globalMetadata && { global_metadata: this.get('config')?.globalMetadata }),\n };\n }\n\n private buildEventPayload(data: Partial<EventData>): EventData {\n const isSessionStart = data.type === EventType.SESSION_START;\n const currentPageUrl = data.page_url ?? this.get('pageUrl');\n\n const payload: EventData = {\n id: generateEventId(),\n type: data.type as EventType,\n page_url: currentPageUrl,\n timestamp: Date.now(),\n ...(isSessionStart && { referrer: document.referrer || 'Direct' }),\n ...(data.from_page_url && { from_page_url: data.from_page_url }),\n ...(data.scroll_data && { scroll_data: data.scroll_data }),\n ...(data.click_data && { click_data: data.click_data }),\n ...(data.custom_event && { custom_event: data.custom_event }),\n ...(data.web_vitals && { web_vitals: data.web_vitals }),\n ...(data.error_data && { error_data: data.error_data }),\n ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),\n ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),\n };\n\n return payload;\n }\n\n private isDuplicateEvent(event: EventData): boolean {\n const now = Date.now();\n const fingerprint = this.createEventFingerprint(event);\n\n if (this.lastEventFingerprint === fingerprint && now - this.lastEventTime < DUPLICATE_EVENT_THRESHOLD_MS) {\n return true;\n }\n\n this.lastEventFingerprint = fingerprint;\n this.lastEventTime = now;\n return false;\n }\n\n private createEventFingerprint(event: EventData): string {\n let fingerprint = `${event.type}_${event.page_url}`;\n\n if (event.click_data) {\n const x = Math.round((event.click_data.x || 0) / 10) * 10;\n const y = Math.round((event.click_data.y || 0) / 10) * 10;\n fingerprint += `_click_${x}_${y}`;\n }\n\n if (event.scroll_data) {\n fingerprint += `_scroll_${event.scroll_data.depth}_${event.scroll_data.direction}`;\n }\n\n if (event.custom_event) {\n fingerprint += `_custom_${event.custom_event.name}`;\n }\n\n if (event.web_vitals) {\n fingerprint += `_vitals_${event.web_vitals.type}`;\n }\n\n if (event.error_data) {\n fingerprint += `_error_${event.error_data.type}_${event.error_data.message}`;\n }\n\n return fingerprint;\n }\n\n private createEventSignature(event: EventData): string {\n return this.createEventFingerprint(event);\n }\n\n private addToQueue(event: EventData): void {\n this.eventsQueue.push(event);\n\n this.emitEvent(event);\n\n if (this.eventsQueue.length > MAX_EVENTS_QUEUE_LENGTH) {\n const nonCriticalIndex = this.eventsQueue.findIndex(\n (e) => e.type !== EventType.SESSION_START && e.type !== EventType.SESSION_END,\n );\n\n const removedEvent =\n nonCriticalIndex >= 0 ? this.eventsQueue.splice(nonCriticalIndex, 1)[0] : this.eventsQueue.shift();\n\n log('warn', 'Event queue overflow, oldest non-critical event removed', {\n data: {\n maxLength: MAX_EVENTS_QUEUE_LENGTH,\n currentLength: this.eventsQueue.length,\n removedEventType: removedEvent?.type,\n wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,\n },\n });\n }\n\n if (!this.sendIntervalId) {\n this.startSendInterval();\n }\n\n this.handleGoogleAnalyticsIntegration(event);\n }\n\n private startSendInterval(): void {\n this.sendIntervalId = window.setInterval(() => {\n if (this.eventsQueue.length > 0) {\n this.sendEventsQueue();\n }\n }, EVENT_SENT_INTERVAL_MS);\n }\n\n private handleGoogleAnalyticsIntegration(event: EventData): void {\n if (this.googleAnalytics && event.type === EventType.CUSTOM && event.custom_event) {\n if (this.get('mode') === Mode.QA) {\n return;\n }\n\n this.googleAnalytics.trackEvent(event.custom_event.name, event.custom_event.metadata ?? {});\n }\n }\n\n private shouldSample(): boolean {\n const samplingRate = this.get('config')?.samplingRate ?? 1;\n return Math.random() < samplingRate;\n }\n\n private checkRateLimit(): boolean {\n const now = Date.now();\n\n // Reset counter if window has expired\n if (now - this.rateLimitWindowStart > RATE_LIMIT_WINDOW_MS) {\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = now;\n }\n\n // Check if limit exceeded\n if (this.rateLimitCounter >= MAX_EVENTS_PER_SECOND) {\n return false;\n }\n\n // Increment counter\n this.rateLimitCounter++;\n return true;\n }\n\n private removeProcessedEvents(eventIds: string[]): void {\n const eventIdSet = new Set(eventIds);\n\n this.eventsQueue = this.eventsQueue.filter((event) => {\n return !eventIdSet.has(event.id);\n });\n }\n\n private emitEvent(eventData: EventData): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.EVENT, eventData);\n }\n }\n\n private emitEventsQueue(queue: BaseEventsQueueDto): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.QUEUE, queue);\n }\n }\n}\n","import { USER_ID_KEY } from '../constants';\nimport { generateUUID } from '../utils';\nimport { StorageManager } from './storage.manager';\n\n/**\n * Simple utility for managing user identification.\n * Generates and persists unique user IDs per project.\n */\nexport class UserManager {\n /**\n * Gets or creates a unique user ID for the given project.\n * The user ID is persisted in localStorage and reused across sessions.\n *\n * @param storageManager - Storage manager instance\n * @param projectId - Project identifier for namespacing\n * @returns Persistent unique user ID\n */\n static getId(storageManager: StorageManager): string {\n const storageKey = USER_ID_KEY;\n const storedUserId = storageManager.getItem(storageKey);\n\n if (storedUserId) {\n return storedUserId;\n }\n\n const newUserId = generateUUID();\n storageManager.setItem(storageKey, newUserId);\n\n return newUserId;\n }\n}\n","import { BROADCAST_CHANNEL_NAME, DEFAULT_SESSION_TIMEOUT, SESSION_STORAGE_KEY } from '../constants';\nimport { EventType } from '../types';\nimport { SessionEndReason } from '../types/session.types';\nimport { log } from '../utils';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { EventManager } from './event.manager';\n\ninterface StoredSessionData {\n id: string;\n lastActivity: number;\n}\n\nexport class SessionManager extends StateManager {\n private readonly storageManager: StorageManager;\n private readonly eventManager: EventManager;\n private readonly projectId: string;\n private sessionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private broadcastChannel: BroadcastChannel | null = null;\n private activityHandler: (() => void) | null = null;\n private visibilityChangeHandler: (() => void) | null = null;\n private beforeUnloadHandler: ((event: BeforeUnloadEvent) => void) | null = null;\n private isTracking = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager, projectId: string) {\n super();\n this.storageManager = storageManager;\n this.eventManager = eventManager;\n this.projectId = projectId;\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') {\n log('warn', 'BroadcastChannel not supported');\n return;\n }\n\n const projectId = this.getProjectId();\n this.broadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME(projectId));\n\n this.broadcastChannel.onmessage = (event): void => {\n const { action, sessionId, timestamp, projectId: messageProjectId } = event.data ?? {};\n\n if (messageProjectId !== projectId) {\n return;\n }\n\n if (action === 'session_end') {\n this.resetSessionState();\n return;\n }\n\n if (sessionId && typeof timestamp === 'number' && timestamp > Date.now() - 5000) {\n this.set('sessionId', sessionId);\n this.set('hasStartSession', true);\n this.persistSession(sessionId, timestamp);\n if (this.isTracking) {\n this.setupSessionTimeout();\n }\n }\n };\n }\n\n private shareSession(sessionId: string): void {\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_start',\n projectId: this.getProjectId(),\n sessionId,\n timestamp: Date.now(),\n });\n }\n }\n\n private broadcastSessionEnd(sessionId: string | null, reason: SessionEndReason): void {\n if (!sessionId) {\n return;\n }\n\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_end',\n projectId: this.getProjectId(),\n sessionId,\n reason,\n timestamp: Date.now(),\n });\n }\n }\n\n private cleanupCrossTabSync(): void {\n if (this.broadcastChannel) {\n if (typeof this.broadcastChannel.close === 'function') {\n this.broadcastChannel.close();\n }\n this.broadcastChannel = null;\n }\n }\n\n private recoverSession(): string | null {\n const storedSession = this.loadStoredSession();\n\n if (!storedSession) {\n return null;\n }\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n if (Date.now() - storedSession.lastActivity > sessionTimeout) {\n this.clearStoredSession();\n return null;\n }\n\n return storedSession.id;\n }\n\n private persistSession(sessionId: string, lastActivity: number = Date.now()): void {\n this.saveStoredSession({\n id: sessionId,\n lastActivity,\n });\n }\n\n private clearStoredSession(): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.removeItem(storageKey);\n }\n\n private loadStoredSession(): StoredSessionData | null {\n const storageKey = this.getSessionStorageKey();\n const storedData = this.storageManager.getItem(storageKey);\n\n if (!storedData) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(storedData) as StoredSessionData;\n if (!parsed.id || typeof parsed.lastActivity !== 'number') {\n return null;\n }\n return parsed;\n } catch {\n this.storageManager.removeItem(storageKey);\n return null;\n }\n }\n\n private saveStoredSession(session: StoredSessionData): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.setItem(storageKey, JSON.stringify(session));\n }\n\n private getSessionStorageKey(): string {\n return SESSION_STORAGE_KEY(this.getProjectId());\n }\n\n private getProjectId(): string {\n return this.projectId;\n }\n\n async startTracking(): Promise<void> {\n if (this.isTracking) {\n log('warn', 'Session tracking already active');\n return;\n }\n\n const recoveredSessionId = this.recoverSession();\n const sessionId = recoveredSessionId ?? this.generateSessionId();\n const isRecovered = Boolean(recoveredSessionId);\n\n this.isTracking = true;\n\n try {\n this.set('sessionId', sessionId);\n this.persistSession(sessionId);\n\n if (!isRecovered) {\n this.eventManager.track({\n type: EventType.SESSION_START,\n });\n }\n\n this.initCrossTabSync();\n this.shareSession(sessionId);\n this.setupSessionTimeout();\n this.setupActivityListeners();\n this.setupLifecycleListeners();\n } catch (error) {\n this.isTracking = false;\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n this.set('sessionId', null);\n\n throw error;\n }\n }\n\n private generateSessionId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private setupSessionTimeout(): void {\n this.clearSessionTimeout();\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n this.sessionTimeoutId = setTimeout(() => {\n this.endSession('inactivity');\n }, sessionTimeout);\n }\n\n private resetSessionTimeout(): void {\n this.setupSessionTimeout();\n const sessionId = this.get('sessionId') as string;\n if (sessionId) {\n this.persistSession(sessionId);\n }\n }\n\n private clearSessionTimeout(): void {\n if (this.sessionTimeoutId) {\n clearTimeout(this.sessionTimeoutId);\n this.sessionTimeoutId = null;\n }\n }\n\n private setupActivityListeners(): void {\n this.activityHandler = (): void => this.resetSessionTimeout();\n\n document.addEventListener('click', this.activityHandler, { passive: true });\n document.addEventListener('keydown', this.activityHandler, { passive: true });\n document.addEventListener('scroll', this.activityHandler, { passive: true });\n }\n\n private cleanupActivityListeners(): void {\n if (this.activityHandler) {\n document.removeEventListener('click', this.activityHandler);\n document.removeEventListener('keydown', this.activityHandler);\n document.removeEventListener('scroll', this.activityHandler);\n this.activityHandler = null;\n }\n }\n\n private setupLifecycleListeners(): void {\n if (this.visibilityChangeHandler || this.beforeUnloadHandler) {\n return;\n }\n\n this.visibilityChangeHandler = (): void => {\n if (document.hidden) {\n this.clearSessionTimeout();\n } else {\n const sessionId = this.get('sessionId');\n if (sessionId) {\n this.setupSessionTimeout();\n }\n }\n };\n\n this.beforeUnloadHandler = (): void => {\n this.endSession('page_unload');\n };\n\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n }\n\n private cleanupLifecycleListeners(): void {\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n }\n\n private async endSession(reason: SessionEndReason): Promise<void> {\n const sessionId = this.get('sessionId');\n\n if (!sessionId) {\n log('warn', 'endSession called without active session', { data: { reason } });\n this.resetSessionState(reason);\n return;\n }\n\n this.eventManager.track({\n type: EventType.SESSION_END,\n session_end_reason: reason,\n });\n\n const finalize = (): void => {\n this.broadcastSessionEnd(sessionId, reason);\n this.resetSessionState(reason);\n };\n\n const flushResult = this.eventManager.flushImmediatelySync();\n\n if (flushResult) {\n finalize();\n return;\n }\n\n try {\n await this.eventManager.flushImmediately();\n finalize();\n } catch (error) {\n log('warn', 'Async flush failed during session end', { error });\n finalize();\n }\n }\n\n private resetSessionState(reason?: SessionEndReason): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n\n if (reason !== 'page_unload') {\n this.clearStoredSession();\n }\n\n this.set('sessionId', null);\n this.set('hasStartSession', false);\n this.isTracking = false;\n }\n\n async stopTracking(): Promise<void> {\n await this.endSession('manual_stop');\n }\n\n destroy(): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupCrossTabSync();\n this.cleanupLifecycleListeners();\n this.isTracking = false;\n this.set('hasStartSession', false);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { SessionManager } from '../managers/session.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { StorageManager } from '../managers/storage.manager';\nimport { log } from '../utils';\n\nexport class SessionHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly storageManager: StorageManager;\n private sessionManager: SessionManager | null = null;\n private destroyed = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n this.storageManager = storageManager;\n }\n\n async startTracking(): Promise<void> {\n if (this.isActive()) {\n return;\n }\n\n if (this.destroyed) {\n log('warn', 'Cannot start tracking on destroyed handler');\n return;\n }\n\n const config = this.get('config');\n const projectId =\n config?.integrations?.tracelog?.projectId ?? config?.integrations?.custom?.collectApiUrl ?? 'default';\n\n if (!projectId) {\n throw new Error('Cannot start session tracking: config not available');\n }\n\n try {\n this.sessionManager = new SessionManager(this.storageManager, this.eventManager, projectId);\n await this.sessionManager.startTracking();\n\n // Flush any events that were buffered during initialization\n this.eventManager.flushPendingEvents();\n } catch (error) {\n if (this.sessionManager) {\n try {\n this.sessionManager.destroy();\n } catch {\n // Ignore cleanup errors\n }\n this.sessionManager = null;\n }\n\n log('error', 'Failed to start session tracking', { error });\n throw error;\n }\n }\n\n private isActive(): boolean {\n return this.sessionManager !== null && !this.destroyed;\n }\n\n private async cleanupSessionManager(): Promise<void> {\n if (this.sessionManager) {\n await this.sessionManager.stopTracking();\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n }\n\n async stopTracking(): Promise<void> {\n await this.cleanupSessionManager();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.sessionManager) {\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n\n this.destroyed = true;\n this.set('hasStartSession', false);\n }\n}\n","import { EventType, PageViewData } from '../types';\nimport { normalizeUrl } from '../utils';\nimport { StateManager } from '../managers/state.manager';\nimport { EventManager } from '../managers/event.manager';\n\nexport class PageViewHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly onTrack: () => void;\n\n private originalPushState?: typeof window.history.pushState;\n private originalReplaceState?: typeof window.history.replaceState;\n\n constructor(eventManager: EventManager, onTrack: () => void) {\n super();\n\n this.eventManager = eventManager;\n this.onTrack = onTrack;\n }\n\n startTracking(): void {\n this.trackInitialPageView();\n\n window.addEventListener('popstate', this.trackCurrentPage, true);\n window.addEventListener('hashchange', this.trackCurrentPage, true);\n\n this.patchHistory('pushState');\n this.patchHistory('replaceState');\n }\n\n stopTracking(): void {\n window.removeEventListener('popstate', this.trackCurrentPage, true);\n window.removeEventListener('hashchange', this.trackCurrentPage, true);\n\n if (this.originalPushState) {\n window.history.pushState = this.originalPushState;\n }\n\n if (this.originalReplaceState) {\n window.history.replaceState = this.originalReplaceState;\n }\n }\n\n private patchHistory(method: 'pushState' | 'replaceState'): void {\n const original = window.history[method];\n\n if (method === 'pushState' && !this.originalPushState) {\n this.originalPushState = original;\n } else if (method === 'replaceState' && !this.originalReplaceState) {\n this.originalReplaceState = original;\n }\n\n window.history[method] = (...args: [unknown, string, string | URL | null | undefined]): void => {\n original.apply(window.history, args);\n this.trackCurrentPage();\n };\n }\n\n private readonly trackCurrentPage = async (): Promise<void> => {\n const rawUrl = window.location.href;\n const normalizedUrl = normalizeUrl(rawUrl, this.get('config').sensitiveQueryParams);\n\n if (this.get('pageUrl') === normalizedUrl) {\n return;\n }\n\n this.onTrack();\n\n const fromUrl = this.get('pageUrl');\n\n this.set('pageUrl', normalizedUrl);\n\n const pageViewData = this.extractPageViewData();\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: this.get('pageUrl'),\n from_page_url: fromUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n };\n\n private trackInitialPageView(): void {\n const normalizedUrl = normalizeUrl(window.location.href, this.get('config').sensitiveQueryParams);\n const pageViewData = this.extractPageViewData();\n\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: normalizedUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n\n this.onTrack();\n }\n\n private extractPageViewData(): PageViewData | undefined {\n const { pathname, search, hash } = window.location;\n const { referrer } = document;\n const { title } = document;\n\n // Early return if no meaningful data\n if (!referrer && !title && !pathname && !search && !hash) {\n return undefined;\n }\n\n const data: PageViewData = {\n ...(referrer && { referrer }),\n ...(title && { title }),\n ...(pathname && { pathname }),\n ...(search && { search }),\n ...(hash && { hash }),\n };\n\n return data;\n }\n}\n","import { HTML_DATA_ATTR_PREFIX, MAX_TEXT_LENGTH, INTERACTIVE_SELECTORS } from '../constants';\nimport { ClickCoordinates, ClickData, ClickTrackingElementData, EventType } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '@/utils';\n\nexport class ClickHandler extends StateManager {\n private readonly eventManager: EventManager;\n\n private clickHandler?: (event: Event) => void;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n if (this.clickHandler) {\n return;\n }\n\n this.clickHandler = (event: Event): void => {\n const mouseEvent = event as MouseEvent;\n const target = mouseEvent.target as EventTarget | null;\n const clickedElement =\n typeof HTMLElement !== 'undefined' && target instanceof HTMLElement\n ? target\n : typeof HTMLElement !== 'undefined' && target instanceof Node && target.parentElement instanceof HTMLElement\n ? target.parentElement\n : null;\n\n if (!clickedElement) {\n log('warn', 'Click target not found or not an element');\n return;\n }\n\n const trackingElement = this.findTrackingElement(clickedElement);\n const relevantClickElement = this.getRelevantClickElement(clickedElement);\n const coordinates = this.calculateClickCoordinates(mouseEvent, clickedElement);\n\n if (trackingElement) {\n const trackingData = this.extractTrackingData(trackingElement);\n\n if (trackingData) {\n const attributeData = this.createCustomEventData(trackingData);\n\n this.eventManager.track({\n type: EventType.CUSTOM,\n custom_event: {\n name: attributeData.name,\n ...(attributeData.value && { metadata: { value: attributeData.value } }),\n },\n });\n }\n }\n\n const clickData = this.generateClickData(clickedElement, relevantClickElement, coordinates);\n\n this.eventManager.track({\n type: EventType.CLICK,\n click_data: clickData,\n });\n };\n\n window.addEventListener('click', this.clickHandler, true);\n }\n\n stopTracking(): void {\n if (this.clickHandler) {\n window.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = undefined;\n }\n }\n\n private findTrackingElement(element: HTMLElement): HTMLElement | undefined {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-name`)) {\n return element;\n }\n\n const closest = element.closest(`[${HTML_DATA_ATTR_PREFIX}-name]`) as HTMLElement;\n\n return closest || undefined;\n }\n\n private getRelevantClickElement(element: HTMLElement): HTMLElement {\n for (const selector of INTERACTIVE_SELECTORS) {\n try {\n if (element.matches(selector)) {\n return element;\n }\n\n const parent = element.closest(selector) as HTMLElement;\n if (parent) {\n return parent;\n }\n } catch (error) {\n log('warn', 'Invalid selector in element search', { error, data: { selector } });\n continue;\n }\n }\n\n return element;\n }\n\n private clamp(value: number): number {\n return Math.max(0, Math.min(1, Number(value.toFixed(3))));\n }\n\n private calculateClickCoordinates(event: MouseEvent, element: HTMLElement): ClickCoordinates {\n const rect = element.getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n const relativeX = rect.width > 0 ? this.clamp((x - rect.left) / rect.width) : 0;\n const relativeY = rect.height > 0 ? this.clamp((y - rect.top) / rect.height) : 0;\n\n return { x, y, relativeX, relativeY };\n }\n\n private extractTrackingData(trackingElement: HTMLElement): ClickTrackingElementData | undefined {\n const name = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n const value = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-value`);\n\n if (!name) {\n return undefined;\n }\n\n return {\n element: trackingElement,\n name,\n ...(value && { value }),\n };\n }\n\n private generateClickData(\n clickedElement: HTMLElement,\n relevantElement: HTMLElement,\n coordinates: ClickCoordinates,\n ): ClickData {\n const { x, y, relativeX, relativeY } = coordinates;\n const text = this.getRelevantText(clickedElement, relevantElement);\n const attributes = this.extractElementAttributes(relevantElement);\n\n return {\n x,\n y,\n relativeX,\n relativeY,\n tag: relevantElement.tagName.toLowerCase(),\n ...(relevantElement.id && { id: relevantElement.id }),\n ...(relevantElement.className && { class: relevantElement.className }),\n ...(text && { text }),\n ...(attributes.href && { href: attributes.href }),\n ...(attributes.title && { title: attributes.title }),\n ...(attributes.alt && { alt: attributes.alt }),\n ...(attributes.role && { role: attributes.role }),\n ...(attributes['aria-label'] && { ariaLabel: attributes['aria-label'] }),\n ...(Object.keys(attributes).length > 0 && { dataAttributes: attributes }),\n };\n }\n\n private getRelevantText(clickedElement: HTMLElement, relevantElement: HTMLElement): string {\n const clickedText = clickedElement.textContent?.trim() ?? '';\n const relevantText = relevantElement.textContent?.trim() ?? '';\n\n if (!clickedText && !relevantText) {\n return '';\n }\n\n if (clickedText && clickedText.length <= MAX_TEXT_LENGTH) {\n return clickedText;\n }\n\n if (relevantText.length <= MAX_TEXT_LENGTH) {\n return relevantText;\n }\n\n return relevantText.slice(0, MAX_TEXT_LENGTH - 3) + '...';\n }\n\n private extractElementAttributes(element: HTMLElement): Record<string, string> {\n const commonAttributes = [\n 'id',\n 'class',\n 'data-testid',\n 'aria-label',\n 'title',\n 'href',\n 'type',\n 'name',\n 'alt',\n 'role',\n ];\n const result: Record<string, string> = {};\n\n for (const attributeName of commonAttributes) {\n const value = element.getAttribute(attributeName);\n\n if (value) {\n result[attributeName] = value;\n }\n }\n\n return result;\n }\n\n private createCustomEventData(trackingData: ClickTrackingElementData): { name: string; value?: string } {\n return {\n name: trackingData.name,\n ...(trackingData.value && { value: trackingData.value }),\n };\n }\n}\n","import {\n MAX_SCROLL_EVENTS_PER_SESSION,\n MIN_SCROLL_DEPTH_CHANGE,\n SCROLL_DEBOUNCE_TIME_MS,\n SCROLL_MIN_EVENT_INTERVAL_MS,\n SIGNIFICANT_SCROLL_DELTA,\n} from '../constants';\nimport { EventType, ScrollData, ScrollDirection } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\ninterface ScrollContainer {\n element: Window | HTMLElement;\n lastScrollPos: number;\n lastDepth: number;\n lastDirection: ScrollDirection;\n lastEventTime: number;\n debounceTimer: number | null;\n listener: EventListener;\n}\n\nexport class ScrollHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly containers: ScrollContainer[] = [];\n private limitWarningLogged = false;\n private minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n private minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n private maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n this.limitWarningLogged = false;\n this.applyConfigOverrides();\n this.set('scrollEventCount', 0);\n\n const raw = this.get('config').scrollContainerSelectors;\n const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];\n\n if (selectors.length === 0) {\n this.setupScrollContainer(window);\n } else {\n this.trySetupContainers(selectors, 0);\n }\n }\n\n stopTracking(): void {\n for (const container of this.containers) {\n this.clearContainerTimer(container);\n\n if (container.element instanceof Window) {\n window.removeEventListener('scroll', container.listener);\n } else {\n container.element.removeEventListener('scroll', container.listener);\n }\n }\n\n this.containers.length = 0;\n this.set('scrollEventCount', 0);\n this.limitWarningLogged = false;\n }\n\n private trySetupContainers(selectors: string[], attempt: number): void {\n const elements: HTMLElement[] = selectors\n .map((sel) => this.safeQuerySelector(sel))\n .filter(\n (element): element is HTMLElement =>\n element != null && typeof HTMLElement !== 'undefined' && element instanceof HTMLElement,\n );\n\n if (elements.length > 0) {\n for (const element of elements) {\n const isAlreadyTracking = this.containers.some((c) => c.element === element);\n\n if (!isAlreadyTracking) {\n this.setupScrollContainer(element);\n }\n }\n\n return;\n }\n\n if (attempt < 5) {\n setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);\n return;\n }\n\n if (this.containers.length === 0) {\n this.setupScrollContainer(window);\n }\n }\n\n private setupScrollContainer(element: Window | HTMLElement): void {\n if (element !== window && !this.isElementScrollable(element as HTMLElement)) {\n return;\n }\n\n const handleScroll = (): void => {\n if (this.get('suppressNextScroll')) {\n return;\n }\n\n this.clearContainerTimer(container);\n\n container.debounceTimer = window.setTimeout(() => {\n const scrollData = this.calculateScrollData(container);\n\n if (scrollData) {\n const now = Date.now();\n\n this.processScrollEvent(container, scrollData, now);\n }\n\n container.debounceTimer = null;\n }, SCROLL_DEBOUNCE_TIME_MS);\n };\n\n const initialScrollTop = this.getScrollTop(element);\n const container: ScrollContainer = {\n element,\n lastScrollPos: initialScrollTop,\n lastDepth: this.calculateScrollDepth(\n initialScrollTop,\n this.getScrollHeight(element),\n this.getViewportHeight(element),\n ),\n lastDirection: ScrollDirection.DOWN,\n lastEventTime: 0,\n debounceTimer: null,\n listener: handleScroll,\n };\n\n this.containers.push(container);\n\n if (element instanceof Window) {\n window.addEventListener('scroll', handleScroll, { passive: true });\n } else {\n element.addEventListener('scroll', handleScroll, { passive: true });\n }\n }\n\n private processScrollEvent(container: ScrollContainer, scrollData: ScrollData, timestamp: number): void {\n if (!this.shouldEmitScrollEvent(container, scrollData, timestamp)) {\n return;\n }\n\n container.lastEventTime = timestamp;\n container.lastDepth = scrollData.depth;\n container.lastDirection = scrollData.direction;\n\n const currentCount = this.get('scrollEventCount') ?? 0;\n this.set('scrollEventCount', currentCount + 1);\n\n this.eventManager.track({\n type: EventType.SCROLL,\n scroll_data: scrollData,\n });\n }\n\n private shouldEmitScrollEvent(container: ScrollContainer, scrollData: ScrollData, timestamp: number): boolean {\n if (this.hasReachedSessionLimit()) {\n this.logLimitOnce();\n return false;\n }\n\n if (!this.hasElapsedMinimumInterval(container, timestamp)) {\n return false;\n }\n\n if (!this.hasSignificantDepthChange(container, scrollData.depth)) {\n return false;\n }\n\n return true;\n }\n\n private hasReachedSessionLimit(): boolean {\n const currentCount = this.get('scrollEventCount') ?? 0;\n return currentCount >= this.maxEventsPerSession;\n }\n\n private hasElapsedMinimumInterval(container: ScrollContainer, timestamp: number): boolean {\n if (container.lastEventTime === 0) {\n return true;\n }\n return timestamp - container.lastEventTime >= this.minIntervalMs;\n }\n\n private hasSignificantDepthChange(container: ScrollContainer, newDepth: number): boolean {\n return Math.abs(newDepth - container.lastDepth) >= this.minDepthChange;\n }\n\n private logLimitOnce(): void {\n if (this.limitWarningLogged) {\n return;\n }\n\n this.limitWarningLogged = true;\n\n log('warn', 'Max scroll events per session reached', {\n data: { limit: this.maxEventsPerSession },\n });\n }\n\n private applyConfigOverrides(): void {\n this.minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n this.minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n this.maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n }\n\n private isWindowScrollable(): boolean {\n return document.documentElement.scrollHeight > window.innerHeight;\n }\n\n private clearContainerTimer(container: ScrollContainer): void {\n if (container.debounceTimer !== null) {\n clearTimeout(container.debounceTimer);\n container.debounceTimer = null;\n }\n }\n\n private getScrollDirection(current: number, previous: number): ScrollDirection {\n return current > previous ? ScrollDirection.DOWN : ScrollDirection.UP;\n }\n\n private calculateScrollDepth(scrollTop: number, scrollHeight: number, viewportHeight: number): number {\n if (scrollHeight <= viewportHeight) {\n return 0;\n }\n\n const maxScrollTop = scrollHeight - viewportHeight;\n return Math.min(100, Math.max(0, Math.floor((scrollTop / maxScrollTop) * 100)));\n }\n\n private calculateScrollData(container: ScrollContainer): ScrollData | null {\n const { element, lastScrollPos } = container;\n const scrollTop = this.getScrollTop(element);\n\n const positionDelta = Math.abs(scrollTop - lastScrollPos);\n if (positionDelta < SIGNIFICANT_SCROLL_DELTA) {\n return null;\n }\n\n if (element === window && !this.isWindowScrollable()) {\n return null;\n }\n\n const viewportHeight = this.getViewportHeight(element);\n const scrollHeight = this.getScrollHeight(element);\n const direction = this.getScrollDirection(scrollTop, lastScrollPos);\n const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);\n\n container.lastScrollPos = scrollTop;\n\n return { depth, direction };\n }\n\n private getScrollTop(element: Window | HTMLElement): number {\n return element instanceof Window ? window.scrollY : element.scrollTop;\n }\n\n private getViewportHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? window.innerHeight : element.clientHeight;\n }\n\n private getScrollHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? document.documentElement.scrollHeight : element.scrollHeight;\n }\n\n private isElementScrollable(element: HTMLElement): boolean {\n const style = getComputedStyle(element);\n const hasScrollableOverflow =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflowX === 'auto' ||\n style.overflowX === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n const hasOverflowContent = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;\n\n return hasScrollableOverflow && hasOverflowContent;\n }\n\n private safeQuerySelector(selector: string): HTMLElement | null {\n try {\n return document.querySelector(selector);\n } catch (error) {\n log('warn', 'Invalid CSS selector', {\n error,\n data: { selector },\n showToClient: true,\n });\n\n return null;\n }\n }\n}\n","import { MetadataType } from '../types';\nimport { log } from '../utils';\nimport { StateManager } from '../managers/state.manager';\n\ndeclare global {\n interface Window {\n gtag?: (...args: unknown[]) => void;\n dataLayer?: unknown[];\n }\n}\n\nexport class GoogleAnalyticsIntegration extends StateManager {\n private isInitialized = false;\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n const measurementId = this.get('config').integrations?.googleAnalytics?.measurementId;\n const userId = this.get('userId');\n\n if (!measurementId?.trim() || !userId?.trim()) {\n return;\n }\n\n try {\n if (this.isScriptAlreadyLoaded()) {\n this.isInitialized = true;\n return;\n }\n\n await this.loadScript(measurementId);\n this.configureGtag(measurementId, userId);\n this.isInitialized = true;\n } catch (error) {\n log('error', 'Google Analytics initialization failed', { error });\n }\n }\n\n trackEvent(eventName: string, metadata: Record<string, MetadataType> | Record<string, MetadataType>[]): void {\n if (!eventName?.trim() || !this.isInitialized || typeof window.gtag !== 'function') {\n return;\n }\n\n try {\n const normalizedMetadata = Array.isArray(metadata) ? { items: metadata } : metadata;\n window.gtag('event', eventName, normalizedMetadata);\n } catch (error) {\n log('error', 'Google Analytics event tracking failed', { error });\n }\n }\n\n cleanup(): void {\n this.isInitialized = false;\n const script = document.getElementById('tracelog-ga-script');\n if (script) {\n script.remove();\n }\n }\n\n private isScriptAlreadyLoaded(): boolean {\n // Check if we already loaded the script\n if (document.getElementById('tracelog-ga-script')) {\n return true;\n }\n\n // Check if GA is already loaded by another source\n const existingGAScript = document.querySelector('script[src*=\"googletagmanager.com/gtag/js\"]');\n return !!existingGAScript;\n }\n\n private async loadScript(measurementId: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.id = 'tracelog-ga-script';\n script.async = true;\n script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('Failed to load Google Analytics script'));\n\n document.head.appendChild(script);\n });\n }\n\n private configureGtag(measurementId: string, userId: string): void {\n const gaScriptConfig = document.createElement('script');\n gaScriptConfig.innerHTML = `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${measurementId}', {\n 'user_id': '${userId}'\n });\n `;\n document.head.appendChild(gaScriptConfig);\n }\n}\n","import { log } from '../utils';\n\n/**\n * Manages localStorage and sessionStorage with automatic fallback to in-memory storage.\n * Provides a consistent interface for storing session data, configuration,\n * and analytics metadata across browser environments.\n */\nexport class StorageManager {\n private readonly storage: Storage | null;\n private readonly sessionStorageRef: Storage | null;\n private readonly fallbackStorage = new Map<string, string>();\n private readonly fallbackSessionStorage = new Map<string, string>();\n\n private hasQuotaExceededError = false;\n\n constructor() {\n this.storage = this.initializeStorage('localStorage');\n this.sessionStorageRef = this.initializeStorage('sessionStorage');\n\n if (!this.storage) {\n log('warn', 'localStorage not available, using memory fallback');\n }\n if (!this.sessionStorageRef) {\n log('warn', 'sessionStorage not available, using memory fallback');\n }\n }\n\n /**\n * Retrieves an item from storage\n */\n getItem(key: string): string | null {\n try {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n return this.fallbackStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in storage\n */\n setItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n // This ensures fallback is in sync and can serve as backup if storage fails\n this.fallbackStorage.set(key, value);\n\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n this.hasQuotaExceededError = true;\n\n log('warn', 'localStorage quota exceeded, attempting cleanup', {\n data: { key, valueSize: value.length },\n });\n\n // Attempt to free up space by removing old TraceLog data\n const cleanedUp = this.cleanupOldData();\n\n if (cleanedUp) {\n // Retry after cleanup\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n // Successfully stored after cleanup\n return;\n }\n } catch (retryError) {\n log('error', 'localStorage quota exceeded even after cleanup - data will not persist', {\n error: retryError,\n data: { key, valueSize: value.length },\n });\n }\n } else {\n log('error', 'localStorage quota exceeded and no data to cleanup - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from storage\n */\n removeItem(key: string): void {\n try {\n if (this.storage) {\n this.storage.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackStorage.delete(key);\n }\n\n /**\n * Clears all TracLog-related items from storage\n */\n clear(): void {\n if (!this.storage) {\n this.fallbackStorage.clear();\n return;\n }\n\n try {\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => this.storage!.removeItem(key));\n this.fallbackStorage.clear();\n } catch (error) {\n log('error', 'Failed to clear storage', { error });\n this.fallbackStorage.clear();\n }\n }\n\n /**\n * Checks if storage is available\n */\n isAvailable(): boolean {\n return this.storage !== null;\n }\n\n /**\n * Checks if a QuotaExceededError has occurred\n * This indicates localStorage is full and data may not persist\n */\n hasQuotaError(): boolean {\n return this.hasQuotaExceededError;\n }\n\n /**\n * Attempts to cleanup old TraceLog data from storage to free up space\n * Returns true if any data was removed, false otherwise\n */\n private cleanupOldData(): boolean {\n if (!this.storage) {\n return false;\n }\n\n try {\n const tracelogKeys: string[] = [];\n const persistedEventsKeys: string[] = [];\n\n // Collect all TraceLog keys\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n tracelogKeys.push(key);\n\n // Prioritize removing old persisted events\n if (key.startsWith('tracelog_persisted_events_')) {\n persistedEventsKeys.push(key);\n }\n }\n }\n\n // First, try to remove old persisted events (usually the largest data)\n if (persistedEventsKeys.length > 0) {\n persistedEventsKeys.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n // If no persisted events, remove non-critical keys\n // Define critical key prefixes that should be preserved\n const criticalPrefixes = ['tracelog_session_', 'tracelog_user_id', 'tracelog_device_id', 'tracelog_config'];\n\n const nonCriticalKeys = tracelogKeys.filter((key) => {\n // Keep keys that start with any critical prefix\n return !criticalPrefixes.some((prefix) => key.startsWith(prefix));\n });\n\n if (nonCriticalKeys.length > 0) {\n // Remove up to 5 non-critical keys\n const keysToRemove = nonCriticalKeys.slice(0, 5);\n keysToRemove.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n return false;\n } catch (error) {\n log('error', 'Failed to cleanup old data', { error });\n return false;\n }\n }\n\n /**\n * Initialize storage (localStorage or sessionStorage) with feature detection\n */\n private initializeStorage(type: 'localStorage' | 'sessionStorage'): Storage | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const storage = type === 'localStorage' ? window.localStorage : window.sessionStorage;\n const testKey = '__tracelog_test__';\n\n storage.setItem(testKey, 'test');\n storage.removeItem(testKey);\n\n return storage;\n } catch {\n return null;\n }\n }\n\n /**\n * Retrieves an item from sessionStorage\n */\n getSessionItem(key: string): string | null {\n try {\n if (this.sessionStorageRef) {\n return this.sessionStorageRef.getItem(key);\n }\n return this.fallbackSessionStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackSessionStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in sessionStorage\n */\n setSessionItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n this.fallbackSessionStorage.set(key, value);\n\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n log('error', 'sessionStorage quota exceeded - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackSessionStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from sessionStorage\n */\n removeSessionItem(key: string): void {\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackSessionStorage.delete(key);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, WebVitalType } from '../types';\nimport { LONG_TASK_THROTTLE_MS, PRECISION_TWO_DECIMALS, WEB_VITALS_THRESHOLDS } from '../constants';\nimport { log } from '@/utils';\n\ntype LayoutShiftEntry = PerformanceEntry & { value?: number; hadRecentInput?: boolean };\n\nexport class PerformanceHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly reportedByNav: Map<string, Set<string>> = new Map();\n\n private readonly observers: PerformanceObserver[] = [];\n private lastLongTaskSentAt = 0;\n\n private readonly vitalThresholds = WEB_VITALS_THRESHOLDS;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n async startTracking(): Promise<void> {\n await this.initWebVitals();\n this.observeLongTasks();\n }\n\n stopTracking(): void {\n this.observers.forEach((obs, index) => {\n try {\n obs.disconnect();\n } catch (error) {\n log('warn', 'Failed to disconnect performance observer', { error, data: { observerIndex: index } });\n }\n });\n\n this.observers.length = 0;\n this.reportedByNav.clear();\n }\n\n private observeWebVitalsFallback(): void {\n // TTFB - should be captured immediately as it's available from navigation timing\n this.reportTTFB();\n\n // LCP\n this.safeObserve(\n 'largest-contentful-paint',\n (list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1] as (PerformanceEntry & { startTime: number }) | undefined;\n\n if (!last) {\n return;\n }\n\n this.sendVital({ type: 'LCP', value: Number(last.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'largest-contentful-paint', buffered: true },\n true,\n );\n\n // CLS (layout-shift)\n let clsValue = 0;\n let currentNavId = this.getNavigationId();\n\n this.safeObserve(\n 'layout-shift',\n (list) => {\n const navId = this.getNavigationId();\n\n // Reset CLS on navigation change\n if (navId !== currentNavId) {\n clsValue = 0;\n currentNavId = navId;\n }\n\n const entries = list.getEntries() as LayoutShiftEntry[];\n\n for (const entry of entries) {\n if (entry.hadRecentInput === true) {\n continue;\n }\n\n const value = typeof entry.value === 'number' ? entry.value : 0;\n clsValue += value;\n }\n\n this.sendVital({ type: 'CLS', value: Number(clsValue.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'layout-shift', buffered: true },\n );\n\n // FCP\n this.safeObserve(\n 'paint',\n (list) => {\n for (const entry of list.getEntries()) {\n if (entry.name === 'first-contentful-paint') {\n this.sendVital({ type: 'FCP', value: Number(entry.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n }\n },\n { type: 'paint', buffered: true },\n true,\n );\n\n // INP via performance event timing (where supported)\n this.safeObserve(\n 'event',\n (list) => {\n let worst = 0;\n const entries = list.getEntries() as Array<{ startTime: number; processingEnd?: number }>;\n\n for (const entry of entries) {\n const dur = (entry.processingEnd ?? 0) - (entry.startTime ?? 0);\n worst = Math.max(worst, dur);\n }\n\n if (worst > 0) {\n this.sendVital({ type: 'INP', value: Number(worst.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n },\n { type: 'event', buffered: true },\n );\n }\n\n private async initWebVitals(): Promise<void> {\n try {\n const { onLCP, onCLS, onFCP, onTTFB, onINP } = await import('web-vitals');\n\n const report =\n (type: WebVitalType) =>\n (metric: { value: number }): void => {\n const value = Number(metric.value.toFixed(PRECISION_TWO_DECIMALS));\n this.sendVital({ type, value });\n };\n\n onLCP(report('LCP'));\n onCLS(report('CLS'));\n onFCP(report('FCP'));\n onTTFB(report('TTFB'));\n onINP(report('INP'));\n } catch (error) {\n log('warn', 'Failed to load web-vitals library, using fallback', { error });\n this.observeWebVitalsFallback();\n }\n }\n\n private reportTTFB(): void {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return;\n }\n\n const ttfb = nav.responseStart;\n\n // TTFB can be 0 in some browsers (especially Mobile Safari) when:\n // - Response is served from cache\n // - Connection is reused\n // - Browser cannot determine exact timing\n // We still report it as it's a valid measurement\n if (typeof ttfb === 'number' && Number.isFinite(ttfb)) {\n this.sendVital({ type: 'TTFB', value: Number(ttfb.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n } catch (error) {\n log('warn', 'Failed to report TTFB', { error });\n }\n }\n\n private observeLongTasks(): void {\n this.safeObserve(\n 'longtask',\n (list) => {\n const entries = list.getEntries() as Array<{ duration: number }>;\n\n for (const entry of entries) {\n const duration = Number(entry.duration.toFixed(PRECISION_TWO_DECIMALS));\n const now = Date.now();\n\n if (now - this.lastLongTaskSentAt >= LONG_TASK_THROTTLE_MS) {\n if (this.shouldSendVital('LONG_TASK', duration)) {\n this.trackWebVital('LONG_TASK', duration);\n }\n this.lastLongTaskSentAt = now;\n }\n }\n },\n { type: 'longtask', buffered: true },\n );\n }\n\n private sendVital(sample: { type: WebVitalType; value: number }): void {\n if (!this.shouldSendVital(sample.type, sample.value)) {\n return;\n }\n\n const navId = this.getNavigationId();\n\n // Check for duplicates if we have a navigation ID\n if (navId) {\n const reportedForNav = this.reportedByNav.get(navId);\n const isDuplicate = reportedForNav?.has(sample.type);\n\n if (isDuplicate) {\n return;\n }\n\n // Initialize or update reported vitals for this navigation\n if (!reportedForNav) {\n this.reportedByNav.set(navId, new Set([sample.type]));\n } else {\n reportedForNav.add(sample.type);\n }\n }\n\n this.trackWebVital(sample.type, sample.value);\n }\n\n private trackWebVital(type: WebVitalType, value: number): void {\n if (!Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return;\n }\n\n this.eventManager.track({\n type: EventType.WEB_VITALS,\n web_vitals: {\n type,\n value,\n },\n });\n }\n\n private getNavigationId(): string | null {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return null;\n }\n\n // Use more precise timestamp and add random component to prevent collisions\n const timestamp = nav.startTime || performance.now();\n const random = Math.random().toString(36).substr(2, 5);\n return `${timestamp.toFixed(2)}_${window.location.pathname}_${random}`;\n } catch (error) {\n log('warn', 'Failed to get navigation ID', { error });\n return null;\n }\n }\n\n private isObserverSupported(type: string): boolean {\n if (typeof PerformanceObserver === 'undefined') return false;\n const supported = PerformanceObserver.supportedEntryTypes;\n return !supported || supported.includes(type);\n }\n\n private safeObserve(\n type: string,\n cb: PerformanceObserverCallback,\n options?: PerformanceObserverInit,\n once = false,\n ): boolean {\n try {\n if (!this.isObserverSupported(type)) {\n return false;\n }\n\n const obs = new PerformanceObserver((list, observer) => {\n try {\n cb(list, observer);\n } catch (callbackError) {\n log('warn', 'Observer callback failed', {\n error: callbackError,\n data: { type },\n });\n }\n\n if (once) {\n try {\n observer.disconnect();\n } catch {\n // Disconnect errors are safe to ignore\n }\n }\n });\n\n obs.observe(options ?? { type, buffered: true });\n\n if (!once) {\n this.observers.push(obs);\n }\n\n return true;\n } catch (error) {\n log('warn', 'Failed to create performance observer', {\n error,\n data: { type },\n });\n return false;\n }\n }\n\n private shouldSendVital(type: WebVitalType, value?: number): boolean {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return false;\n }\n\n const threshold = this.vitalThresholds[type];\n\n if (typeof threshold === 'number' && value <= threshold) {\n return false;\n }\n\n return true;\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { ErrorType, EventType } from '../types';\nimport {\n PII_PATTERNS,\n MAX_ERROR_MESSAGE_LENGTH,\n ERROR_SUPPRESSION_WINDOW_MS,\n MAX_TRACKED_ERRORS,\n MAX_TRACKED_ERRORS_HARD_LIMIT,\n} from '../constants/error.constants';\n\n/**\n * Simplified error handler for tracking JavaScript errors and unhandled promise rejections\n * Includes PII sanitization and sampling support\n */\nexport class ErrorHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly recentErrors = new Map<string, number>();\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n window.addEventListener('error', this.handleError);\n window.addEventListener('unhandledrejection', this.handleRejection);\n }\n\n stopTracking(): void {\n window.removeEventListener('error', this.handleError);\n window.removeEventListener('unhandledrejection', this.handleRejection);\n this.recentErrors.clear();\n }\n\n private shouldSample(): boolean {\n const config = this.get('config');\n const samplingRate = config?.errorSampling ?? 0.1;\n return Math.random() < samplingRate;\n }\n\n private readonly handleError = (event: ErrorEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const sanitizedMessage = this.sanitize(event.message || 'Unknown error');\n\n if (this.shouldSuppressError(ErrorType.JS_ERROR, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.JS_ERROR,\n message: sanitizedMessage,\n ...(event.filename && { filename: event.filename }),\n ...(event.lineno && { line: event.lineno }),\n ...(event.colno && { column: event.colno }),\n },\n });\n };\n\n private readonly handleRejection = (event: PromiseRejectionEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const message = this.extractRejectionMessage(event.reason);\n const sanitizedMessage = this.sanitize(message);\n\n if (this.shouldSuppressError(ErrorType.PROMISE_REJECTION, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.PROMISE_REJECTION,\n message: sanitizedMessage,\n },\n });\n };\n\n private extractRejectionMessage(reason: unknown): string {\n if (!reason) return 'Unknown rejection';\n\n if (typeof reason === 'string') return reason;\n\n if (reason instanceof Error) {\n return reason.stack ?? reason.message ?? reason.toString();\n }\n\n // Handle objects with message property\n if (typeof reason === 'object' && 'message' in reason) {\n return String(reason.message);\n }\n\n // Try to stringify objects\n try {\n return JSON.stringify(reason);\n } catch {\n return String(reason);\n }\n }\n\n private sanitize(text: string): string {\n let sanitized = text.length > MAX_ERROR_MESSAGE_LENGTH ? text.slice(0, MAX_ERROR_MESSAGE_LENGTH) + '...' : text;\n\n for (const pattern of PII_PATTERNS) {\n // Create new regex instance to avoid global flag state issues\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private shouldSuppressError(type: ErrorType, message: string): boolean {\n const now = Date.now();\n const key = `${type}:${message}`;\n const lastSeenAt = this.recentErrors.get(key);\n\n if (lastSeenAt && now - lastSeenAt < ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.set(key, now);\n return true;\n }\n\n this.recentErrors.set(key, now);\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS_HARD_LIMIT) {\n // Hard limit exceeded, clearing all tracked errors\n this.recentErrors.clear();\n this.recentErrors.set(key, now);\n\n return false;\n }\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS) {\n this.pruneOldErrors();\n }\n\n return false;\n }\n\n private pruneOldErrors(): void {\n const now = Date.now();\n for (const [key, timestamp] of this.recentErrors.entries()) {\n if (now - timestamp > ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.delete(key);\n }\n }\n\n if (this.recentErrors.size <= MAX_TRACKED_ERRORS) {\n return;\n }\n\n const entries = Array.from(this.recentErrors.entries()).sort((a, b) => a[1] - b[1]);\n const excess = this.recentErrors.size - MAX_TRACKED_ERRORS;\n\n for (let index = 0; index < excess; index += 1) {\n const entry = entries[index];\n if (entry) {\n this.recentErrors.delete(entry[0]);\n }\n }\n }\n}\n","import { EventManager } from './managers/event.manager';\nimport { UserManager } from './managers/user.manager';\nimport { StateManager } from './managers/state.manager';\nimport { SessionHandler } from './handlers/session.handler';\nimport { PageViewHandler } from './handlers/page-view.handler';\nimport { ClickHandler } from './handlers/click.handler';\nimport { ScrollHandler } from './handlers/scroll.handler';\nimport { Config, EventType, EmitterCallback, EmitterMap, Mode } from './types';\nimport { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';\nimport { isEventValid, getDeviceType, normalizeUrl, Emitter, getCollectApiUrl, detectQaMode, log } from './utils';\nimport { StorageManager } from './managers/storage.manager';\nimport { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';\nimport { PerformanceHandler } from './handlers/performance.handler';\nimport { ErrorHandler } from './handlers/error.handler';\n\nexport class App extends StateManager {\n private isInitialized = false;\n private suppressNextScrollTimer: number | null = null;\n\n private readonly emitter = new Emitter();\n\n protected managers: {\n storage?: StorageManager;\n event?: EventManager;\n } = {};\n\n protected handlers: {\n session?: SessionHandler;\n pageView?: PageViewHandler;\n click?: ClickHandler;\n scroll?: ScrollHandler;\n performance?: PerformanceHandler;\n error?: ErrorHandler;\n } = {};\n\n protected integrations: {\n googleAnalytics?: GoogleAnalyticsIntegration;\n } = {};\n\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n async init(config: Config = {}): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n this.managers.storage = new StorageManager();\n\n try {\n this.setupState(config);\n await this.setupIntegrations();\n\n this.managers.event = new EventManager(this.managers.storage, this.integrations.googleAnalytics, this.emitter);\n\n await this.initializeHandlers();\n\n await this.managers.event.recoverPersistedEvents().catch((error) => {\n log('warn', 'Failed to recover persisted events', { error });\n });\n\n this.isInitialized = true;\n } catch (error) {\n await this.destroy(true);\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] TraceLog initialization failed: ${errorMessage}`);\n }\n }\n\n sendCustomEvent(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void {\n if (!this.managers.event) {\n return;\n }\n\n const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);\n\n if (!valid) {\n if (this.get('mode') === Mode.QA) {\n throw new Error(`[TraceLog] Custom event \"${name}\" validation failed: ${error}`);\n }\n\n return;\n }\n\n this.managers.event.track({\n type: EventType.CUSTOM,\n custom_event: {\n name,\n ...(sanitizedMetadata && { metadata: sanitizedMetadata }),\n },\n });\n }\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.on(event, callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.off(event, callback);\n }\n\n async destroy(force = false): Promise<void> {\n if (!this.isInitialized && !force) {\n return;\n }\n\n this.integrations.googleAnalytics?.cleanup();\n\n const handlerCleanups = Object.values(this.handlers)\n .filter(Boolean)\n .map(async (handler) => {\n try {\n await handler.stopTracking();\n } catch (error) {\n log('warn', 'Failed to stop tracking', { error });\n }\n });\n\n await Promise.allSettled(handlerCleanups);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n this.suppressNextScrollTimer = null;\n }\n\n this.managers.event?.flushImmediatelySync();\n\n this.managers.event?.stop();\n\n this.emitter.removeAllListeners();\n\n this.set('hasStartSession', false);\n this.set('suppressNextScroll', false);\n this.set('sessionId', null);\n\n this.isInitialized = false;\n this.handlers = {};\n }\n\n private setupState(config: Config = {}): void {\n this.set('config', config);\n\n const userId = UserManager.getId(this.managers.storage as StorageManager);\n this.set('userId', userId);\n\n const collectApiUrl = getCollectApiUrl(config);\n this.set('collectApiUrl', collectApiUrl);\n\n const device = getDeviceType();\n this.set('device', device);\n\n const pageUrl = normalizeUrl(window.location.href, config.sensitiveQueryParams);\n this.set('pageUrl', pageUrl);\n\n const mode = detectQaMode() ? Mode.QA : undefined;\n\n if (mode) {\n this.set('mode', mode);\n }\n }\n\n private async setupIntegrations(): Promise<void> {\n const config = this.get('config');\n const measurementId = config.integrations?.googleAnalytics?.measurementId;\n\n if (measurementId?.trim()) {\n try {\n this.integrations.googleAnalytics = new GoogleAnalyticsIntegration();\n await this.integrations.googleAnalytics.initialize();\n } catch {\n this.integrations.googleAnalytics = undefined;\n }\n }\n }\n\n private async initializeHandlers(): Promise<void> {\n this.handlers.session = new SessionHandler(\n this.managers.storage as StorageManager,\n this.managers.event as EventManager,\n );\n\n await this.handlers.session.startTracking();\n\n const onPageView = (): void => {\n this.set('suppressNextScroll', true);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n }\n\n this.suppressNextScrollTimer = window.setTimeout(() => {\n this.set('suppressNextScroll', false);\n }, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESS_MULTIPLIER);\n };\n\n this.handlers.pageView = new PageViewHandler(this.managers.event as EventManager, onPageView);\n this.handlers.pageView.startTracking();\n\n this.handlers.click = new ClickHandler(this.managers.event as EventManager);\n this.handlers.click.startTracking();\n\n this.handlers.scroll = new ScrollHandler(this.managers.event as EventManager);\n this.handlers.scroll.startTracking();\n\n this.handlers.performance = new PerformanceHandler(this.managers.event as EventManager);\n this.handlers.performance.startTracking().catch((error) => {\n log('warn', 'Failed to start performance tracking', { error });\n });\n\n this.handlers.error = new ErrorHandler(this.managers.event as EventManager);\n this.handlers.error.startTracking();\n }\n}\n","import { App } from './app';\nimport { MetadataType, Config, EmitterCallback, EmitterMap } from './types';\nimport { log, validateAndNormalizeConfig } from './utils';\nimport { TestBridge } from './test-bridge';\nimport { INITIALIZATION_TIMEOUT_MS } from './constants';\nimport './types/window.types';\n\ninterface PendingListener {\n event: keyof EmitterMap;\n callback: EmitterCallback<EmitterMap[keyof EmitterMap]>;\n}\n\n// Buffer for listeners registered before init()\nconst pendingListeners: PendingListener[] = [];\n\nlet app: App | null = null;\nlet isInitializing = false;\nlet isDestroying = false;\n\nexport const init = async (config?: Config): Promise<void> => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[TraceLog] This library can only be used in a browser environment');\n }\n\n if (window.__traceLogDisabled) {\n return;\n }\n\n if (app) {\n return;\n }\n\n if (isInitializing) {\n return;\n }\n\n isInitializing = true;\n\n try {\n const validatedConfig = validateAndNormalizeConfig(config ?? {});\n const instance = new App();\n\n try {\n // Attach buffered listeners BEFORE init() so they capture initial events\n pendingListeners.forEach(({ event, callback }) => {\n instance.on(event, callback as EmitterCallback<EmitterMap[typeof event]>);\n });\n pendingListeners.length = 0;\n\n // Wrap initialization with timeout using Promise.race\n const initPromise = instance.init(validatedConfig);\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`[TraceLog] Initialization timeout after ${INITIALIZATION_TIMEOUT_MS}ms`));\n }, INITIALIZATION_TIMEOUT_MS);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n\n app = instance;\n } catch (error) {\n try {\n await instance.destroy(true);\n } catch (cleanupError) {\n log('error', 'Failed to cleanup partially initialized app', { error: cleanupError });\n }\n\n throw error;\n }\n } catch (error) {\n app = null;\n throw error;\n } finally {\n isInitializing = false;\n }\n};\n\nexport const event = (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]): void => {\n if (!app) {\n throw new Error('[TraceLog] TraceLog not initialized. Please call init() first.');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Cannot send events while TraceLog is being destroyed');\n }\n\n app.sendCustomEvent(name, metadata);\n};\n\nexport const on = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (!app || isInitializing) {\n // Buffer listeners registered before or during init()\n pendingListeners.push({ event, callback } as PendingListener);\n return;\n }\n\n app.on(event, callback);\n};\n\nexport const off = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (!app) {\n // Remove from pending listeners if not yet initialized\n const index = pendingListeners.findIndex((l) => l.event === event && l.callback === callback);\n if (index !== -1) {\n pendingListeners.splice(index, 1);\n }\n return;\n }\n\n app.off(event, callback);\n};\n\nexport const isInitialized = (): boolean => {\n return app !== null;\n};\n\nexport const destroy = async (): Promise<void> => {\n if (!app) {\n throw new Error('[TraceLog] App not initialized');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Destroy operation already in progress');\n }\n\n isDestroying = true;\n\n try {\n await app.destroy();\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Clear TestBridge reference in dev mode to prevent stale references\n if (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined' && window.__traceLogBridge) {\n // Don't call destroy on bridge (would cause recursion), just clear reference\n window.__traceLogBridge = undefined as any;\n }\n } catch (error) {\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Log error but don't re-throw - destroy should always complete successfully\n // Applications should be able to tear down TraceLog even if internal cleanup fails\n log('warn', 'Error during destroy, forced cleanup completed', { error });\n } finally {\n isDestroying = false;\n }\n};\n\nif (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined') {\n const injectTestingBridge = (): void => {\n window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectTestingBridge);\n } else {\n injectTestingBridge();\n }\n}\n\n/**\n * Internal sync function - ONLY for TestBridge in development\n *\n * WARNING: This function is internal and should NEVER be called directly.\n * It's only exported for TestBridge synchronization in dev mode.\n *\n * @internal\n */\nexport const __setAppInstance = (instance: App | null): void => {\n if (instance !== null) {\n const hasRequiredMethods =\n typeof instance === 'object' &&\n 'init' in instance &&\n 'destroy' in instance &&\n 'on' in instance &&\n 'off' in instance;\n\n if (!hasRequiredMethods) {\n throw new Error('[TraceLog] Invalid app instance type');\n }\n }\n\n // Prevent overwriting an already initialized app (except when clearing)\n if (app !== null && instance !== null && app !== instance) {\n throw new Error('[TraceLog] Cannot overwrite existing app instance. Call destroy() first.');\n }\n\n app = instance;\n};\n","import { WEB_VITALS_THRESHOLDS } from './constants/performance.constants';\nimport { PII_PATTERNS } from './constants/error.constants';\n\nexport const PERFORMANCE_CONFIG = {\n WEB_VITALS_THRESHOLDS, // Business thresholds for performance analysis\n} as const;\n\nexport const DATA_PROTECTION = {\n PII_PATTERNS, // Patterns for sensitive data protection\n} as const;\n\nexport const ENGAGEMENT_THRESHOLDS = {\n LOW_ACTIVITY_EVENT_COUNT: 50,\n HIGH_ACTIVITY_EVENT_COUNT: 1000,\n MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,\n MIN_EVENTS_FOR_TREND_ANALYSIS: 30,\n BOUNCE_RATE_SESSION_THRESHOLD: 1, // Sessions with 1 page view = bounce\n MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1000,\n MIN_SCROLL_DEPTH_ENGAGEMENT: 25, // 25% scroll depth for engagement\n} as const;\n\nexport const SESSION_ANALYTICS = {\n INACTIVITY_TIMEOUT_MS: 30 * 60 * 1000, // 30min for analytics (vs 15min client)\n SHORT_SESSION_THRESHOLD_MS: 30 * 1000,\n MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1000,\n LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1000,\n MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1000, // Filter outliers\n} as const;\n\nexport const DEVICE_ANALYTICS = {\n MOBILE_MAX_WIDTH: 768,\n TABLET_MAX_WIDTH: 1024,\n MOBILE_PERFORMANCE_FACTOR: 1.5, // Mobile typically 1.5x slower\n TABLET_PERFORMANCE_FACTOR: 1.2,\n} as const;\n\nexport const CONTENT_ANALYTICS = {\n MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,\n MIN_CLICKS_FOR_HOT_ELEMENT: 10, // Popular element threshold\n MIN_SCROLL_COMPLETION_PERCENT: 80, // Page consumption threshold\n MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1000,\n} as const;\n\nexport const INSIGHT_THRESHOLDS = {\n SIGNIFICANT_CHANGE_PERCENT: 20,\n MAJOR_CHANGE_PERCENT: 50,\n MIN_EVENTS_FOR_INSIGHT: 100,\n MIN_SESSIONS_FOR_INSIGHT: 10,\n MIN_CORRELATION_STRENGTH: 0.7, // Strong correlation threshold\n LOW_ERROR_RATE_PERCENT: 1,\n HIGH_ERROR_RATE_PERCENT: 5,\n CRITICAL_ERROR_RATE_PERCENT: 10,\n} as const;\n\nexport const TEMPORAL_ANALYSIS = {\n SHORT_TERM_TREND_HOURS: 24,\n MEDIUM_TERM_TREND_DAYS: 7,\n LONG_TERM_TREND_DAYS: 30,\n MIN_DATA_POINTS_FOR_TREND: 5,\n WEEKLY_PATTERN_MIN_WEEKS: 4,\n DAILY_PATTERN_MIN_DAYS: 14,\n} as const;\n\nexport const SEGMENTATION_ANALYTICS = {\n MIN_SEGMENT_SIZE: 10,\n MIN_COHORT_SIZE: 5,\n COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],\n MIN_FUNNEL_EVENTS: 20,\n} as const;\n\nexport const ANALYTICS_QUERY_LIMITS = {\n DEFAULT_EVENTS_LIMIT: 5,\n DEFAULT_SESSIONS_LIMIT: 5,\n DEFAULT_PAGES_LIMIT: 5,\n MAX_EVENTS_FOR_DEEP_ANALYSIS: 10000,\n MAX_TIME_RANGE_DAYS: 365,\n ANALYTICS_BATCH_SIZE: 1000, // For historical analysis\n} as const;\n\nexport const ANOMALY_DETECTION = {\n ANOMALY_THRESHOLD_SIGMA: 2.5,\n STRONG_ANOMALY_THRESHOLD_SIGMA: 3.0,\n TRAFFIC_DROP_ALERT_PERCENT: -30,\n TRAFFIC_SPIKE_ALERT_PERCENT: 200,\n MIN_BASELINE_DAYS: 7,\n MIN_EVENTS_FOR_ANOMALY_DETECTION: 50,\n} as const;\n\nexport const SPECIAL_PAGE_URLS = {\n PAGE_URL_EXCLUDED: 'excluded',\n PAGE_URL_UNKNOWN: 'unknown',\n} as const;\n","import { init, event, on, off, isInitialized, destroy } from './api';\n\n// Constants\nexport * from './app.constants';\n\n// Types\nexport * from './types';\n\n// TraceLog namespace containing all API methods\nexport const tracelog = {\n init,\n event,\n on,\n off,\n isInitialized,\n destroy,\n};\n","var e,n,t,r,i,o=-1,a=function(e){addEventListener(\"pageshow\",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r=\"navigate\";o>=0?r=\"back-forward-cache\":t&&(document.prerendering||u()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":t.type&&(r=t.type.replace(/_/g,\"-\")));return{name:e,value:void 0===n?-1:n,rating:\"good\",delta:0,entries:[],id:\"v4-\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?\"poor\":e>n[0]?\"needs-improvement\":\"good\"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener(\"visibilitychange\",(function(){\"hidden\"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return\"hidden\"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){\"hidden\"===document.visibilityState&&m>-1&&(m=\"visibilitychange\"===e.type?e.timeStamp:0,T())},y=function(){addEventListener(\"visibilitychange\",g,!0),addEventListener(\"prerenderingchange\",g,!0)},T=function(){removeEventListener(\"visibilitychange\",g,!0),removeEventListener(\"prerenderingchange\",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener(\"prerenderingchange\",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"FCP\"),o=s(\"paint\",(function(e){e.forEach((function(e){\"first-contentful-paint\"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f(\"FCP\"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f(\"CLS\",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s(\"layout-shift\",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f(\"CLS\",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){\"interactionCount\"in performance||e||(e=s(\"event\",M,{type:\"event\",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||\"first-input\"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),\"hidden\"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){\"PerformanceEventTiming\"in self&&\"interactionId\"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f(\"INP\"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s(\"event\",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:\"first-input\",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f(\"INP\"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"LCP\"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s(\"largest-contentful-paint\",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));[\"keydown\",\"click\"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f(\"LCP\"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):\"complete\"!==document.readyState?addEventListener(\"load\",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f(\"TTFB\"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f(\"TTFB\",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:\"first-input\",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;\"pointerdown\"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener(\"pointerup\",t,U),removeEventListener(\"pointercancel\",r,U)};addEventListener(\"pointerup\",t,U),addEventListener(\"pointercancel\",r,U)}(n,e):W(n,e)}},Z=function(e){[\"mousedown\",\"keydown\",\"touchstart\",\"pointerdown\"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f(\"FID\"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s(\"first-input\",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f(\"FID\"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};\n"],"names":["HTML_DATA_ATTR_PREFIX","INTERACTIVE_SELECTORS","UTM_PARAMS","VALIDATION_MESSAGES","XSS_PATTERNS","SpecialApiUrl","DeviceType","EmitterEvent","EventType","ScrollDirection","ErrorType","Mode","TraceLogValidationError","message","errorCode","layer","AppConfigValidationError","SessionTimeoutValidationError","SamplingRateValidationError","IntegrationValidationError","InitializationTimeoutError","timeoutMs","formatLogMsg","msg","error","sanitizedMessage","log","type","extra","data","showToClient","formattedMsg","method","sanitizedData","sanitizeLogData","sanitized","sensitiveKeys","key","value","lowerKey","sensitiveKey","coarsePointerQuery","noHoverQuery","initMediaQueries","getDeviceType","nav","width","hasCoarsePointer","hasNoHover","hasTouchSupport","ua","isMobileUA","isTabletUA","STORAGE_BASE_KEY","QA_MODE_KEY","USER_ID_KEY","QUEUE_KEY","id","SESSION_STORAGE_KEY","BROADCAST_CHANNEL_NAME","WEB_VITALS_THRESHOLDS","LONG_TASK_THROTTLE_MS","PII_PATTERNS","MAX_ERROR_MESSAGE_LENGTH","ERROR_SUPPRESSION_WINDOW_MS","MAX_TRACKED_ERRORS","MAX_TRACKED_ERRORS_HARD_LIMIT","QA_MODE_PARAM","QA_MODE_VALUE","detectQaMode","params","isQaMode","newSearch","newUrl","getUTMParameters","urlParams","utmParams","param","generateUUID","c","r","generateEventId","timestamp","random","bytes","b","isValidUrl","url","allowHttp","parsed","isHttps","isHttp","getCollectApiUrl","config","parts","projectId","cleanDomain","collectApiUrl","normalizeUrl","sensitiveQueryParams","urlObject","searchParams","hasChanged","removedParams","sanitizeString","xssPatternMatches","pattern","beforeReplace","sanitizeValue","depth","item","sanitizedObject","limitedEntries","value_","sanitizedKey","sanitizedValue","sanitizeMetadata","metadata","errorMessage","validateAppConfig","validateScrollContainerSelectors","validateIntegrations","isValidCssSelectorSyntax","selector","parenthesesCount","char","bracketsCount","selectors","selectorsArray","integrations","validateAndNormalizeConfig","normalizedConfig","isValidArrayItem","entries","isOnlyPrimitiveFields","object","isValidEventName","eventName","validateSingleMetadata","sanitizedMetadata","intro","jsonString","isValidMetadata","sanitizedArray","itemValidation","isEventValid","nameValidation","metadataValidation","Emitter","event","callback","callbacks","index","globalState","StateManager","SenderManager","storeManager","userId","body","success","persistedData","payload","controller","timeoutId","response","blob","enrichedBody","storageKey","persistedDataString","originalCallbacks","retryDelay","delay","resolve","EventManager","googleAnalytics","emitter","_eventCount","recoveredEvents","eventIds","e","page_url","from_page_url","scroll_data","click_data","custom_event","web_vitals","error_data","session_end_reason","isCriticalEvent","eventType","isSessionStart","currentPageUrl","currentSessionId","bufferedEvents","isSync","eventsToSend","eventMap","order","signature","events","a","now","fingerprint","x","y","nonCriticalIndex","removedEvent","samplingRate","eventIdSet","eventData","queue","UserManager","storageManager","storedUserId","newUserId","SessionManager","eventManager","action","sessionId","messageProjectId","reason","storedSession","sessionTimeout","lastActivity","storedData","session","recoveredSessionId","isRecovered","finalize","SessionHandler","PageViewHandler","onTrack","original","args","rawUrl","normalizedUrl","fromUrl","pageViewData","pathname","search","hash","referrer","title","ClickHandler","mouseEvent","target","clickedElement","trackingElement","relevantClickElement","coordinates","trackingData","attributeData","clickData","element","parent","rect","relativeX","relativeY","name","relevantElement","text","attributes","clickedText","relevantText","commonAttributes","result","attributeName","ScrollHandler","raw","container","attempt","elements","sel","handleScroll","scrollData","initialScrollTop","currentCount","newDepth","current","previous","scrollTop","scrollHeight","viewportHeight","maxScrollTop","lastScrollPos","direction","style","hasScrollableOverflow","hasOverflowContent","GoogleAnalyticsIntegration","measurementId","normalizedMetadata","script","reject","gaScriptConfig","StorageManager","retryError","keysToRemove","i","tracelogKeys","persistedEventsKeys","criticalPrefixes","nonCriticalKeys","prefix","storage","testKey","PerformanceHandler","obs","list","last","clsValue","currentNavId","navId","entry","worst","dur","onLCP","onCLS","onFCP","onTTFB","onINP","webVitals","report","metric","ttfb","duration","sample","reportedForNav","supported","cb","options","once","observer","callbackError","threshold","ErrorHandler","regex","lastSeenAt","excess","App","valid","force","handlerCleanups","handler","device","pageUrl","mode","onPageView","pendingListeners","app","isInitializing","isDestroying","init","validatedConfig","instance","initPromise","timeoutPromise","_","cleanupError","on","off","l","isInitialized","destroy","PERFORMANCE_CONFIG","DATA_PROTECTION","ENGAGEMENT_THRESHOLDS","SESSION_ANALYTICS","DEVICE_ANALYTICS","CONTENT_ANALYTICS","INSIGHT_THRESHOLDS","TEMPORAL_ANALYSIS","SEGMENTATION_ANALYTICS","ANALYTICS_QUERY_LIMITS","ANOMALY_DETECTION","SPECIAL_PAGE_URLS","tracelog","o","n","u","f","s","d","p","v","m","h","g","T","E","C","S","L","w","t","A","I","M","k","F","D","R","B","H","q","O","N","j","z","G","J","K","Q"],"mappings":"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","x_google_ignoreList":[39]}
|
|
1
|
+
{"version":3,"file":"tracelog.esm.js","sources":["../../src/constants/config.constants.ts","../../src/types/config.types.ts","../../src/types/device.types.ts","../../src/types/emitter.types.ts","../../src/types/event.types.ts","../../src/types/mode.types.ts","../../src/types/validation-error.types.ts","../../src/utils/logging.utils.ts","../../src/utils/browser/device-detector.utils.ts","../../src/constants/storage.constants.ts","../../src/constants/performance.constants.ts","../../src/constants/error.constants.ts","../../src/utils/browser/qa-mode.utils.ts","../../src/utils/browser/utm-params.utils.ts","../../src/utils/data/uuid.utils.ts","../../src/utils/network/url.utils.ts","../../src/utils/security/sanitize.utils.ts","../../src/utils/validations/config-validations.utils.ts","../../src/utils/validations/type-guards.utils.ts","../../src/utils/validations/metadata-validations.utils.ts","../../src/utils/validations/event-validations.utils.ts","../../src/utils/emitter.utils.ts","../../src/managers/state.manager.ts","../../src/managers/sender.manager.ts","../../src/managers/event.manager.ts","../../src/managers/user.manager.ts","../../src/managers/session.manager.ts","../../src/handlers/session.handler.ts","../../src/handlers/page-view.handler.ts","../../src/handlers/click.handler.ts","../../src/handlers/scroll.handler.ts","../../src/integrations/google-analytics.integration.ts","../../src/managers/storage.manager.ts","../../src/handlers/performance.handler.ts","../../src/handlers/error.handler.ts","../../src/app.ts","../../src/api.ts","../../src/app.constants.ts","../../src/public-api.ts","../../node_modules/web-vitals/dist/web-vitals.js"],"sourcesContent":["/**\n * Consolidated configuration constants for TraceLog\n * This file centralizes all timing, limits, browser, and initialization constants\n */\n\n// ============================================================================\n// SESSION & TIMING\n// ============================================================================\n\nexport const DEFAULT_SESSION_TIMEOUT = 15 * 60 * 1000; // 15 minutes\nexport const DUPLICATE_EVENT_THRESHOLD_MS = 500; // 500ms\nexport const EVENT_SENT_INTERVAL_MS = 10000; // 10 seconds\n\n// Throttling and debouncing\nexport const SCROLL_DEBOUNCE_TIME_MS = 250;\nexport const DEFAULT_VISIBILITY_TIMEOUT_MS = 2000;\n\n// Event expiry\nexport const EVENT_EXPIRY_HOURS = 24;\nexport const EVENT_PERSISTENCE_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// ============================================================================\n// LIMITS & RETRIES\n// ============================================================================\n\nexport const MAX_EVENTS_QUEUE_LENGTH = 100;\nexport const MAX_RETRIES = 3;\nexport const RETRY_DELAY_MS = 5000;\nexport const REQUEST_TIMEOUT_MS = 10000;\nexport const MAX_METADATA_SIZE = 5000;\n\n// Motion and interaction thresholds\nexport const DEFAULT_MOTION_THRESHOLD = 2;\nexport const SIGNIFICANT_SCROLL_DELTA = 10;\nexport const MIN_SCROLL_DEPTH_CHANGE = 5;\nexport const SCROLL_MIN_EVENT_INTERVAL_MS = 500;\nexport const MAX_SCROLL_EVENTS_PER_SESSION = 120;\n\n// Sampling and rate limits\nexport const DEFAULT_SAMPLING_RATE = 1;\nexport const MIN_SAMPLING_RATE = 0;\nexport const MAX_SAMPLING_RATE = 1;\nexport const RATE_LIMIT_WINDOW_MS = 1000; // 1 second window\nexport const MAX_EVENTS_PER_SECOND = 200; // Maximum 200 events per second\n\n// Queue and batch limits\nexport const BATCH_SIZE_THRESHOLD = 50;\nexport const MAX_PENDING_EVENTS_BUFFER = 100; // Maximum events to buffer before session init\n\n// Session timeout validation limits\nexport const MIN_SESSION_TIMEOUT_MS = 30000; // 30 seconds minimum\nexport const MAX_SESSION_TIMEOUT_MS = 86400000; // 24 hours maximum\n\n// Custom event validation limits\nexport const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;\nexport const MAX_CUSTOM_EVENT_STRING_SIZE = 8 * 1024; // 8KB\nexport const MAX_CUSTOM_EVENT_KEYS = 10;\nexport const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;\nexport const MAX_NESTED_OBJECT_KEYS = 20; // Maximum keys in nested objects within arrays\n\n// Text content limits\nexport const MAX_TEXT_LENGTH = 255; // For click tracking text content\n\n// Data sanitization limits\nexport const MAX_STRING_LENGTH = 1000;\nexport const MAX_ARRAY_LENGTH = 100;\nexport const MAX_OBJECT_DEPTH = 3;\n\n// Precision for numeric metrics\nexport const PRECISION_TWO_DECIMALS = 2 as const;\n\n// Sync XHR timeout\nexport const SYNC_XHR_TIMEOUT_MS = 2000; // 2 seconds\n\n// Event fingerprint management\nexport const MAX_FINGERPRINTS = 1000; // Maximum fingerprints stored before cleanup\nexport const FINGERPRINT_CLEANUP_MULTIPLIER = 10; // Cleanup fingerprints older than 10x threshold\nexport const MAX_FINGERPRINTS_HARD_LIMIT = 2000; // Hard limit for aggressive cleanup\n\n// ============================================================================\n// BROWSER & HTML\n// ============================================================================\n\nexport const HTML_DATA_ATTR_PREFIX = 'data-tlog';\n\n// Interactive element selectors for click tracking\nexport const INTERACTIVE_SELECTORS = [\n 'button',\n 'a',\n 'input[type=\"button\"]',\n 'input[type=\"submit\"]',\n 'input[type=\"reset\"]',\n 'input[type=\"checkbox\"]',\n 'input[type=\"radio\"]',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[routerLink]',\n '[ng-click]',\n '[data-action]',\n '[data-click]',\n '[data-navigate]',\n '[data-toggle]',\n '[onclick]',\n '.btn',\n '.button',\n '.clickable',\n '.nav-link',\n '.menu-item',\n '[data-testid]',\n '[tabindex=\"0\"]',\n] as const;\n\n// UTM parameters for tracking\nexport const UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];\n\n// ============================================================================\n// ============================================================================\n// INITIALIZATION\n// ============================================================================\n\nexport const INITIALIZATION_MAX_CONCURRENT_RETRIES = 20;\nexport const INITIALIZATION_CONCURRENT_RETRY_DELAY_MS = 50;\nexport const INITIALIZATION_TIMEOUT_MS = 10000;\n\n// ============================================================================\n// SESSION MANAGEMENT\n// ============================================================================\n\nexport const SESSION_SYNC_TIMEOUT_MS = 2000;\nexport const SESSION_MAX_RETRY_ATTEMPTS = 3;\nexport const SESSION_CLEANUP_DELAY_MS = 100;\n\n// Cross-tab coordination\nexport const CROSS_TAB_INITIALIZATION_LOCK_TIMEOUT_MS = 5000;\nexport const TAB_HEARTBEAT_INTERVAL_MS = 5000; // 5 seconds\nexport const TAB_ELECTION_TIMEOUT_MS = 2000; // 2 seconds\nexport const TAB_CLEANUP_DELAY_MS = 1000; // 1 second\n\n// Session recovery\nexport const SESSION_RECOVERY_WINDOW_MULTIPLIER = 2; // 2x session timeout\nexport const MAX_SESSION_RECOVERY_ATTEMPTS = 3;\nexport const MAX_SESSION_RECOVERY_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours max\nexport const MIN_SESSION_RECOVERY_WINDOW_MS = 2 * 60 * 1000; // 2 minutes minimum\n\n// ============================================================================\n// SCROLL SUPPRESSION\n// ============================================================================\n\nexport const SCROLL_SUPPRESS_MULTIPLIER = 2;\n\n// ============================================================================\n// NETWORK TIMING\n// ============================================================================\n\nexport const RETRY_BACKOFF_INITIAL = 1000; // 1 second\nexport const RETRY_BACKOFF_MAX = 30_000; // 30 seconds\nexport const RATE_LIMIT_INTERVAL = 1000; // 1 second\nexport const MAX_RETRY_ATTEMPTS = 10;\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n// Validation error messages - standardized across all layers\nexport const VALIDATION_MESSAGES = {\n MISSING_PROJECT_ID: 'Project ID is required',\n PROJECT_ID_EMPTY_AFTER_TRIM: 'Project ID is required',\n INVALID_SESSION_TIMEOUT: `Session timeout must be between ${MIN_SESSION_TIMEOUT_MS}ms (30 seconds) and ${MAX_SESSION_TIMEOUT_MS}ms (24 hours)`,\n INVALID_SAMPLING_RATE: 'Sampling rate must be between 0 and 1',\n INVALID_ERROR_SAMPLING_RATE: 'Error sampling must be between 0 and 1',\n INVALID_TRACELOG_PROJECT_ID: 'TraceLog project ID is required when integration is enabled',\n INVALID_CUSTOM_API_URL: 'Custom API URL is required when integration is enabled',\n INVALID_GOOGLE_ANALYTICS_ID: 'Google Analytics measurement ID is required when integration is enabled',\n INVALID_SCROLL_CONTAINER_SELECTORS: 'Scroll container selectors must be valid CSS selectors',\n INVALID_GLOBAL_METADATA: 'Global metadata must be an object',\n INVALID_SENSITIVE_QUERY_PARAMS: 'Sensitive query params must be an array of strings',\n} as const;\n\n// ============================================================================\n// SECURITY\n// ============================================================================\n\n// XSS protection patterns\nexport const XSS_PATTERNS = [\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n /javascript:/gi,\n /on\\w+\\s*=/gi,\n /<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi,\n /<embed\\b[^>]*>/gi,\n /<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi,\n] as const;\n","import { MetadataType } from './common.types';\n\nexport interface Config {\n /** Session inactivity timeout in milliseconds. @default 900000 */\n sessionTimeout?: number;\n /** Metadata appended to every tracked event. */\n globalMetadata?: Record<string, MetadataType>;\n /** Selectors defining custom scroll containers to monitor. */\n scrollContainerSelectors?: string | string[];\n /** Query parameters to remove before tracking URLs. */\n sensitiveQueryParams?: string[];\n /** Error event sampling rate between 0 and 1. */\n errorSampling?: number;\n /** Event sampling rate between 0 and 1. */\n samplingRate?: number;\n /** Optional configuration for third-party integrations. */\n integrations?: {\n /** TraceLog integration options. */\n tracelog?: {\n /** Required project ID TraceLog SaaS integration. */\n projectId: string;\n };\n /** Custom integration options. */\n custom?: {\n /** Endpoint for collecting events. */\n collectApiUrl: string;\n /** Allow HTTP URLs (not recommended for production). @default false */\n allowHttp?: boolean;\n };\n /** Google Analytics integration options. */\n googleAnalytics?: {\n /** Required measurement ID for Google Analytics. */\n measurementId: string;\n };\n };\n}\n\nexport enum SpecialApiUrl {\n Localhost = 'localhost:8080',\n Fail = 'localhost:9999',\n}\n","export enum DeviceType {\n Mobile = 'mobile',\n Tablet = 'tablet',\n Desktop = 'desktop',\n Unknown = 'unknown',\n}\n","import { EventData } from './event.types';\nimport { BaseEventsQueueDto } from './queue.types';\n\nexport type EmitterCallback<T = any> = (data: T) => void;\n\nexport enum EmitterEvent {\n EVENT = 'event',\n QUEUE = 'queue',\n}\n\nexport interface EmitterMap {\n [EmitterEvent.EVENT]: EventData;\n [EmitterEvent.QUEUE]: BaseEventsQueueDto;\n}\n","import { MetadataType } from './common.types';\nimport { SessionEndReason } from './session.types';\n\nexport type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB' | 'LONG_TASK';\n\nexport enum EventType {\n PAGE_VIEW = 'page_view',\n CLICK = 'click',\n SCROLL = 'scroll',\n SESSION_START = 'session_start',\n SESSION_END = 'session_end',\n CUSTOM = 'custom',\n WEB_VITALS = 'web_vitals',\n ERROR = 'error',\n}\n\nexport enum ScrollDirection {\n UP = 'up',\n DOWN = 'down',\n}\n\nexport enum ErrorType {\n JS_ERROR = 'js_error',\n PROMISE_REJECTION = 'promise_rejection',\n}\n\nexport interface ScrollData {\n depth: number;\n direction: ScrollDirection;\n}\n\nexport interface ClickData {\n x: number;\n y: number;\n relativeX: number;\n relativeY: number;\n id?: string;\n class?: string;\n tag?: string;\n text?: string;\n href?: string;\n title?: string;\n alt?: string;\n role?: string;\n ariaLabel?: string;\n dataAttributes?: Record<string, string>;\n}\n\nexport type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;\n\nexport interface ClickTrackingElementData {\n element: HTMLElement;\n name: string;\n value?: string;\n}\n\nexport interface CustomEventData {\n name: string;\n metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n}\n\nexport interface WebVitalsData {\n type: WebVitalType;\n value: number;\n}\n\nexport interface ErrorData {\n type: ErrorType;\n message: string;\n filename?: string;\n line?: number;\n column?: number;\n}\n\nexport interface UTM {\n source?: string;\n medium?: string;\n campaign?: string;\n term?: string;\n content?: string;\n}\n\nexport interface PageViewData {\n referrer?: string;\n title?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}\n\nexport interface EventData {\n id: string;\n type: EventType;\n page_url: string;\n timestamp: number;\n referrer?: string;\n from_page_url?: string;\n scroll_data?: ScrollData;\n click_data?: ClickData;\n custom_event?: CustomEventData;\n web_vitals?: WebVitalsData;\n page_view?: PageViewData;\n session_end_reason?: SessionEndReason;\n error_data?: ErrorData;\n utm?: UTM;\n}\n","/**\n * App modes for the TraceLog Library\n */\nexport enum Mode {\n QA = 'qa',\n}\n","/**\n * Custom error classes for TraceLog validation errors\n * Provides better error handling and consistency across validation layers\n */\n\n/**\n * Base class for all TraceLog validation errors\n */\nexport abstract class TraceLogValidationError extends Error {\n constructor(\n message: string,\n public readonly errorCode: string,\n public readonly layer: 'config' | 'app' | 'runtime',\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when app configuration validation fails\n */\nexport class AppConfigValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'APP_CONFIG_INVALID', layer);\n }\n}\n\n/**\n * Thrown when session timeout validation fails\n */\nexport class SessionTimeoutValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SESSION_TIMEOUT_INVALID', layer);\n }\n}\n\n/**\n * Thrown when sampling rate validation fails\n */\nexport class SamplingRateValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SAMPLING_RATE_INVALID', layer);\n }\n}\n\n/**\n * Thrown when integrations validation fails\n */\nexport class IntegrationValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'INTEGRATION_INVALID', layer);\n }\n}\n\n/**\n * Thrown when initialization exceeds the maximum allowed timeout\n */\nexport class InitializationTimeoutError extends TraceLogValidationError {\n constructor(\n message: string,\n public readonly timeoutMs: number,\n layer: 'config' | 'app' | 'runtime' = 'runtime',\n ) {\n super(message, 'INITIALIZATION_TIMEOUT', layer);\n }\n}\n","export const formatLogMsg = (msg: string, error?: unknown): string => {\n if (error) {\n // In production, sanitize error messages to avoid exposing sensitive paths\n if (process.env.NODE_ENV !== 'dev' && error instanceof Error) {\n // Remove file paths and line numbers from error messages\n const sanitizedMessage = error.message.replace(/\\s+at\\s+.*$/gm, '').replace(/\\(.*?:\\d+:\\d+\\)/g, '');\n return `[TraceLog] ${msg}: ${sanitizedMessage}`;\n }\n return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : 'Unknown error'}`;\n }\n\n return `[TraceLog] ${msg}`;\n};\n\n/**\n * Safe logging utility that respects production environment\n *\n * @param type - Log level (info, warn, error, debug)\n * @param msg - Message to log\n * @param extra - Optional extra data\n *\n * Production behavior:\n * - debug: Never logged in production\n * - info: Only logged if showToClient=true\n * - warn: Always logged (important for debugging production issues)\n * - error: Always logged\n * - Stack traces are sanitized\n * - Data objects are sanitized\n */\nexport const log = (\n type: 'info' | 'warn' | 'error' | 'debug',\n msg: string,\n extra?: { error?: unknown; data?: Record<string, unknown>; showToClient?: boolean },\n): void => {\n const { error, data, showToClient = false } = extra ?? {};\n const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;\n const method = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';\n\n // Production logging strategy:\n // - Development: Log everything\n // - Production:\n // - debug: never logged\n // - info: only if showToClient=true\n // - warn: always logged (critical for debugging)\n // - error: always logged\n const isProduction = process.env.NODE_ENV !== 'dev';\n\n if (isProduction) {\n // Never log debug in production\n if (type === 'debug') {\n return;\n }\n\n // Log info only if explicitly flagged\n if (type === 'info' && !showToClient) {\n return;\n }\n\n // warn and error always logged in production\n }\n\n // In production, sanitize data to avoid exposing sensitive information\n if (isProduction && data !== undefined) {\n const sanitizedData = sanitizeLogData(data);\n console[method](formattedMsg, sanitizedData);\n } else if (data !== undefined) {\n console[method](formattedMsg, data);\n } else {\n console[method](formattedMsg);\n }\n};\n\n/**\n * Sanitizes log data in production to prevent sensitive information leakage\n * Simple approach: redact sensitive keys only\n */\nconst sanitizeLogData = (data: Record<string, unknown>): Record<string, unknown> => {\n const sanitized: Record<string, unknown> = {};\n const sensitiveKeys = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'sessionid', 'session_id'];\n\n for (const [key, value] of Object.entries(data)) {\n const lowerKey = key.toLowerCase();\n\n // Redact sensitive keys\n if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {\n sanitized[key] = '[REDACTED]';\n } else {\n sanitized[key] = value;\n }\n }\n\n return sanitized;\n};\n","import { DeviceType } from '../../types/device.types';\nimport { log } from '../logging.utils';\n\nlet coarsePointerQuery: MediaQueryList | undefined;\nlet noHoverQuery: MediaQueryList | undefined;\n\nconst initMediaQueries = (): void => {\n if (typeof window !== 'undefined' && !coarsePointerQuery) {\n coarsePointerQuery = window.matchMedia('(pointer: coarse)');\n noHoverQuery = window.matchMedia('(hover: none)');\n }\n};\n\ninterface NavigatorWithUserAgentData extends Navigator {\n userAgentData?: {\n mobile: boolean;\n platform?: string;\n };\n}\n\n/**\n * Detects the device type based on screen size, user agent, and browser capabilities\n * @returns The detected device type\n */\nexport const getDeviceType = (): DeviceType => {\n try {\n const nav = navigator as NavigatorWithUserAgentData;\n\n if (nav.userAgentData && typeof nav.userAgentData.mobile === 'boolean') {\n if (nav.userAgentData.platform && /ipad|tablet/i.test(nav.userAgentData.platform)) {\n return DeviceType.Tablet;\n }\n\n const result = nav.userAgentData.mobile ? DeviceType.Mobile : DeviceType.Desktop;\n return result;\n }\n\n initMediaQueries();\n\n const width = window.innerWidth;\n const hasCoarsePointer = coarsePointerQuery?.matches ?? false;\n const hasNoHover = noHoverQuery?.matches ?? false;\n const hasTouchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const ua = navigator.userAgent.toLowerCase();\n const isMobileUA = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(ua);\n const isTabletUA = /tablet|ipad|android(?!.*mobile)/.test(ua);\n\n if (width <= 767 || (isMobileUA && hasTouchSupport)) {\n return DeviceType.Mobile;\n }\n\n if ((width >= 768 && width <= 1024) || isTabletUA || (hasCoarsePointer && hasNoHover && hasTouchSupport)) {\n return DeviceType.Tablet;\n }\n\n return DeviceType.Desktop;\n } catch (error) {\n log('warn', 'Device detection failed, defaulting to desktop', { error });\n\n return DeviceType.Desktop;\n }\n};\n","export const STORAGE_BASE_KEY = 'tlog';\nexport const QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;\nexport const USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;\n\nexport const QUEUE_KEY = (id: string): string => (id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`);\nexport const SESSION_STORAGE_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;\n\n// Cross-tab session management storage keys\nexport const CROSS_TAB_SESSION_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:cross_tab_session` : `${STORAGE_BASE_KEY}:cross_tab_session`;\nexport const TAB_INFO_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:tab_info` : `${STORAGE_BASE_KEY}:tab_info`;\n\nexport const TAB_SPECIFIC_INFO_KEY = (projectId: string, tabId: string): string =>\n `${STORAGE_BASE_KEY}:${projectId}:tab:${tabId}:info`;\nexport const SESSION_RECOVERY_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:recovery` : `${STORAGE_BASE_KEY}:recovery`;\n\n// BroadcastChannel name for cross-tab communication\nexport const BROADCAST_CHANNEL_NAME = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;\n","/**\n * Performance monitoring and web vitals constants for TraceLog\n * Centralizes thresholds and configuration for performance tracking\n */\n\nimport { WebVitalType } from '../types';\n\n// ============================================================================\n// WEB VITALS THRESHOLDS\n// ============================================================================\n\n/**\n * Web Vitals thresholds in milliseconds (except CLS which is unitless)\n * These define the minimum values required to report a web vital metric\n *\n * Based on Core Web Vitals standards:\n * - LCP (Largest Contentful Paint): 4000ms threshold (poor threshold)\n * - FCP (First Contentful Paint): 1800ms threshold (good threshold)\n * - CLS (Cumulative Layout Shift): 0.25 threshold (unitless, needs improvement threshold)\n * - INP (Interaction to Next Paint): 200ms threshold (good threshold)\n * - TTFB (Time to First Byte): 800ms threshold (good/needs improvement boundary, aligned with Web Vitals standard)\n * - LONG_TASK: 50ms threshold for long task detection\n */\nexport const WEB_VITALS_THRESHOLDS: Record<WebVitalType, number> = {\n LCP: 4000,\n FCP: 1800,\n CLS: 0.25,\n INP: 200,\n TTFB: 800,\n LONG_TASK: 50,\n} as const;\n\n// ============================================================================\n// PERFORMANCE MONITORING LIMITS\n// ============================================================================\n\n/**\n * Long task throttling interval in milliseconds\n * Prevents excessive long task events from being sent\n */\nexport const LONG_TASK_THROTTLE_MS = 1000;\n\n/**\n * Precision for performance metric values\n * All performance metrics are rounded to 2 decimal places\n */\nexport const PERFORMANCE_PRECISION_DECIMALS = 2 as const;\n","/**\n * Error handling and PII sanitization constants for TraceLog\n * Centralizes patterns and limits for error tracking and data protection\n */\n\n// ============================================================================\n// PII SANITIZATION PATTERNS\n// ============================================================================\n\n/**\n * Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)\n * These patterns are used to replace sensitive information with [REDACTED] in error messages\n */\nexport const PII_PATTERNS = [\n // Email addresses\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/gi,\n\n // US Phone numbers (various formats)\n /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n\n // Credit card numbers (16 digits with optional separators)\n /\\b\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/g,\n\n // IBAN (International Bank Account Number)\n /\\b[A-Z]{2}\\d{2}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/gi,\n\n // API keys/tokens (sk_test_, sk_live_, pk_test_, pk_live_, etc.)\n /\\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\\b/gi,\n\n // Bearer tokens (JWT-like patterns - matches complete and partial tokens)\n /Bearer\\s+[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)?(?:\\.[A-Za-z0-9_-]+)?/gi,\n\n // Passwords in connection strings (protocol://user:password@host)\n /:\\/\\/[^:/]+:([^@]+)@/gi,\n] as const;\n\n// ============================================================================\n// ERROR TRACKING LIMITS\n// ============================================================================\n\n/**\n * Maximum length for error messages before truncation\n * Prevents extremely long error messages from consuming excessive storage\n */\nexport const MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Time window for error suppression in milliseconds\n * Prevents duplicate errors from flooding the system within this timeframe\n */\nexport const ERROR_SUPPRESSION_WINDOW_MS = 5_000; // 5 seconds\n\n/**\n * Maximum number of unique errors to track for suppression\n * Prevents memory usage from growing indefinitely\n */\nexport const MAX_TRACKED_ERRORS = 50;\n\n/**\n * Hard limit for error tracking before aggressive cleanup\n * If this limit is exceeded, the entire error map is cleared\n */\nexport const MAX_TRACKED_ERRORS_HARD_LIMIT = MAX_TRACKED_ERRORS * 2;\n\n// ============================================================================\n// ERROR SAMPLING\n// ============================================================================\n\n/**\n * Default error sampling rate\n * Controls what percentage of errors are actually reported\n */\nexport const DEFAULT_ERROR_SAMPLING_RATE = 0.1; // 10% of errors\n","import { QA_MODE_KEY } from '../../constants';\nimport { log } from '../logging.utils';\n\nconst QA_MODE_PARAM = 'tlog_mode';\nconst QA_MODE_VALUE = 'qa';\n\n/**\n * Detects if QA mode should be active based on URL query parameter or sessionStorage\n *\n * Detection flow:\n * 1. Check if already active in sessionStorage\n * 2. Check for ?tlog_mode=qa query parameter\n * 3. If found in URL:\n * - Persist to sessionStorage\n * - Clean param from URL\n *\n * @returns True if QA mode is active, false otherwise\n */\nexport const detectQaMode = (): boolean => {\n const stored = sessionStorage.getItem(QA_MODE_KEY);\n\n if (stored === 'true') {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const modeParam = params.get(QA_MODE_PARAM);\n const isQaMode = modeParam === QA_MODE_VALUE;\n\n if (isQaMode) {\n sessionStorage.setItem(QA_MODE_KEY, 'true');\n\n params.delete(QA_MODE_PARAM);\n\n const newSearch = params.toString();\n const newUrl = `${window.location.pathname}${newSearch ? '?' + newSearch : ''}${window.location.hash}`;\n\n try {\n window.history.replaceState({}, '', newUrl);\n } catch (error) {\n log('warn', 'History API not available, cannot replace URL', { error });\n }\n\n console.log(\n '%c[TraceLog] QA Mode ACTIVE',\n 'background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;',\n );\n }\n\n return isQaMode;\n};\n","import { UTM_PARAMS } from '../../constants';\nimport { UTM } from '../../types/event.types';\n\n/**\n * Extracts UTM parameters from the current URL\n * @returns UTM parameters object or undefined if none found\n */\nexport const getUTMParameters = (): UTM | undefined => {\n const urlParams = new URLSearchParams(window.location.search);\n const utmParams: Partial<Record<keyof UTM, string>> = {};\n\n UTM_PARAMS.forEach((param) => {\n const value = urlParams.get(param);\n\n if (value) {\n const key = param.split('utm_')[1] as keyof UTM;\n utmParams[key] = value;\n }\n });\n\n const result = Object.keys(utmParams).length ? utmParams : undefined;\n\n return result;\n};\n","/**\n * Generates a RFC4122 compliant UUID v4 using native crypto API with fallback\n * @returns A UUID string\n */\nexport const generateUUID = (): string => {\n // Use native crypto.randomUUID() if available (modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * Generates a unique event ID optimized for high-frequency event tracking\n *\n * Uses a simple hybrid approach:\n * - Timestamp for temporal ordering\n * - Random component for uniqueness across tabs/processes\n *\n * Format: {timestamp}-{random}\n * Example: \"1704067200000-a3f9c2b1\"\n *\n * @returns Unique event ID string\n */\nexport const generateEventId = (): string => {\n const timestamp = Date.now();\n\n // Generate 8 random hex chars (32 bits entropy)\n let random = '';\n try {\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const bytes = crypto.getRandomValues(new Uint8Array(4));\n if (bytes) {\n random = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n }\n } catch {\n // crypto failed, use fallback\n }\n\n // Fallback to Math.random if crypto unavailable\n if (!random) {\n random = Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, '0');\n }\n\n return `${timestamp}-${random}`;\n};\n","import { Config } from '../../types';\nimport { log } from '../logging.utils';\n\n/**\n * Validates if a URL is valid and optionally allows HTTP URLs\n * @param url - The URL to validate\n * @param allowHttp - Whether to allow HTTP URLs (default: false)\n * @returns True if the URL is valid, false otherwise\n */\nconst isValidUrl = (url: string, allowHttp = false): boolean => {\n try {\n const parsed = new URL(url);\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n return isHttps || (allowHttp && isHttp);\n } catch {\n return false;\n }\n};\n\n/**\n * Generates an API URL based on project ID and current domain\n * @param id - The project ID\n * @returns The generated API URL\n */\nexport const getCollectApiUrl = (config: Config): string => {\n if (config.integrations?.tracelog?.projectId) {\n const url = new URL(window.location.href);\n const host = url.hostname;\n const parts = host.split('.');\n\n if (parts.length === 0) {\n throw new Error('Invalid URL');\n }\n\n const projectId = config.integrations.tracelog.projectId;\n const cleanDomain = parts.slice(-2).join('.');\n const collectApiUrl = `https://${projectId}.${cleanDomain}/collect`;\n const isValid = isValidUrl(collectApiUrl);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n const collectApiUrl = config.integrations?.custom?.collectApiUrl;\n\n if (collectApiUrl) {\n const allowHttp = config.integrations?.custom?.allowHttp ?? false;\n const isValid = isValidUrl(collectApiUrl, allowHttp);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n return '';\n};\n\n/**\n * Normalizes a URL by removing sensitive query parameters\n * @param url - The URL to normalize\n * @param sensitiveQueryParams - Array of parameter names to remove\n * @returns The normalized URL\n */\nexport const normalizeUrl = (url: string, sensitiveQueryParams: string[] = []): string => {\n try {\n const urlObject = new URL(url);\n const searchParams = urlObject.searchParams;\n\n let hasChanged = false;\n const removedParams: string[] = [];\n\n sensitiveQueryParams.forEach((param) => {\n if (searchParams.has(param)) {\n searchParams.delete(param);\n hasChanged = true;\n removedParams.push(param);\n }\n });\n\n if (!hasChanged && url.includes('?')) {\n return url;\n }\n\n urlObject.search = searchParams.toString();\n const result = urlObject.toString();\n\n return result;\n } catch (error) {\n log('warn', 'URL normalization failed, returning original', { error, data: { url: url.slice(0, 100) } });\n\n return url;\n }\n};\n","import { MAX_ARRAY_LENGTH, MAX_OBJECT_DEPTH, MAX_STRING_LENGTH, XSS_PATTERNS } from '../../constants';\nimport { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\n\n/**\n * Sanitizes a string value to prevent XSS attacks\n * @param value - The string to sanitize\n * @returns The sanitized string\n */\nexport const sanitizeString = (value: string): string => {\n if (!value || typeof value !== 'string' || value.trim().length === 0) {\n return '';\n }\n\n let sanitized = value;\n\n // Limit string length\n if (value.length > MAX_STRING_LENGTH) {\n sanitized = value.slice(0, Math.max(0, MAX_STRING_LENGTH));\n // Silent truncation - this is expected behavior for long strings\n }\n\n // Remove potential XSS patterns\n let xssPatternMatches = 0;\n for (const pattern of XSS_PATTERNS) {\n const beforeReplace = sanitized;\n sanitized = sanitized.replace(pattern, '');\n if (beforeReplace !== sanitized) {\n xssPatternMatches++;\n }\n }\n\n if (xssPatternMatches > 0) {\n log('warn', 'XSS patterns detected and removed', {\n data: {\n patternMatches: xssPatternMatches,\n originalValue: value.slice(0, 100),\n },\n });\n }\n\n // Basic HTML entity encoding for critical characters\n sanitized = sanitized\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''')\n .replaceAll('/', '/');\n\n const result = sanitized.trim();\n\n return result;\n};\n\n/**\n * Sanitizes any value recursively with depth protection\n * @param value - The value to sanitize\n * @param depth - Current recursion depth\n * @returns The sanitized value\n */\nconst sanitizeValue = (value: unknown, depth = 0): unknown => {\n // Prevent infinite recursion\n if (depth > MAX_OBJECT_DEPTH) {\n // Silent depth limit - prevents stack overflow\n return null;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return sanitizeString(value);\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < -Number.MAX_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {\n // Silent normalization - invalid numbers become 0\n return 0;\n }\n\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (Array.isArray(value)) {\n const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);\n\n // Silent array length limit\n const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);\n\n // Silent filter - empty arrays are valid results\n return sanitizedArray;\n }\n\n if (typeof value === 'object') {\n const sanitizedObject: Record<string, unknown> = {};\n const entries = Object.entries(value);\n const limitedEntries = entries.slice(0, 20);\n\n // Silent object keys limit\n for (const [key, value_] of limitedEntries) {\n const sanitizedKey = sanitizeString(key);\n\n if (sanitizedKey) {\n const sanitizedValue = sanitizeValue(value_, depth + 1);\n\n if (sanitizedValue !== null) {\n sanitizedObject[sanitizedKey] = sanitizedValue;\n }\n }\n }\n\n return sanitizedObject;\n }\n\n return null;\n};\n\n/**\n * Sanitizes user metadata for custom events\n * @param metadata - The metadata to sanitize\n * @returns The sanitized metadata\n */\nexport const sanitizeMetadata = (metadata: unknown): Record<string, MetadataType> => {\n if (typeof metadata !== 'object' || metadata === null) {\n return {};\n }\n\n try {\n const sanitized = sanitizeValue(metadata);\n const result =\n typeof sanitized === 'object' && sanitized !== null ? (sanitized as Record<string, MetadataType>) : {};\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] Metadata sanitization failed: ${errorMessage}`);\n }\n};\n","import {\n MAX_SESSION_TIMEOUT_MS,\n MIN_SESSION_TIMEOUT_MS,\n DEFAULT_SESSION_TIMEOUT,\n VALIDATION_MESSAGES,\n} from '../../constants';\nimport { Config } from '../../types';\nimport {\n AppConfigValidationError,\n SessionTimeoutValidationError,\n SamplingRateValidationError,\n IntegrationValidationError,\n} from '../../types/validation-error.types';\nimport { log } from '../logging.utils';\n\n/**\n * Validates the app configuration object (before normalization)\n * This validates the structure and basic types but allows for normalization afterward\n * @param config - The app configuration to validate\n * @throws {ProjectIdValidationError} If project ID validation fails\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAppConfig = (config?: Config): void => {\n if (config !== undefined && (config === null || typeof config !== 'object')) {\n throw new AppConfigValidationError('Configuration must be an object', 'config');\n }\n\n if (!config) {\n return;\n }\n\n if (config.sessionTimeout !== undefined) {\n if (\n typeof config.sessionTimeout !== 'number' ||\n config.sessionTimeout < MIN_SESSION_TIMEOUT_MS ||\n config.sessionTimeout > MAX_SESSION_TIMEOUT_MS\n ) {\n throw new SessionTimeoutValidationError(VALIDATION_MESSAGES.INVALID_SESSION_TIMEOUT, 'config');\n }\n }\n\n if (config.globalMetadata !== undefined) {\n if (typeof config.globalMetadata !== 'object' || config.globalMetadata === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_GLOBAL_METADATA, 'config');\n }\n }\n\n if (config.scrollContainerSelectors !== undefined) {\n validateScrollContainerSelectors(config.scrollContainerSelectors);\n }\n\n if (config.integrations) {\n validateIntegrations(config.integrations);\n }\n\n if (config.sensitiveQueryParams !== undefined) {\n if (!Array.isArray(config.sensitiveQueryParams)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SENSITIVE_QUERY_PARAMS, 'config');\n }\n\n for (const param of config.sensitiveQueryParams) {\n if (typeof param !== 'string') {\n throw new AppConfigValidationError('All sensitive query params must be strings', 'config');\n }\n }\n }\n\n if (config.errorSampling !== undefined) {\n if (typeof config.errorSampling !== 'number' || config.errorSampling < 0 || config.errorSampling > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_ERROR_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.samplingRate !== undefined) {\n if (typeof config.samplingRate !== 'number' || config.samplingRate < 0 || config.samplingRate > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_SAMPLING_RATE, 'config');\n }\n }\n};\n\n/**\n * Validates CSS selector syntax without executing querySelector (XSS prevention)\n * @param selector - CSS selector to validate\n * @returns True if the selector syntax is valid\n */\nconst isValidCssSelectorSyntax = (selector: string): boolean => {\n // Prevent dangerous characters that could indicate XSS attempts\n if (selector.includes('<') || selector.includes('>') || /on\\w+\\s*=/i.test(selector)) {\n return false;\n }\n\n // Safe CSS selector pattern - allows common selector syntax\n const safePattern = /^[a-zA-Z0-9\\-_#.[\\]=\"':, >+~*()]+$/;\n if (!safePattern.test(selector)) {\n return false;\n }\n\n // Check for balanced parentheses\n let parenthesesCount = 0;\n for (const char of selector) {\n if (char === '(') parenthesesCount++;\n if (char === ')') parenthesesCount--;\n if (parenthesesCount < 0) return false;\n }\n if (parenthesesCount !== 0) return false;\n\n // Check for balanced square brackets\n let bracketsCount = 0;\n for (const char of selector) {\n if (char === '[') bracketsCount++;\n if (char === ']') bracketsCount--;\n if (bracketsCount < 0) return false;\n }\n if (bracketsCount !== 0) return false;\n\n return true;\n};\n\n/**\n * Validates scroll container selectors\n * @param selectors - CSS selectors to validate\n */\nconst validateScrollContainerSelectors = (selectors: string | string[]): void => {\n const selectorsArray = Array.isArray(selectors) ? selectors : [selectors];\n\n for (const selector of selectorsArray) {\n if (typeof selector !== 'string' || selector.trim() === '') {\n log('error', 'Invalid scroll container selector', {\n showToClient: true,\n data: {\n selector,\n type: typeof selector,\n isEmpty: selector === '' || (typeof selector === 'string' && selector.trim() === ''),\n },\n });\n\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SCROLL_CONTAINER_SELECTORS, 'config');\n }\n\n // Validate CSS selector syntax using regex-based validation (XSS prevention)\n // This validates syntax WITHOUT executing document.querySelector()\n if (!isValidCssSelectorSyntax(selector)) {\n log('error', 'Invalid or potentially unsafe CSS selector', {\n showToClient: true,\n data: {\n selector,\n reason: 'Failed security validation',\n },\n });\n\n throw new AppConfigValidationError('Invalid or potentially unsafe CSS selector', 'config');\n }\n }\n};\n\n/**\n * Validates integrations configuration\n * @param integrations - Integrations configuration to validate\n */\nconst validateIntegrations = (integrations: Config['integrations']): void => {\n if (!integrations) {\n return;\n }\n\n if (integrations.tracelog) {\n if (\n !integrations.tracelog.projectId ||\n typeof integrations.tracelog.projectId !== 'string' ||\n integrations.tracelog.projectId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_TRACELOG_PROJECT_ID, 'config');\n }\n }\n\n if (integrations.custom) {\n if (\n !integrations.custom.collectApiUrl ||\n typeof integrations.custom.collectApiUrl !== 'string' ||\n integrations.custom.collectApiUrl.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_CUSTOM_API_URL, 'config');\n }\n\n if (integrations.custom.allowHttp !== undefined && typeof integrations.custom.allowHttp !== 'boolean') {\n throw new IntegrationValidationError('allowHttp must be a boolean', 'config');\n }\n\n const collectApiUrl = integrations.custom.collectApiUrl.trim();\n\n if (!collectApiUrl.startsWith('http://') && !collectApiUrl.startsWith('https://')) {\n throw new IntegrationValidationError('Custom API URL must start with \"http://\" or \"https://\"', 'config');\n }\n\n const allowHttp = integrations.custom.allowHttp ?? false;\n\n if (!allowHttp && collectApiUrl.startsWith('http://')) {\n throw new IntegrationValidationError(\n 'Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)',\n 'config',\n );\n }\n }\n\n if (integrations.googleAnalytics) {\n if (\n !integrations.googleAnalytics.measurementId ||\n typeof integrations.googleAnalytics.measurementId !== 'string' ||\n integrations.googleAnalytics.measurementId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_GOOGLE_ANALYTICS_ID, 'config');\n }\n\n const measurementId = integrations.googleAnalytics.measurementId.trim();\n\n if (!measurementId.match(/^(G-|UA-)/)) {\n throw new IntegrationValidationError('Google Analytics measurement ID must start with \"G-\" or \"UA-\"', 'config');\n }\n }\n};\n\n/**\n * Validates and normalizes the app configuration\n * This is the primary validation entry point that ensures consistent behavior\n * @param config - The app configuration to validate and normalize\n * @returns The normalized configuration\n * @throws {ProjectIdValidationError} If project ID validation fails after normalization\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAndNormalizeConfig = (config?: Config): Config => {\n validateAppConfig(config);\n\n const normalizedConfig: Config = {\n ...(config ?? {}),\n sessionTimeout: config?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,\n globalMetadata: config?.globalMetadata ?? {},\n sensitiveQueryParams: config?.sensitiveQueryParams ?? [],\n errorSampling: config?.errorSampling ?? 1,\n samplingRate: config?.samplingRate ?? 1,\n };\n\n // Normalize integrations\n if (normalizedConfig.integrations?.custom) {\n normalizedConfig.integrations.custom = {\n ...normalizedConfig.integrations.custom,\n allowHttp: normalizedConfig.integrations.custom.allowHttp ?? false,\n };\n }\n\n return normalizedConfig;\n};\n","import { MAX_NESTED_OBJECT_KEYS } from '../../constants';\n\n/**\n * Validates if an item in an array is a valid nested object\n * @param item - The item to validate\n * @returns True if the item is a valid nested object\n */\nconst isValidArrayItem = (item: unknown): boolean => {\n if (typeof item === 'string') {\n return true;\n }\n\n // Allow objects with primitive fields only (one level deep)\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const entries = Object.entries(item);\n\n // Check key count limit\n if (entries.length > MAX_NESTED_OBJECT_KEYS) {\n return false;\n }\n\n // All values must be primitives (no nested objects or arrays)\n for (const [, value] of entries) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n};\n\n/**\n * Checks if an object contains only primitive fields, string arrays, or arrays of flat objects\n * @param object - The object to check\n * @returns True if the object contains only valid fields\n */\nexport const isOnlyPrimitiveFields = (object: Record<string, unknown>): boolean => {\n if (typeof object !== 'object' || object === null) {\n return false;\n }\n\n for (const value of Object.values(object)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type === 'string' || type === 'number' || type === 'boolean') {\n continue;\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n\n // Determine array type from first item\n const firstItem = value[0];\n const isStringArray = typeof firstItem === 'string';\n\n // All items must be of the same type (all strings OR all objects)\n if (isStringArray) {\n if (!value.every((item) => typeof item === 'string')) {\n return false;\n }\n } else {\n // Must be all objects\n if (!value.every((item) => isValidArrayItem(item))) {\n return false;\n }\n }\n\n continue;\n }\n\n return false;\n }\n\n return true;\n};\n","import {\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_STRING_LENGTH,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { sanitizeMetadata } from '../security/sanitize.utils';\nimport { isOnlyPrimitiveFields } from './type-guards.utils';\n\n/**\n * Validates an event name\n * @param eventName - The event name to validate\n * @returns Validation result with error message if invalid\n */\nexport const isValidEventName = (eventName: string): { valid: boolean; error?: string } => {\n if (typeof eventName !== 'string') {\n return {\n valid: false,\n error: 'Event name must be a string',\n };\n }\n\n if (eventName.length === 0) {\n return {\n valid: false,\n error: 'Event name cannot be empty',\n };\n }\n\n if (eventName.length > MAX_CUSTOM_EVENT_NAME_LENGTH) {\n return {\n valid: false,\n error: `Event name is too long (max ${MAX_CUSTOM_EVENT_NAME_LENGTH} characters)`,\n };\n }\n\n if (eventName.includes('<') || eventName.includes('>') || eventName.includes('&')) {\n return {\n valid: false,\n error: 'Event name contains invalid characters',\n };\n }\n\n const reservedWords = ['constructor', 'prototype', '__proto__', 'eval', 'function', 'var', 'let', 'const'];\n\n if (reservedWords.includes(eventName.toLowerCase())) {\n return {\n valid: false,\n error: 'Event name cannot be a reserved word',\n };\n }\n\n return { valid: true };\n};\n\n/**\n * Validates a single metadata object\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata object to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nconst validateSingleMetadata = (\n eventName: string,\n metadata: Record<string, unknown>,\n type?: 'globalMetadata' | 'customEvent',\n): { valid: boolean; error?: string; sanitizedMetadata?: Record<string, MetadataType> } => {\n const sanitizedMetadata = sanitizeMetadata(metadata);\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n if (!isOnlyPrimitiveFields(sanitizedMetadata)) {\n return {\n valid: false,\n error: `${intro}: object has invalid types. Valid types are string, number, boolean or string arrays.`,\n };\n }\n\n let jsonString: string;\n\n try {\n jsonString = JSON.stringify(sanitizedMetadata);\n } catch {\n return {\n valid: false,\n error: `${intro}: object contains circular references or cannot be serialized.`,\n };\n }\n\n if (jsonString.length > MAX_CUSTOM_EVENT_STRING_SIZE) {\n return {\n valid: false,\n error: `${intro}: object is too large (max ${MAX_CUSTOM_EVENT_STRING_SIZE / 1024} KB).`,\n };\n }\n\n const keyCount = Object.keys(sanitizedMetadata).length;\n\n if (keyCount > MAX_CUSTOM_EVENT_KEYS) {\n return {\n valid: false,\n error: `${intro}: object has too many keys (max ${MAX_CUSTOM_EVENT_KEYS} keys).`,\n };\n }\n\n for (const [key, value] of Object.entries(sanitizedMetadata)) {\n if (Array.isArray(value)) {\n if (value.length > MAX_CUSTOM_EVENT_ARRAY_SIZE) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" is too large (max ${MAX_CUSTOM_EVENT_ARRAY_SIZE} items).`,\n };\n }\n\n for (const item of value) {\n if (typeof item === 'string' && item.length > 500) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" contains strings that are too long (max 500 characters).`,\n };\n }\n }\n }\n\n if (typeof value === 'string' && value.length > MAX_STRING_LENGTH) {\n return {\n valid: false,\n error: `${intro}: property \"${key}\" is too long (max ${MAX_STRING_LENGTH} characters).`,\n };\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata,\n };\n};\n\n/**\n * Validates metadata for events (supports both objects and arrays of objects)\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isValidMetadata = (\n eventName: string,\n metadata: Record<string, unknown> | Record<string, unknown>[],\n type?: 'globalMetadata' | 'customEvent',\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n if (Array.isArray(metadata)) {\n const sanitizedArray: Record<string, MetadataType>[] = [];\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n for (let i = 0; i < metadata.length; i++) {\n const item = metadata[i];\n\n if (typeof item !== 'object' || item === null || Array.isArray(item)) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} must be an object.`,\n };\n }\n\n const itemValidation = validateSingleMetadata(eventName, item, type);\n\n if (!itemValidation.valid) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} is invalid: ${itemValidation.error}`,\n };\n }\n\n if (itemValidation.sanitizedMetadata) {\n sanitizedArray.push(itemValidation.sanitizedMetadata);\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata: sanitizedArray,\n };\n }\n\n return validateSingleMetadata(eventName, metadata, type);\n};\n","import { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\nimport { isValidEventName, isValidMetadata } from './metadata-validations.utils';\n\n/**\n * Validates a complete event with name and optional metadata\n * @param eventName - The event name to validate\n * @param metadata - Optional metadata to validate\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isEventValid = (\n eventName: string,\n metadata?: Record<string, unknown> | Record<string, unknown>[],\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n const nameValidation = isValidEventName(eventName);\n\n if (!nameValidation.valid) {\n log('error', 'Event name validation failed', {\n showToClient: true,\n data: { eventName, error: nameValidation.error },\n });\n\n return nameValidation;\n }\n\n if (!metadata) {\n return { valid: true };\n }\n\n const metadataValidation = isValidMetadata(eventName, metadata, 'customEvent');\n\n if (!metadataValidation.valid) {\n log('error', 'Event metadata validation failed', {\n showToClient: true,\n data: {\n eventName,\n error: metadataValidation.error,\n },\n });\n }\n\n return metadataValidation;\n};\n","import { EmitterCallback, EmitterMap } from '../types';\n\nexport class Emitter {\n private readonly listeners: Map<string, EmitterCallback[]> = new Map();\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n\n this.listeners.get(event)!.push(callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n const index = callbacks.indexOf(callback);\n\n if (index > -1) {\n callbacks.splice(index, 1);\n }\n }\n }\n\n emit<K extends keyof EmitterMap>(event: K, data: EmitterMap[K]): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n callbacks.forEach((callback) => callback(data));\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { State } from '../types';\n\nconst globalState: State = {} as State;\n\nexport function getGlobalState(): Readonly<State> {\n return globalState;\n}\n\nexport function resetGlobalState(): void {\n Object.keys(globalState).forEach((key) => {\n delete globalState[key as keyof State];\n });\n}\n\nexport abstract class StateManager {\n protected get<T extends keyof State>(key: T): State[T] {\n return globalState[key];\n }\n\n protected set<T extends keyof State>(key: T, value: State[T]): void {\n globalState[key] = value;\n }\n\n protected getState(): Readonly<State> {\n return { ...globalState };\n }\n}\n","import { QUEUE_KEY, EVENT_EXPIRY_HOURS, MAX_RETRIES, RETRY_DELAY_MS, REQUEST_TIMEOUT_MS } from '../constants';\nimport { PersistedQueueData, BaseEventsQueueDto, SpecialApiUrl } from '../types';\nimport { log } from '../utils';\nimport { StorageManager } from './storage.manager';\nimport { StateManager } from './state.manager';\n\ninterface SendCallbacks {\n onSuccess?: (eventCount?: number, events?: any[], body?: BaseEventsQueueDto) => void;\n onFailure?: () => void;\n}\n\nexport class SenderManager extends StateManager {\n private readonly storeManager: StorageManager;\n private retryTimeoutId: number | null = null;\n private retryCount = 0;\n private isRetrying = false;\n\n constructor(storeManager: StorageManager) {\n super();\n this.storeManager = storeManager;\n }\n\n private getQueueStorageKey(): string {\n const userId = this.get('userId') || 'anonymous';\n return QUEUE_KEY(userId);\n }\n\n sendEventsQueueSync(body: BaseEventsQueueDto): boolean {\n if (this.shouldSkipSend()) {\n this.resetRetryState();\n\n return true;\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure (sync)', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const success = this.sendQueueSyncInternal(body);\n\n if (success) {\n this.resetRetryState();\n }\n\n return success;\n }\n\n async sendEventsQueue(body: BaseEventsQueueDto, callbacks?: SendCallbacks): Promise<boolean> {\n if (!this.shouldSkipSend()) {\n const persisted = this.persistEvents(body);\n\n if (!persisted) {\n log('warn', 'Failed to persist events, attempting immediate send');\n }\n }\n\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n callbacks?.onSuccess?.(body.events.length, body.events, body);\n } else {\n this.scheduleRetry(body, callbacks);\n callbacks?.onFailure?.();\n }\n\n return success;\n }\n\n async recoverPersistedEvents(callbacks?: SendCallbacks): Promise<void> {\n try {\n const persistedData = this.getPersistedData();\n\n if (!persistedData || !this.isDataRecent(persistedData) || persistedData.events.length === 0) {\n this.clearPersistedEvents();\n return;\n }\n\n const body = this.createRecoveryBody(persistedData);\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n callbacks?.onSuccess?.(persistedData.events.length, persistedData.events, body);\n } else {\n this.scheduleRetry(body, callbacks);\n callbacks?.onFailure?.();\n }\n } catch (error) {\n log('error', 'Failed to recover persisted events', { error });\n this.clearPersistedEvents();\n }\n }\n\n persistEventsForRecovery(body: BaseEventsQueueDto): boolean {\n return this.persistEvents(body);\n }\n\n async sendEventsQueueAsync(body: BaseEventsQueueDto): Promise<boolean> {\n return this.sendEventsQueue(body);\n }\n\n stop(): void {\n this.clearRetryTimeout();\n this.resetRetryState();\n }\n\n private async send(body: BaseEventsQueueDto): Promise<boolean> {\n if (this.shouldSkipSend()) {\n return this.simulateSuccessfulSend();\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const { url, payload } = this.prepareRequest(body);\n\n try {\n const response = await this.sendWithTimeout(url, payload);\n\n return response.ok;\n } catch (error) {\n log('error', 'Send request failed', {\n error,\n data: {\n events: body.events.length,\n url: url.replace(/\\/\\/[^/]+/, '//[DOMAIN]'),\n },\n });\n\n return false;\n }\n }\n\n private async sendWithTimeout(url: string, payload: string): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n body: payload,\n keepalive: true,\n credentials: 'include',\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private sendQueueSyncInternal(body: BaseEventsQueueDto): boolean {\n const { url, payload } = this.prepareRequest(body);\n const blob = new Blob([payload], { type: 'application/json' });\n\n if (this.isSendBeaconAvailable()) {\n const success = navigator.sendBeacon(url, blob);\n\n if (success) {\n return true;\n }\n log('warn', 'sendBeacon failed, persisting events for recovery');\n } else {\n log('warn', 'sendBeacon not available, persisting events for recovery');\n }\n\n this.persistEventsForRecovery(body);\n\n return false;\n }\n\n private prepareRequest(body: BaseEventsQueueDto): { url: string; payload: string } {\n // Enrich payload with metadata for sendBeacon() fallback\n // sendBeacon() doesn't send custom headers, so we include referer in payload\n const enrichedBody = {\n ...body,\n _metadata: {\n referer: typeof window !== 'undefined' ? window.location.href : undefined,\n timestamp: Date.now(),\n },\n };\n\n return {\n url: this.get('collectApiUrl'),\n payload: JSON.stringify(enrichedBody),\n };\n }\n\n private getPersistedData(): PersistedQueueData | null {\n try {\n const storageKey = this.getQueueStorageKey();\n const persistedDataString = this.storeManager.getItem(storageKey);\n\n if (persistedDataString) {\n return JSON.parse(persistedDataString);\n }\n } catch (error) {\n log('warn', 'Failed to parse persisted data', { error });\n this.clearPersistedEvents();\n }\n\n return null;\n }\n\n private isDataRecent(data: PersistedQueueData): boolean {\n if (!data.timestamp || typeof data.timestamp !== 'number') {\n return false;\n }\n\n const ageInHours = (Date.now() - data.timestamp) / (1000 * 60 * 60);\n const isRecent = ageInHours < EVENT_EXPIRY_HOURS;\n\n return isRecent;\n }\n\n private createRecoveryBody(data: PersistedQueueData): BaseEventsQueueDto {\n return {\n user_id: data.userId,\n session_id: data.sessionId,\n device: data.device,\n events: data.events,\n ...(data.global_metadata && { global_metadata: data.global_metadata }),\n };\n }\n\n private persistEvents(body: BaseEventsQueueDto): boolean {\n try {\n const persistedData: PersistedQueueData = {\n userId: body.user_id,\n sessionId: body.session_id,\n device: body.device,\n events: body.events,\n timestamp: Date.now(),\n ...(body.global_metadata && { global_metadata: body.global_metadata }),\n };\n\n const storageKey = this.getQueueStorageKey();\n this.storeManager.setItem(storageKey, JSON.stringify(persistedData));\n\n return !!this.storeManager.getItem(storageKey);\n } catch (error) {\n log('warn', 'Failed to persist events', { error });\n return false;\n }\n }\n\n private clearPersistedEvents(): void {\n try {\n const key = this.getQueueStorageKey();\n this.storeManager.removeItem(key);\n } catch (error) {\n log('warn', 'Failed to clear persisted events', { error });\n }\n }\n\n private resetRetryState(): void {\n this.retryCount = 0;\n this.isRetrying = false;\n this.clearRetryTimeout();\n }\n\n private scheduleRetry(body: BaseEventsQueueDto, originalCallbacks?: SendCallbacks): void {\n if (this.retryTimeoutId !== null || this.isRetrying) {\n return;\n }\n\n if (this.retryCount >= MAX_RETRIES) {\n log('warn', 'Max retries reached, giving up', { data: { retryCount: this.retryCount } });\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onFailure?.();\n return;\n }\n\n const retryDelay = RETRY_DELAY_MS * Math.pow(2, this.retryCount); // Exponential backoff\n\n this.isRetrying = true;\n\n this.retryTimeoutId = window.setTimeout(async () => {\n this.retryTimeoutId = null;\n\n this.retryCount++;\n\n try {\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onSuccess?.(body.events.length);\n } else if (this.retryCount >= MAX_RETRIES) {\n this.clearPersistedEvents();\n this.resetRetryState();\n originalCallbacks?.onFailure?.();\n } else {\n this.scheduleRetry(body, originalCallbacks);\n }\n } finally {\n this.isRetrying = false;\n }\n }, retryDelay);\n }\n\n private shouldSkipSend(): boolean {\n return !this.get('collectApiUrl');\n }\n\n private async simulateSuccessfulSend(): Promise<boolean> {\n const delay = Math.random() * 400 + 100;\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return true;\n }\n\n private isSendBeaconAvailable(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n }\n\n private clearRetryTimeout(): void {\n if (this.retryTimeoutId !== null) {\n clearTimeout(this.retryTimeoutId);\n this.retryTimeoutId = null;\n }\n }\n}\n","import {\n EVENT_SENT_INTERVAL_MS,\n MAX_EVENTS_QUEUE_LENGTH,\n DUPLICATE_EVENT_THRESHOLD_MS,\n RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SECOND,\n MAX_PENDING_EVENTS_BUFFER,\n} from '../constants/config.constants';\nimport { BaseEventsQueueDto, EmitterEvent, EventData, EventType, Mode } from '../types';\nimport { getUTMParameters, log, Emitter, generateEventId } from '../utils';\nimport { SenderManager } from './sender.manager';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { GoogleAnalyticsIntegration } from '../integrations/google-analytics.integration';\n\nexport class EventManager extends StateManager {\n private readonly googleAnalytics: GoogleAnalyticsIntegration | null;\n private readonly dataSender: SenderManager;\n private readonly emitter: Emitter | null;\n\n private eventsQueue: EventData[] = [];\n private pendingEventsBuffer: Partial<EventData>[] = [];\n private lastEventFingerprint: string | null = null;\n private lastEventTime = 0;\n private sendIntervalId: number | null = null;\n private rateLimitCounter = 0;\n private rateLimitWindowStart = 0;\n\n constructor(\n storeManager: StorageManager,\n googleAnalytics: GoogleAnalyticsIntegration | null = null,\n emitter: Emitter | null = null,\n ) {\n super();\n\n this.googleAnalytics = googleAnalytics;\n this.dataSender = new SenderManager(storeManager);\n this.emitter = emitter;\n }\n\n async recoverPersistedEvents(): Promise<void> {\n await this.dataSender.recoverPersistedEvents({\n onSuccess: (_eventCount, recoveredEvents, body) => {\n if (recoveredEvents && recoveredEvents.length > 0) {\n const eventIds = recoveredEvents.map((e) => e.id);\n this.removeProcessedEvents(eventIds);\n\n if (body) {\n this.emitEventsQueue(body);\n }\n }\n },\n onFailure: async () => {\n log('warn', 'Failed to recover persisted events');\n },\n });\n }\n\n track({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n }: Partial<EventData>): void {\n if (!type) {\n log('error', 'Event type is required - event will be ignored');\n return;\n }\n\n // Check session BEFORE rate limiting to avoid consuming quota for buffered events\n if (!this.get('sessionId')) {\n // Protect against unbounded buffer growth during initialization delays\n if (this.pendingEventsBuffer.length >= MAX_PENDING_EVENTS_BUFFER) {\n // Drop oldest event (FIFO) to make room for new one\n this.pendingEventsBuffer.shift();\n log('warn', 'Pending events buffer full - dropping oldest event', {\n data: { maxBufferSize: MAX_PENDING_EVENTS_BUFFER },\n });\n }\n\n this.pendingEventsBuffer.push({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n });\n\n return;\n }\n\n // Rate limiting check (except for critical events)\n // Applied AFTER session check to only rate-limit processable events\n const isCriticalEvent = type === EventType.SESSION_START || type === EventType.SESSION_END;\n if (!isCriticalEvent && !this.checkRateLimit()) {\n // Rate limit exceeded - drop event silently\n // Logging would itself cause performance issues\n return;\n }\n\n const eventType = type as EventType;\n const isSessionStart = eventType === EventType.SESSION_START;\n\n const currentPageUrl = (page_url as string) || this.get('pageUrl');\n const payload = this.buildEventPayload({\n type: eventType,\n page_url: currentPageUrl,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n });\n\n if (!isCriticalEvent && !this.shouldSample()) {\n return;\n }\n\n if (isSessionStart) {\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n log('error', 'Session start event requires sessionId - event will be ignored');\n return;\n }\n\n if (this.get('hasStartSession')) {\n log('warn', 'Duplicate session_start detected', {\n data: { sessionId: currentSessionId },\n });\n\n return;\n }\n\n this.set('hasStartSession', true);\n }\n\n if (this.isDuplicateEvent(payload)) {\n return;\n }\n\n if (this.get('mode') === Mode.QA && eventType === EventType.CUSTOM && custom_event) {\n console.log('[TraceLog] Event', {\n name: custom_event.name,\n ...(custom_event.metadata && { metadata: custom_event.metadata }),\n });\n\n this.emitEvent(payload);\n\n return;\n }\n\n this.addToQueue(payload);\n }\n\n stop(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n\n this.eventsQueue = [];\n this.pendingEventsBuffer = [];\n this.lastEventFingerprint = null;\n this.lastEventTime = 0;\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = 0;\n\n this.dataSender.stop();\n }\n\n async flushImmediately(): Promise<boolean> {\n return this.flushEvents(false);\n }\n\n flushImmediatelySync(): boolean {\n return this.flushEvents(true) as boolean;\n }\n\n getQueueLength(): number {\n return this.eventsQueue.length;\n }\n\n flushPendingEvents(): void {\n if (this.pendingEventsBuffer.length === 0) {\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n if (!currentSessionId) {\n // Keep events in buffer for future retry - do NOT discard\n // This prevents data loss during legitimate race conditions\n log('warn', 'Cannot flush pending events: session not initialized - keeping in buffer', {\n data: { bufferedEventCount: this.pendingEventsBuffer.length },\n });\n\n return;\n }\n\n // Create copy before clearing to avoid infinite recursion\n const bufferedEvents = [...this.pendingEventsBuffer];\n this.pendingEventsBuffer = [];\n\n // Process all buffered events now that session exists\n bufferedEvents.forEach((event) => {\n this.track(event);\n });\n }\n\n private clearSendInterval(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n }\n\n private flushEvents(isSync: boolean): boolean | Promise<boolean> {\n if (this.eventsQueue.length === 0) {\n return isSync ? true : Promise.resolve(true);\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n if (isSync) {\n const success = this.dataSender.sendEventsQueueSync(body);\n\n if (success) {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n }\n\n return success;\n } else {\n return this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n log('warn', 'Async flush failed', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n }\n\n private async sendEventsQueue(): Promise<void> {\n if (!this.get('sessionId') || this.eventsQueue.length === 0) {\n return;\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n await this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.emitEventsQueue(body);\n },\n onFailure: async () => {\n log('warn', 'Events send failed, keeping in queue', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n\n private buildEventsPayload(): BaseEventsQueueDto {\n const eventMap = new Map<string, EventData>();\n const order: string[] = [];\n\n for (const event of this.eventsQueue) {\n const signature = this.createEventSignature(event);\n\n if (!eventMap.has(signature)) {\n order.push(signature);\n }\n\n eventMap.set(signature, event);\n }\n\n const events = order\n .map((signature) => eventMap.get(signature))\n .filter((event): event is EventData => Boolean(event))\n .sort((a, b) => a.timestamp - b.timestamp);\n\n return {\n user_id: this.get('userId'),\n session_id: this.get('sessionId') as string,\n device: this.get('device'),\n events,\n ...(this.get('config')?.globalMetadata && { global_metadata: this.get('config')?.globalMetadata }),\n };\n }\n\n private buildEventPayload(data: Partial<EventData>): EventData {\n const isSessionStart = data.type === EventType.SESSION_START;\n const currentPageUrl = data.page_url ?? this.get('pageUrl');\n\n const payload: EventData = {\n id: generateEventId(),\n type: data.type as EventType,\n page_url: currentPageUrl,\n timestamp: Date.now(),\n ...(isSessionStart && { referrer: document.referrer || 'Direct' }),\n ...(data.from_page_url && { from_page_url: data.from_page_url }),\n ...(data.scroll_data && { scroll_data: data.scroll_data }),\n ...(data.click_data && { click_data: data.click_data }),\n ...(data.custom_event && { custom_event: data.custom_event }),\n ...(data.web_vitals && { web_vitals: data.web_vitals }),\n ...(data.error_data && { error_data: data.error_data }),\n ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),\n ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),\n };\n\n return payload;\n }\n\n private isDuplicateEvent(event: EventData): boolean {\n const now = Date.now();\n const fingerprint = this.createEventFingerprint(event);\n\n if (this.lastEventFingerprint === fingerprint && now - this.lastEventTime < DUPLICATE_EVENT_THRESHOLD_MS) {\n return true;\n }\n\n this.lastEventFingerprint = fingerprint;\n this.lastEventTime = now;\n return false;\n }\n\n private createEventFingerprint(event: EventData): string {\n let fingerprint = `${event.type}_${event.page_url}`;\n\n if (event.click_data) {\n const x = Math.round((event.click_data.x || 0) / 10) * 10;\n const y = Math.round((event.click_data.y || 0) / 10) * 10;\n fingerprint += `_click_${x}_${y}`;\n }\n\n if (event.scroll_data) {\n fingerprint += `_scroll_${event.scroll_data.depth}_${event.scroll_data.direction}`;\n }\n\n if (event.custom_event) {\n fingerprint += `_custom_${event.custom_event.name}`;\n }\n\n if (event.web_vitals) {\n fingerprint += `_vitals_${event.web_vitals.type}`;\n }\n\n if (event.error_data) {\n fingerprint += `_error_${event.error_data.type}_${event.error_data.message}`;\n }\n\n return fingerprint;\n }\n\n private createEventSignature(event: EventData): string {\n return this.createEventFingerprint(event);\n }\n\n private addToQueue(event: EventData): void {\n this.eventsQueue.push(event);\n\n this.emitEvent(event);\n\n if (this.eventsQueue.length > MAX_EVENTS_QUEUE_LENGTH) {\n const nonCriticalIndex = this.eventsQueue.findIndex(\n (e) => e.type !== EventType.SESSION_START && e.type !== EventType.SESSION_END,\n );\n\n const removedEvent =\n nonCriticalIndex >= 0 ? this.eventsQueue.splice(nonCriticalIndex, 1)[0] : this.eventsQueue.shift();\n\n log('warn', 'Event queue overflow, oldest non-critical event removed', {\n data: {\n maxLength: MAX_EVENTS_QUEUE_LENGTH,\n currentLength: this.eventsQueue.length,\n removedEventType: removedEvent?.type,\n wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,\n },\n });\n }\n\n if (!this.sendIntervalId) {\n this.startSendInterval();\n }\n\n this.handleGoogleAnalyticsIntegration(event);\n }\n\n private startSendInterval(): void {\n this.sendIntervalId = window.setInterval(() => {\n if (this.eventsQueue.length > 0) {\n this.sendEventsQueue();\n }\n }, EVENT_SENT_INTERVAL_MS);\n }\n\n private handleGoogleAnalyticsIntegration(event: EventData): void {\n if (this.googleAnalytics && event.type === EventType.CUSTOM && event.custom_event) {\n if (this.get('mode') === Mode.QA) {\n return;\n }\n\n this.googleAnalytics.trackEvent(event.custom_event.name, event.custom_event.metadata ?? {});\n }\n }\n\n private shouldSample(): boolean {\n const samplingRate = this.get('config')?.samplingRate ?? 1;\n return Math.random() < samplingRate;\n }\n\n private checkRateLimit(): boolean {\n const now = Date.now();\n\n // Reset counter if window has expired\n if (now - this.rateLimitWindowStart > RATE_LIMIT_WINDOW_MS) {\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = now;\n }\n\n // Check if limit exceeded\n if (this.rateLimitCounter >= MAX_EVENTS_PER_SECOND) {\n return false;\n }\n\n // Increment counter\n this.rateLimitCounter++;\n return true;\n }\n\n private removeProcessedEvents(eventIds: string[]): void {\n const eventIdSet = new Set(eventIds);\n\n this.eventsQueue = this.eventsQueue.filter((event) => {\n return !eventIdSet.has(event.id);\n });\n }\n\n private emitEvent(eventData: EventData): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.EVENT, eventData);\n }\n }\n\n private emitEventsQueue(queue: BaseEventsQueueDto): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.QUEUE, queue);\n }\n }\n}\n","import { USER_ID_KEY } from '../constants';\nimport { generateUUID } from '../utils';\nimport { StorageManager } from './storage.manager';\n\n/**\n * Simple utility for managing user identification.\n * Generates and persists unique user IDs per project.\n */\nexport class UserManager {\n /**\n * Gets or creates a unique user ID for the given project.\n * The user ID is persisted in localStorage and reused across sessions.\n *\n * @param storageManager - Storage manager instance\n * @param projectId - Project identifier for namespacing\n * @returns Persistent unique user ID\n */\n static getId(storageManager: StorageManager): string {\n const storageKey = USER_ID_KEY;\n const storedUserId = storageManager.getItem(storageKey);\n\n if (storedUserId) {\n return storedUserId;\n }\n\n const newUserId = generateUUID();\n storageManager.setItem(storageKey, newUserId);\n\n return newUserId;\n }\n}\n","import { BROADCAST_CHANNEL_NAME, DEFAULT_SESSION_TIMEOUT, SESSION_STORAGE_KEY } from '../constants';\nimport { EventType } from '../types';\nimport { SessionEndReason } from '../types/session.types';\nimport { log } from '../utils';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { EventManager } from './event.manager';\n\ninterface StoredSessionData {\n id: string;\n lastActivity: number;\n}\n\nexport class SessionManager extends StateManager {\n private readonly storageManager: StorageManager;\n private readonly eventManager: EventManager;\n private readonly projectId: string;\n private sessionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private broadcastChannel: BroadcastChannel | null = null;\n private activityHandler: (() => void) | null = null;\n private visibilityChangeHandler: (() => void) | null = null;\n private beforeUnloadHandler: ((event: BeforeUnloadEvent) => void) | null = null;\n private isTracking = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager, projectId: string) {\n super();\n this.storageManager = storageManager;\n this.eventManager = eventManager;\n this.projectId = projectId;\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') {\n log('warn', 'BroadcastChannel not supported');\n return;\n }\n\n const projectId = this.getProjectId();\n this.broadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME(projectId));\n\n this.broadcastChannel.onmessage = (event): void => {\n const { action, sessionId, timestamp, projectId: messageProjectId } = event.data ?? {};\n\n if (messageProjectId !== projectId) {\n return;\n }\n\n if (action === 'session_end') {\n this.resetSessionState();\n return;\n }\n\n if (sessionId && typeof timestamp === 'number' && timestamp > Date.now() - 5000) {\n this.set('sessionId', sessionId);\n this.set('hasStartSession', true);\n this.persistSession(sessionId, timestamp);\n if (this.isTracking) {\n this.setupSessionTimeout();\n }\n }\n };\n }\n\n private shareSession(sessionId: string): void {\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_start',\n projectId: this.getProjectId(),\n sessionId,\n timestamp: Date.now(),\n });\n }\n }\n\n private broadcastSessionEnd(sessionId: string | null, reason: SessionEndReason): void {\n if (!sessionId) {\n return;\n }\n\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_end',\n projectId: this.getProjectId(),\n sessionId,\n reason,\n timestamp: Date.now(),\n });\n }\n }\n\n private cleanupCrossTabSync(): void {\n if (this.broadcastChannel) {\n if (typeof this.broadcastChannel.close === 'function') {\n this.broadcastChannel.close();\n }\n this.broadcastChannel = null;\n }\n }\n\n private recoverSession(): string | null {\n const storedSession = this.loadStoredSession();\n\n if (!storedSession) {\n return null;\n }\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n if (Date.now() - storedSession.lastActivity > sessionTimeout) {\n this.clearStoredSession();\n return null;\n }\n\n return storedSession.id;\n }\n\n private persistSession(sessionId: string, lastActivity: number = Date.now()): void {\n this.saveStoredSession({\n id: sessionId,\n lastActivity,\n });\n }\n\n private clearStoredSession(): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.removeItem(storageKey);\n }\n\n private loadStoredSession(): StoredSessionData | null {\n const storageKey = this.getSessionStorageKey();\n const storedData = this.storageManager.getItem(storageKey);\n\n if (!storedData) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(storedData) as StoredSessionData;\n if (!parsed.id || typeof parsed.lastActivity !== 'number') {\n return null;\n }\n return parsed;\n } catch {\n this.storageManager.removeItem(storageKey);\n return null;\n }\n }\n\n private saveStoredSession(session: StoredSessionData): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.setItem(storageKey, JSON.stringify(session));\n }\n\n private getSessionStorageKey(): string {\n return SESSION_STORAGE_KEY(this.getProjectId());\n }\n\n private getProjectId(): string {\n return this.projectId;\n }\n\n async startTracking(): Promise<void> {\n if (this.isTracking) {\n log('warn', 'Session tracking already active');\n return;\n }\n\n const recoveredSessionId = this.recoverSession();\n const sessionId = recoveredSessionId ?? this.generateSessionId();\n const isRecovered = Boolean(recoveredSessionId);\n\n this.isTracking = true;\n\n try {\n this.set('sessionId', sessionId);\n this.persistSession(sessionId);\n\n if (!isRecovered) {\n this.eventManager.track({\n type: EventType.SESSION_START,\n });\n }\n\n this.initCrossTabSync();\n this.shareSession(sessionId);\n this.setupSessionTimeout();\n this.setupActivityListeners();\n this.setupLifecycleListeners();\n } catch (error) {\n this.isTracking = false;\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n this.set('sessionId', null);\n\n throw error;\n }\n }\n\n private generateSessionId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private setupSessionTimeout(): void {\n this.clearSessionTimeout();\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n this.sessionTimeoutId = setTimeout(() => {\n this.endSession('inactivity');\n }, sessionTimeout);\n }\n\n private resetSessionTimeout(): void {\n this.setupSessionTimeout();\n const sessionId = this.get('sessionId') as string;\n if (sessionId) {\n this.persistSession(sessionId);\n }\n }\n\n private clearSessionTimeout(): void {\n if (this.sessionTimeoutId) {\n clearTimeout(this.sessionTimeoutId);\n this.sessionTimeoutId = null;\n }\n }\n\n private setupActivityListeners(): void {\n this.activityHandler = (): void => this.resetSessionTimeout();\n\n document.addEventListener('click', this.activityHandler, { passive: true });\n document.addEventListener('keydown', this.activityHandler, { passive: true });\n document.addEventListener('scroll', this.activityHandler, { passive: true });\n }\n\n private cleanupActivityListeners(): void {\n if (this.activityHandler) {\n document.removeEventListener('click', this.activityHandler);\n document.removeEventListener('keydown', this.activityHandler);\n document.removeEventListener('scroll', this.activityHandler);\n this.activityHandler = null;\n }\n }\n\n private setupLifecycleListeners(): void {\n if (this.visibilityChangeHandler || this.beforeUnloadHandler) {\n return;\n }\n\n this.visibilityChangeHandler = (): void => {\n if (document.hidden) {\n this.clearSessionTimeout();\n } else {\n const sessionId = this.get('sessionId');\n if (sessionId) {\n this.setupSessionTimeout();\n }\n }\n };\n\n this.beforeUnloadHandler = (): void => {\n this.endSession('page_unload');\n };\n\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n }\n\n private cleanupLifecycleListeners(): void {\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n }\n\n private async endSession(reason: SessionEndReason): Promise<void> {\n const sessionId = this.get('sessionId');\n\n if (!sessionId) {\n log('warn', 'endSession called without active session', { data: { reason } });\n this.resetSessionState(reason);\n return;\n }\n\n this.eventManager.track({\n type: EventType.SESSION_END,\n session_end_reason: reason,\n });\n\n const finalize = (): void => {\n this.broadcastSessionEnd(sessionId, reason);\n this.resetSessionState(reason);\n };\n\n const flushResult = this.eventManager.flushImmediatelySync();\n\n if (flushResult) {\n finalize();\n return;\n }\n\n try {\n await this.eventManager.flushImmediately();\n finalize();\n } catch (error) {\n log('warn', 'Async flush failed during session end', { error });\n finalize();\n }\n }\n\n private resetSessionState(reason?: SessionEndReason): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n\n if (reason !== 'page_unload') {\n this.clearStoredSession();\n }\n\n this.set('sessionId', null);\n this.set('hasStartSession', false);\n this.isTracking = false;\n }\n\n async stopTracking(): Promise<void> {\n await this.endSession('manual_stop');\n }\n\n destroy(): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupCrossTabSync();\n this.cleanupLifecycleListeners();\n this.isTracking = false;\n this.set('hasStartSession', false);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { SessionManager } from '../managers/session.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { StorageManager } from '../managers/storage.manager';\nimport { log } from '../utils';\n\nexport class SessionHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly storageManager: StorageManager;\n private sessionManager: SessionManager | null = null;\n private destroyed = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n this.storageManager = storageManager;\n }\n\n async startTracking(): Promise<void> {\n if (this.isActive()) {\n return;\n }\n\n if (this.destroyed) {\n log('warn', 'Cannot start tracking on destroyed handler');\n return;\n }\n\n const config = this.get('config');\n const projectId =\n config?.integrations?.tracelog?.projectId ?? config?.integrations?.custom?.collectApiUrl ?? 'default';\n\n if (!projectId) {\n throw new Error('Cannot start session tracking: config not available');\n }\n\n try {\n this.sessionManager = new SessionManager(this.storageManager, this.eventManager, projectId);\n await this.sessionManager.startTracking();\n\n // Flush any events that were buffered during initialization\n this.eventManager.flushPendingEvents();\n } catch (error) {\n if (this.sessionManager) {\n try {\n this.sessionManager.destroy();\n } catch {\n // Ignore cleanup errors\n }\n this.sessionManager = null;\n }\n\n log('error', 'Failed to start session tracking', { error });\n throw error;\n }\n }\n\n private isActive(): boolean {\n return this.sessionManager !== null && !this.destroyed;\n }\n\n private async cleanupSessionManager(): Promise<void> {\n if (this.sessionManager) {\n await this.sessionManager.stopTracking();\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n }\n\n async stopTracking(): Promise<void> {\n await this.cleanupSessionManager();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.sessionManager) {\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n\n this.destroyed = true;\n this.set('hasStartSession', false);\n }\n}\n","import { EventType, PageViewData } from '../types';\nimport { normalizeUrl } from '../utils';\nimport { StateManager } from '../managers/state.manager';\nimport { EventManager } from '../managers/event.manager';\n\nexport class PageViewHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly onTrack: () => void;\n\n private originalPushState?: typeof window.history.pushState;\n private originalReplaceState?: typeof window.history.replaceState;\n\n constructor(eventManager: EventManager, onTrack: () => void) {\n super();\n\n this.eventManager = eventManager;\n this.onTrack = onTrack;\n }\n\n startTracking(): void {\n this.trackInitialPageView();\n\n window.addEventListener('popstate', this.trackCurrentPage, true);\n window.addEventListener('hashchange', this.trackCurrentPage, true);\n\n this.patchHistory('pushState');\n this.patchHistory('replaceState');\n }\n\n stopTracking(): void {\n window.removeEventListener('popstate', this.trackCurrentPage, true);\n window.removeEventListener('hashchange', this.trackCurrentPage, true);\n\n if (this.originalPushState) {\n window.history.pushState = this.originalPushState;\n }\n\n if (this.originalReplaceState) {\n window.history.replaceState = this.originalReplaceState;\n }\n }\n\n private patchHistory(method: 'pushState' | 'replaceState'): void {\n const original = window.history[method];\n\n if (method === 'pushState' && !this.originalPushState) {\n this.originalPushState = original;\n } else if (method === 'replaceState' && !this.originalReplaceState) {\n this.originalReplaceState = original;\n }\n\n window.history[method] = (...args: [unknown, string, string | URL | null | undefined]): void => {\n original.apply(window.history, args);\n this.trackCurrentPage();\n };\n }\n\n private readonly trackCurrentPage = async (): Promise<void> => {\n const rawUrl = window.location.href;\n const normalizedUrl = normalizeUrl(rawUrl, this.get('config').sensitiveQueryParams);\n\n if (this.get('pageUrl') === normalizedUrl) {\n return;\n }\n\n this.onTrack();\n\n const fromUrl = this.get('pageUrl');\n\n this.set('pageUrl', normalizedUrl);\n\n const pageViewData = this.extractPageViewData();\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: this.get('pageUrl'),\n from_page_url: fromUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n };\n\n private trackInitialPageView(): void {\n const normalizedUrl = normalizeUrl(window.location.href, this.get('config').sensitiveQueryParams);\n const pageViewData = this.extractPageViewData();\n\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: normalizedUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n\n this.onTrack();\n }\n\n private extractPageViewData(): PageViewData | undefined {\n const { pathname, search, hash } = window.location;\n const { referrer } = document;\n const { title } = document;\n\n // Early return if no meaningful data\n if (!referrer && !title && !pathname && !search && !hash) {\n return undefined;\n }\n\n const data: PageViewData = {\n ...(referrer && { referrer }),\n ...(title && { title }),\n ...(pathname && { pathname }),\n ...(search && { search }),\n ...(hash && { hash }),\n };\n\n return data;\n }\n}\n","import { HTML_DATA_ATTR_PREFIX, MAX_TEXT_LENGTH, INTERACTIVE_SELECTORS } from '../constants';\nimport { ClickCoordinates, ClickData, ClickTrackingElementData, EventType } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\nexport class ClickHandler extends StateManager {\n private readonly eventManager: EventManager;\n\n private clickHandler?: (event: Event) => void;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n if (this.clickHandler) {\n return;\n }\n\n this.clickHandler = (event: Event): void => {\n const mouseEvent = event as MouseEvent;\n const target = mouseEvent.target as EventTarget | null;\n const clickedElement =\n typeof HTMLElement !== 'undefined' && target instanceof HTMLElement\n ? target\n : typeof HTMLElement !== 'undefined' && target instanceof Node && target.parentElement instanceof HTMLElement\n ? target.parentElement\n : null;\n\n if (!clickedElement) {\n log('warn', 'Click target not found or not an element');\n return;\n }\n\n const trackingElement = this.findTrackingElement(clickedElement);\n const relevantClickElement = this.getRelevantClickElement(clickedElement);\n const coordinates = this.calculateClickCoordinates(mouseEvent, clickedElement);\n\n if (trackingElement) {\n const trackingData = this.extractTrackingData(trackingElement);\n\n if (trackingData) {\n const attributeData = this.createCustomEventData(trackingData);\n\n this.eventManager.track({\n type: EventType.CUSTOM,\n custom_event: {\n name: attributeData.name,\n ...(attributeData.value && { metadata: { value: attributeData.value } }),\n },\n });\n }\n }\n\n const clickData = this.generateClickData(clickedElement, relevantClickElement, coordinates);\n\n this.eventManager.track({\n type: EventType.CLICK,\n click_data: clickData,\n });\n };\n\n window.addEventListener('click', this.clickHandler, true);\n }\n\n stopTracking(): void {\n if (this.clickHandler) {\n window.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = undefined;\n }\n }\n\n private findTrackingElement(element: HTMLElement): HTMLElement | undefined {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-name`)) {\n return element;\n }\n\n const closest = element.closest(`[${HTML_DATA_ATTR_PREFIX}-name]`) as HTMLElement;\n\n return closest || undefined;\n }\n\n private getRelevantClickElement(element: HTMLElement): HTMLElement {\n for (const selector of INTERACTIVE_SELECTORS) {\n try {\n if (element.matches(selector)) {\n return element;\n }\n\n const parent = element.closest(selector) as HTMLElement;\n if (parent) {\n return parent;\n }\n } catch (error) {\n log('warn', 'Invalid selector in element search', { error, data: { selector } });\n continue;\n }\n }\n\n return element;\n }\n\n private clamp(value: number): number {\n return Math.max(0, Math.min(1, Number(value.toFixed(3))));\n }\n\n private calculateClickCoordinates(event: MouseEvent, element: HTMLElement): ClickCoordinates {\n const rect = element.getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n const relativeX = rect.width > 0 ? this.clamp((x - rect.left) / rect.width) : 0;\n const relativeY = rect.height > 0 ? this.clamp((y - rect.top) / rect.height) : 0;\n\n return { x, y, relativeX, relativeY };\n }\n\n private extractTrackingData(trackingElement: HTMLElement): ClickTrackingElementData | undefined {\n const name = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n const value = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-value`);\n\n if (!name) {\n return undefined;\n }\n\n return {\n element: trackingElement,\n name,\n ...(value && { value }),\n };\n }\n\n private generateClickData(\n clickedElement: HTMLElement,\n relevantElement: HTMLElement,\n coordinates: ClickCoordinates,\n ): ClickData {\n const { x, y, relativeX, relativeY } = coordinates;\n const text = this.getRelevantText(clickedElement, relevantElement);\n const attributes = this.extractElementAttributes(relevantElement);\n\n return {\n x,\n y,\n relativeX,\n relativeY,\n tag: relevantElement.tagName.toLowerCase(),\n ...(relevantElement.id && { id: relevantElement.id }),\n ...(relevantElement.className && { class: relevantElement.className }),\n ...(text && { text }),\n ...(attributes.href && { href: attributes.href }),\n ...(attributes.title && { title: attributes.title }),\n ...(attributes.alt && { alt: attributes.alt }),\n ...(attributes.role && { role: attributes.role }),\n ...(attributes['aria-label'] && { ariaLabel: attributes['aria-label'] }),\n ...(Object.keys(attributes).length > 0 && { dataAttributes: attributes }),\n };\n }\n\n private getRelevantText(clickedElement: HTMLElement, relevantElement: HTMLElement): string {\n const clickedText = clickedElement.textContent?.trim() ?? '';\n const relevantText = relevantElement.textContent?.trim() ?? '';\n\n if (!clickedText && !relevantText) {\n return '';\n }\n\n if (clickedText && clickedText.length <= MAX_TEXT_LENGTH) {\n return clickedText;\n }\n\n if (relevantText.length <= MAX_TEXT_LENGTH) {\n return relevantText;\n }\n\n return relevantText.slice(0, MAX_TEXT_LENGTH - 3) + '...';\n }\n\n private extractElementAttributes(element: HTMLElement): Record<string, string> {\n const commonAttributes = [\n 'id',\n 'class',\n 'data-testid',\n 'aria-label',\n 'title',\n 'href',\n 'type',\n 'name',\n 'alt',\n 'role',\n ];\n const result: Record<string, string> = {};\n\n for (const attributeName of commonAttributes) {\n const value = element.getAttribute(attributeName);\n\n if (value) {\n result[attributeName] = value;\n }\n }\n\n return result;\n }\n\n private createCustomEventData(trackingData: ClickTrackingElementData): { name: string; value?: string } {\n return {\n name: trackingData.name,\n ...(trackingData.value && { value: trackingData.value }),\n };\n }\n}\n","import {\n MAX_SCROLL_EVENTS_PER_SESSION,\n MIN_SCROLL_DEPTH_CHANGE,\n SCROLL_DEBOUNCE_TIME_MS,\n SCROLL_MIN_EVENT_INTERVAL_MS,\n SIGNIFICANT_SCROLL_DELTA,\n} from '../constants';\nimport { EventType, ScrollData, ScrollDirection } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\ninterface ScrollContainer {\n element: Window | HTMLElement;\n lastScrollPos: number;\n lastDepth: number;\n lastDirection: ScrollDirection;\n lastEventTime: number;\n debounceTimer: number | null;\n listener: EventListener;\n}\n\nexport class ScrollHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly containers: ScrollContainer[] = [];\n private limitWarningLogged = false;\n private minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n private minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n private maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n this.limitWarningLogged = false;\n this.applyConfigOverrides();\n this.set('scrollEventCount', 0);\n\n const raw = this.get('config').scrollContainerSelectors;\n const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];\n\n if (selectors.length === 0) {\n this.setupScrollContainer(window);\n } else {\n this.trySetupContainers(selectors, 0);\n }\n }\n\n stopTracking(): void {\n for (const container of this.containers) {\n this.clearContainerTimer(container);\n\n if (container.element instanceof Window) {\n window.removeEventListener('scroll', container.listener);\n } else {\n container.element.removeEventListener('scroll', container.listener);\n }\n }\n\n this.containers.length = 0;\n this.set('scrollEventCount', 0);\n this.limitWarningLogged = false;\n }\n\n private trySetupContainers(selectors: string[], attempt: number): void {\n const elements: HTMLElement[] = selectors\n .map((sel) => this.safeQuerySelector(sel))\n .filter(\n (element): element is HTMLElement =>\n element != null && typeof HTMLElement !== 'undefined' && element instanceof HTMLElement,\n );\n\n if (elements.length > 0) {\n for (const element of elements) {\n const isAlreadyTracking = this.containers.some((c) => c.element === element);\n\n if (!isAlreadyTracking) {\n this.setupScrollContainer(element);\n }\n }\n\n return;\n }\n\n if (attempt < 5) {\n setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);\n return;\n }\n\n if (this.containers.length === 0) {\n this.setupScrollContainer(window);\n }\n }\n\n private setupScrollContainer(element: Window | HTMLElement): void {\n if (element !== window && !this.isElementScrollable(element as HTMLElement)) {\n return;\n }\n\n const handleScroll = (): void => {\n if (this.get('suppressNextScroll')) {\n return;\n }\n\n this.clearContainerTimer(container);\n\n container.debounceTimer = window.setTimeout(() => {\n const scrollData = this.calculateScrollData(container);\n\n if (scrollData) {\n const now = Date.now();\n\n this.processScrollEvent(container, scrollData, now);\n }\n\n container.debounceTimer = null;\n }, SCROLL_DEBOUNCE_TIME_MS);\n };\n\n const initialScrollTop = this.getScrollTop(element);\n const container: ScrollContainer = {\n element,\n lastScrollPos: initialScrollTop,\n lastDepth: this.calculateScrollDepth(\n initialScrollTop,\n this.getScrollHeight(element),\n this.getViewportHeight(element),\n ),\n lastDirection: ScrollDirection.DOWN,\n lastEventTime: 0,\n debounceTimer: null,\n listener: handleScroll,\n };\n\n this.containers.push(container);\n\n if (element instanceof Window) {\n window.addEventListener('scroll', handleScroll, { passive: true });\n } else {\n element.addEventListener('scroll', handleScroll, { passive: true });\n }\n }\n\n private processScrollEvent(container: ScrollContainer, scrollData: ScrollData, timestamp: number): void {\n if (!this.shouldEmitScrollEvent(container, scrollData, timestamp)) {\n return;\n }\n\n container.lastEventTime = timestamp;\n container.lastDepth = scrollData.depth;\n container.lastDirection = scrollData.direction;\n\n const currentCount = this.get('scrollEventCount') ?? 0;\n this.set('scrollEventCount', currentCount + 1);\n\n this.eventManager.track({\n type: EventType.SCROLL,\n scroll_data: scrollData,\n });\n }\n\n private shouldEmitScrollEvent(container: ScrollContainer, scrollData: ScrollData, timestamp: number): boolean {\n if (this.hasReachedSessionLimit()) {\n this.logLimitOnce();\n return false;\n }\n\n if (!this.hasElapsedMinimumInterval(container, timestamp)) {\n return false;\n }\n\n if (!this.hasSignificantDepthChange(container, scrollData.depth)) {\n return false;\n }\n\n return true;\n }\n\n private hasReachedSessionLimit(): boolean {\n const currentCount = this.get('scrollEventCount') ?? 0;\n return currentCount >= this.maxEventsPerSession;\n }\n\n private hasElapsedMinimumInterval(container: ScrollContainer, timestamp: number): boolean {\n if (container.lastEventTime === 0) {\n return true;\n }\n return timestamp - container.lastEventTime >= this.minIntervalMs;\n }\n\n private hasSignificantDepthChange(container: ScrollContainer, newDepth: number): boolean {\n return Math.abs(newDepth - container.lastDepth) >= this.minDepthChange;\n }\n\n private logLimitOnce(): void {\n if (this.limitWarningLogged) {\n return;\n }\n\n this.limitWarningLogged = true;\n\n log('warn', 'Max scroll events per session reached', {\n data: { limit: this.maxEventsPerSession },\n });\n }\n\n private applyConfigOverrides(): void {\n this.minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n this.minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n this.maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n }\n\n private isWindowScrollable(): boolean {\n return document.documentElement.scrollHeight > window.innerHeight;\n }\n\n private clearContainerTimer(container: ScrollContainer): void {\n if (container.debounceTimer !== null) {\n clearTimeout(container.debounceTimer);\n container.debounceTimer = null;\n }\n }\n\n private getScrollDirection(current: number, previous: number): ScrollDirection {\n return current > previous ? ScrollDirection.DOWN : ScrollDirection.UP;\n }\n\n private calculateScrollDepth(scrollTop: number, scrollHeight: number, viewportHeight: number): number {\n if (scrollHeight <= viewportHeight) {\n return 0;\n }\n\n const maxScrollTop = scrollHeight - viewportHeight;\n return Math.min(100, Math.max(0, Math.floor((scrollTop / maxScrollTop) * 100)));\n }\n\n private calculateScrollData(container: ScrollContainer): ScrollData | null {\n const { element, lastScrollPos } = container;\n const scrollTop = this.getScrollTop(element);\n\n const positionDelta = Math.abs(scrollTop - lastScrollPos);\n if (positionDelta < SIGNIFICANT_SCROLL_DELTA) {\n return null;\n }\n\n if (element === window && !this.isWindowScrollable()) {\n return null;\n }\n\n const viewportHeight = this.getViewportHeight(element);\n const scrollHeight = this.getScrollHeight(element);\n const direction = this.getScrollDirection(scrollTop, lastScrollPos);\n const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);\n\n container.lastScrollPos = scrollTop;\n\n return { depth, direction };\n }\n\n private getScrollTop(element: Window | HTMLElement): number {\n return element instanceof Window ? window.scrollY : element.scrollTop;\n }\n\n private getViewportHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? window.innerHeight : element.clientHeight;\n }\n\n private getScrollHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? document.documentElement.scrollHeight : element.scrollHeight;\n }\n\n private isElementScrollable(element: HTMLElement): boolean {\n const style = getComputedStyle(element);\n const hasScrollableOverflow =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflowX === 'auto' ||\n style.overflowX === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n const hasOverflowContent = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;\n\n return hasScrollableOverflow && hasOverflowContent;\n }\n\n private safeQuerySelector(selector: string): HTMLElement | null {\n try {\n return document.querySelector(selector);\n } catch (error) {\n log('warn', 'Invalid CSS selector', {\n error,\n data: { selector },\n showToClient: true,\n });\n\n return null;\n }\n }\n}\n","import { MetadataType } from '../types';\nimport { log } from '../utils';\nimport { StateManager } from '../managers/state.manager';\n\ndeclare global {\n interface Window {\n gtag?: (...args: unknown[]) => void;\n dataLayer?: unknown[];\n }\n}\n\nexport class GoogleAnalyticsIntegration extends StateManager {\n private isInitialized = false;\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n const measurementId = this.get('config').integrations?.googleAnalytics?.measurementId;\n const userId = this.get('userId');\n\n if (!measurementId?.trim() || !userId?.trim()) {\n return;\n }\n\n try {\n if (this.isScriptAlreadyLoaded()) {\n this.isInitialized = true;\n return;\n }\n\n await this.loadScript(measurementId);\n this.configureGtag(measurementId, userId);\n this.isInitialized = true;\n } catch (error) {\n log('error', 'Google Analytics initialization failed', { error });\n }\n }\n\n trackEvent(eventName: string, metadata: Record<string, MetadataType> | Record<string, MetadataType>[]): void {\n if (!eventName?.trim() || !this.isInitialized || typeof window.gtag !== 'function') {\n return;\n }\n\n try {\n const normalizedMetadata = Array.isArray(metadata) ? { items: metadata } : metadata;\n window.gtag('event', eventName, normalizedMetadata);\n } catch (error) {\n log('error', 'Google Analytics event tracking failed', { error });\n }\n }\n\n cleanup(): void {\n this.isInitialized = false;\n const script = document.getElementById('tracelog-ga-script');\n if (script) {\n script.remove();\n }\n }\n\n private isScriptAlreadyLoaded(): boolean {\n // Check if we already loaded the script\n if (document.getElementById('tracelog-ga-script')) {\n return true;\n }\n\n // Check if GA is already loaded by another source\n const existingGAScript = document.querySelector('script[src*=\"googletagmanager.com/gtag/js\"]');\n return !!existingGAScript;\n }\n\n private async loadScript(measurementId: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.id = 'tracelog-ga-script';\n script.async = true;\n script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('Failed to load Google Analytics script'));\n\n document.head.appendChild(script);\n });\n }\n\n private configureGtag(measurementId: string, userId: string): void {\n const gaScriptConfig = document.createElement('script');\n gaScriptConfig.innerHTML = `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${measurementId}', {\n 'user_id': '${userId}'\n });\n `;\n document.head.appendChild(gaScriptConfig);\n }\n}\n","import { log } from '../utils';\n\n/**\n * Manages localStorage and sessionStorage with automatic fallback to in-memory storage.\n * Provides a consistent interface for storing session data, configuration,\n * and analytics metadata across browser environments.\n */\nexport class StorageManager {\n private readonly storage: Storage | null;\n private readonly sessionStorageRef: Storage | null;\n private readonly fallbackStorage = new Map<string, string>();\n private readonly fallbackSessionStorage = new Map<string, string>();\n\n private hasQuotaExceededError = false;\n\n constructor() {\n this.storage = this.initializeStorage('localStorage');\n this.sessionStorageRef = this.initializeStorage('sessionStorage');\n\n if (!this.storage) {\n log('warn', 'localStorage not available, using memory fallback');\n }\n if (!this.sessionStorageRef) {\n log('warn', 'sessionStorage not available, using memory fallback');\n }\n }\n\n /**\n * Retrieves an item from storage\n */\n getItem(key: string): string | null {\n try {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n return this.fallbackStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in storage\n */\n setItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n // This ensures fallback is in sync and can serve as backup if storage fails\n this.fallbackStorage.set(key, value);\n\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n this.hasQuotaExceededError = true;\n\n log('warn', 'localStorage quota exceeded, attempting cleanup', {\n data: { key, valueSize: value.length },\n });\n\n // Attempt to free up space by removing old TraceLog data\n const cleanedUp = this.cleanupOldData();\n\n if (cleanedUp) {\n // Retry after cleanup\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n // Successfully stored after cleanup\n return;\n }\n } catch (retryError) {\n log('error', 'localStorage quota exceeded even after cleanup - data will not persist', {\n error: retryError,\n data: { key, valueSize: value.length },\n });\n }\n } else {\n log('error', 'localStorage quota exceeded and no data to cleanup - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from storage\n */\n removeItem(key: string): void {\n try {\n if (this.storage) {\n this.storage.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackStorage.delete(key);\n }\n\n /**\n * Clears all TracLog-related items from storage\n */\n clear(): void {\n if (!this.storage) {\n this.fallbackStorage.clear();\n return;\n }\n\n try {\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => this.storage!.removeItem(key));\n this.fallbackStorage.clear();\n } catch (error) {\n log('error', 'Failed to clear storage', { error });\n this.fallbackStorage.clear();\n }\n }\n\n /**\n * Checks if storage is available\n */\n isAvailable(): boolean {\n return this.storage !== null;\n }\n\n /**\n * Checks if a QuotaExceededError has occurred\n * This indicates localStorage is full and data may not persist\n */\n hasQuotaError(): boolean {\n return this.hasQuotaExceededError;\n }\n\n /**\n * Attempts to cleanup old TraceLog data from storage to free up space\n * Returns true if any data was removed, false otherwise\n */\n private cleanupOldData(): boolean {\n if (!this.storage) {\n return false;\n }\n\n try {\n const tracelogKeys: string[] = [];\n const persistedEventsKeys: string[] = [];\n\n // Collect all TraceLog keys\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n tracelogKeys.push(key);\n\n // Prioritize removing old persisted events\n if (key.startsWith('tracelog_persisted_events_')) {\n persistedEventsKeys.push(key);\n }\n }\n }\n\n // First, try to remove old persisted events (usually the largest data)\n if (persistedEventsKeys.length > 0) {\n persistedEventsKeys.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n // If no persisted events, remove non-critical keys\n // Define critical key prefixes that should be preserved\n const criticalPrefixes = ['tracelog_session_', 'tracelog_user_id', 'tracelog_device_id', 'tracelog_config'];\n\n const nonCriticalKeys = tracelogKeys.filter((key) => {\n // Keep keys that start with any critical prefix\n return !criticalPrefixes.some((prefix) => key.startsWith(prefix));\n });\n\n if (nonCriticalKeys.length > 0) {\n // Remove up to 5 non-critical keys\n const keysToRemove = nonCriticalKeys.slice(0, 5);\n keysToRemove.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n return false;\n } catch (error) {\n log('error', 'Failed to cleanup old data', { error });\n return false;\n }\n }\n\n /**\n * Initialize storage (localStorage or sessionStorage) with feature detection\n */\n private initializeStorage(type: 'localStorage' | 'sessionStorage'): Storage | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const storage = type === 'localStorage' ? window.localStorage : window.sessionStorage;\n const testKey = '__tracelog_test__';\n\n storage.setItem(testKey, 'test');\n storage.removeItem(testKey);\n\n return storage;\n } catch {\n return null;\n }\n }\n\n /**\n * Retrieves an item from sessionStorage\n */\n getSessionItem(key: string): string | null {\n try {\n if (this.sessionStorageRef) {\n return this.sessionStorageRef.getItem(key);\n }\n return this.fallbackSessionStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackSessionStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in sessionStorage\n */\n setSessionItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n this.fallbackSessionStorage.set(key, value);\n\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n log('error', 'sessionStorage quota exceeded - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackSessionStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from sessionStorage\n */\n removeSessionItem(key: string): void {\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackSessionStorage.delete(key);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, WebVitalType } from '../types';\nimport { LONG_TASK_THROTTLE_MS, PRECISION_TWO_DECIMALS, WEB_VITALS_THRESHOLDS } from '../constants';\nimport { log } from '../utils';\n\ntype LayoutShiftEntry = PerformanceEntry & { value?: number; hadRecentInput?: boolean };\n\nexport class PerformanceHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly reportedByNav: Map<string, Set<string>> = new Map();\n\n private readonly observers: PerformanceObserver[] = [];\n private lastLongTaskSentAt = 0;\n\n private readonly vitalThresholds = WEB_VITALS_THRESHOLDS;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n async startTracking(): Promise<void> {\n await this.initWebVitals();\n this.observeLongTasks();\n }\n\n stopTracking(): void {\n this.observers.forEach((obs, index) => {\n try {\n obs.disconnect();\n } catch (error) {\n log('warn', 'Failed to disconnect performance observer', { error, data: { observerIndex: index } });\n }\n });\n\n this.observers.length = 0;\n this.reportedByNav.clear();\n }\n\n private observeWebVitalsFallback(): void {\n // TTFB - should be captured immediately as it's available from navigation timing\n this.reportTTFB();\n\n // LCP\n this.safeObserve(\n 'largest-contentful-paint',\n (list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1] as (PerformanceEntry & { startTime: number }) | undefined;\n\n if (!last) {\n return;\n }\n\n this.sendVital({ type: 'LCP', value: Number(last.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'largest-contentful-paint', buffered: true },\n true,\n );\n\n // CLS (layout-shift)\n let clsValue = 0;\n let currentNavId = this.getNavigationId();\n\n this.safeObserve(\n 'layout-shift',\n (list) => {\n const navId = this.getNavigationId();\n\n // Reset CLS on navigation change\n if (navId !== currentNavId) {\n clsValue = 0;\n currentNavId = navId;\n }\n\n const entries = list.getEntries() as LayoutShiftEntry[];\n\n for (const entry of entries) {\n if (entry.hadRecentInput === true) {\n continue;\n }\n\n const value = typeof entry.value === 'number' ? entry.value : 0;\n clsValue += value;\n }\n\n this.sendVital({ type: 'CLS', value: Number(clsValue.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'layout-shift', buffered: true },\n );\n\n // FCP\n this.safeObserve(\n 'paint',\n (list) => {\n for (const entry of list.getEntries()) {\n if (entry.name === 'first-contentful-paint') {\n this.sendVital({ type: 'FCP', value: Number(entry.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n }\n },\n { type: 'paint', buffered: true },\n true,\n );\n\n // INP via performance event timing (where supported)\n this.safeObserve(\n 'event',\n (list) => {\n let worst = 0;\n const entries = list.getEntries() as Array<{ startTime: number; processingEnd?: number }>;\n\n for (const entry of entries) {\n const dur = (entry.processingEnd ?? 0) - (entry.startTime ?? 0);\n worst = Math.max(worst, dur);\n }\n\n if (worst > 0) {\n this.sendVital({ type: 'INP', value: Number(worst.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n },\n { type: 'event', buffered: true },\n );\n }\n\n private async initWebVitals(): Promise<void> {\n try {\n const { onLCP, onCLS, onFCP, onTTFB, onINP } = await import('web-vitals');\n\n const report =\n (type: WebVitalType) =>\n (metric: { value: number }): void => {\n const value = Number(metric.value.toFixed(PRECISION_TWO_DECIMALS));\n this.sendVital({ type, value });\n };\n\n onLCP(report('LCP'));\n onCLS(report('CLS'));\n onFCP(report('FCP'));\n onTTFB(report('TTFB'));\n onINP(report('INP'));\n } catch (error) {\n log('warn', 'Failed to load web-vitals library, using fallback', { error });\n this.observeWebVitalsFallback();\n }\n }\n\n private reportTTFB(): void {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return;\n }\n\n const ttfb = nav.responseStart;\n\n // TTFB can be 0 in some browsers (especially Mobile Safari) when:\n // - Response is served from cache\n // - Connection is reused\n // - Browser cannot determine exact timing\n // We still report it as it's a valid measurement\n if (typeof ttfb === 'number' && Number.isFinite(ttfb)) {\n this.sendVital({ type: 'TTFB', value: Number(ttfb.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n } catch (error) {\n log('warn', 'Failed to report TTFB', { error });\n }\n }\n\n private observeLongTasks(): void {\n this.safeObserve(\n 'longtask',\n (list) => {\n const entries = list.getEntries() as Array<{ duration: number }>;\n\n for (const entry of entries) {\n const duration = Number(entry.duration.toFixed(PRECISION_TWO_DECIMALS));\n const now = Date.now();\n\n if (now - this.lastLongTaskSentAt >= LONG_TASK_THROTTLE_MS) {\n if (this.shouldSendVital('LONG_TASK', duration)) {\n this.trackWebVital('LONG_TASK', duration);\n }\n this.lastLongTaskSentAt = now;\n }\n }\n },\n { type: 'longtask', buffered: true },\n );\n }\n\n private sendVital(sample: { type: WebVitalType; value: number }): void {\n if (!this.shouldSendVital(sample.type, sample.value)) {\n return;\n }\n\n const navId = this.getNavigationId();\n\n // Check for duplicates if we have a navigation ID\n if (navId) {\n const reportedForNav = this.reportedByNav.get(navId);\n const isDuplicate = reportedForNav?.has(sample.type);\n\n if (isDuplicate) {\n return;\n }\n\n // Initialize or update reported vitals for this navigation\n if (!reportedForNav) {\n this.reportedByNav.set(navId, new Set([sample.type]));\n } else {\n reportedForNav.add(sample.type);\n }\n }\n\n this.trackWebVital(sample.type, sample.value);\n }\n\n private trackWebVital(type: WebVitalType, value: number): void {\n if (!Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return;\n }\n\n this.eventManager.track({\n type: EventType.WEB_VITALS,\n web_vitals: {\n type,\n value,\n },\n });\n }\n\n private getNavigationId(): string | null {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return null;\n }\n\n // Use more precise timestamp and add random component to prevent collisions\n const timestamp = nav.startTime || performance.now();\n const random = Math.random().toString(36).substr(2, 5);\n return `${timestamp.toFixed(2)}_${window.location.pathname}_${random}`;\n } catch (error) {\n log('warn', 'Failed to get navigation ID', { error });\n return null;\n }\n }\n\n private isObserverSupported(type: string): boolean {\n if (typeof PerformanceObserver === 'undefined') return false;\n const supported = PerformanceObserver.supportedEntryTypes;\n return !supported || supported.includes(type);\n }\n\n private safeObserve(\n type: string,\n cb: PerformanceObserverCallback,\n options?: PerformanceObserverInit,\n once = false,\n ): boolean {\n try {\n if (!this.isObserverSupported(type)) {\n return false;\n }\n\n const obs = new PerformanceObserver((list, observer) => {\n try {\n cb(list, observer);\n } catch (callbackError) {\n log('warn', 'Observer callback failed', {\n error: callbackError,\n data: { type },\n });\n }\n\n if (once) {\n try {\n observer.disconnect();\n } catch {\n // Disconnect errors are safe to ignore\n }\n }\n });\n\n obs.observe(options ?? { type, buffered: true });\n\n if (!once) {\n this.observers.push(obs);\n }\n\n return true;\n } catch (error) {\n log('warn', 'Failed to create performance observer', {\n error,\n data: { type },\n });\n return false;\n }\n }\n\n private shouldSendVital(type: WebVitalType, value?: number): boolean {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return false;\n }\n\n const threshold = this.vitalThresholds[type];\n\n if (typeof threshold === 'number' && value <= threshold) {\n return false;\n }\n\n return true;\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { ErrorType, EventType } from '../types';\nimport {\n PII_PATTERNS,\n MAX_ERROR_MESSAGE_LENGTH,\n ERROR_SUPPRESSION_WINDOW_MS,\n MAX_TRACKED_ERRORS,\n MAX_TRACKED_ERRORS_HARD_LIMIT,\n} from '../constants/error.constants';\n\n/**\n * Simplified error handler for tracking JavaScript errors and unhandled promise rejections\n * Includes PII sanitization and sampling support\n */\nexport class ErrorHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly recentErrors = new Map<string, number>();\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n window.addEventListener('error', this.handleError);\n window.addEventListener('unhandledrejection', this.handleRejection);\n }\n\n stopTracking(): void {\n window.removeEventListener('error', this.handleError);\n window.removeEventListener('unhandledrejection', this.handleRejection);\n this.recentErrors.clear();\n }\n\n private shouldSample(): boolean {\n const config = this.get('config');\n const samplingRate = config?.errorSampling ?? 0.1;\n return Math.random() < samplingRate;\n }\n\n private readonly handleError = (event: ErrorEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const sanitizedMessage = this.sanitize(event.message || 'Unknown error');\n\n if (this.shouldSuppressError(ErrorType.JS_ERROR, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.JS_ERROR,\n message: sanitizedMessage,\n ...(event.filename && { filename: event.filename }),\n ...(event.lineno && { line: event.lineno }),\n ...(event.colno && { column: event.colno }),\n },\n });\n };\n\n private readonly handleRejection = (event: PromiseRejectionEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const message = this.extractRejectionMessage(event.reason);\n const sanitizedMessage = this.sanitize(message);\n\n if (this.shouldSuppressError(ErrorType.PROMISE_REJECTION, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.PROMISE_REJECTION,\n message: sanitizedMessage,\n },\n });\n };\n\n private extractRejectionMessage(reason: unknown): string {\n if (!reason) return 'Unknown rejection';\n\n if (typeof reason === 'string') return reason;\n\n if (reason instanceof Error) {\n return reason.stack ?? reason.message ?? reason.toString();\n }\n\n // Handle objects with message property\n if (typeof reason === 'object' && 'message' in reason) {\n return String(reason.message);\n }\n\n // Try to stringify objects\n try {\n return JSON.stringify(reason);\n } catch {\n return String(reason);\n }\n }\n\n private sanitize(text: string): string {\n let sanitized = text.length > MAX_ERROR_MESSAGE_LENGTH ? text.slice(0, MAX_ERROR_MESSAGE_LENGTH) + '...' : text;\n\n for (const pattern of PII_PATTERNS) {\n // Create new regex instance to avoid global flag state issues\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private shouldSuppressError(type: ErrorType, message: string): boolean {\n const now = Date.now();\n const key = `${type}:${message}`;\n const lastSeenAt = this.recentErrors.get(key);\n\n if (lastSeenAt && now - lastSeenAt < ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.set(key, now);\n return true;\n }\n\n this.recentErrors.set(key, now);\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS_HARD_LIMIT) {\n // Hard limit exceeded, clearing all tracked errors\n this.recentErrors.clear();\n this.recentErrors.set(key, now);\n\n return false;\n }\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS) {\n this.pruneOldErrors();\n }\n\n return false;\n }\n\n private pruneOldErrors(): void {\n const now = Date.now();\n for (const [key, timestamp] of this.recentErrors.entries()) {\n if (now - timestamp > ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.delete(key);\n }\n }\n\n if (this.recentErrors.size <= MAX_TRACKED_ERRORS) {\n return;\n }\n\n const entries = Array.from(this.recentErrors.entries()).sort((a, b) => a[1] - b[1]);\n const excess = this.recentErrors.size - MAX_TRACKED_ERRORS;\n\n for (let index = 0; index < excess; index += 1) {\n const entry = entries[index];\n if (entry) {\n this.recentErrors.delete(entry[0]);\n }\n }\n }\n}\n","import { EventManager } from './managers/event.manager';\nimport { UserManager } from './managers/user.manager';\nimport { StateManager } from './managers/state.manager';\nimport { SessionHandler } from './handlers/session.handler';\nimport { PageViewHandler } from './handlers/page-view.handler';\nimport { ClickHandler } from './handlers/click.handler';\nimport { ScrollHandler } from './handlers/scroll.handler';\nimport { Config, EventType, EmitterCallback, EmitterMap, Mode } from './types';\nimport { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';\nimport { isEventValid, getDeviceType, normalizeUrl, Emitter, getCollectApiUrl, detectQaMode, log } from './utils';\nimport { StorageManager } from './managers/storage.manager';\nimport { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';\nimport { PerformanceHandler } from './handlers/performance.handler';\nimport { ErrorHandler } from './handlers/error.handler';\n\nexport class App extends StateManager {\n private isInitialized = false;\n private suppressNextScrollTimer: number | null = null;\n\n private readonly emitter = new Emitter();\n\n protected managers: {\n storage?: StorageManager;\n event?: EventManager;\n } = {};\n\n protected handlers: {\n session?: SessionHandler;\n pageView?: PageViewHandler;\n click?: ClickHandler;\n scroll?: ScrollHandler;\n performance?: PerformanceHandler;\n error?: ErrorHandler;\n } = {};\n\n protected integrations: {\n googleAnalytics?: GoogleAnalyticsIntegration;\n } = {};\n\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n async init(config: Config = {}): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n this.managers.storage = new StorageManager();\n\n try {\n this.setupState(config);\n await this.setupIntegrations();\n\n this.managers.event = new EventManager(this.managers.storage, this.integrations.googleAnalytics, this.emitter);\n\n await this.initializeHandlers();\n\n await this.managers.event.recoverPersistedEvents().catch((error) => {\n log('warn', 'Failed to recover persisted events', { error });\n });\n\n this.isInitialized = true;\n } catch (error) {\n await this.destroy(true);\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] TraceLog initialization failed: ${errorMessage}`);\n }\n }\n\n sendCustomEvent(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void {\n if (!this.managers.event) {\n return;\n }\n\n const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);\n\n if (!valid) {\n if (this.get('mode') === Mode.QA) {\n throw new Error(`[TraceLog] Custom event \"${name}\" validation failed: ${error}`);\n }\n\n return;\n }\n\n this.managers.event.track({\n type: EventType.CUSTOM,\n custom_event: {\n name,\n ...(sanitizedMetadata && { metadata: sanitizedMetadata }),\n },\n });\n }\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.on(event, callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.off(event, callback);\n }\n\n async destroy(force = false): Promise<void> {\n if (!this.isInitialized && !force) {\n return;\n }\n\n this.integrations.googleAnalytics?.cleanup();\n\n const handlerCleanups = Object.values(this.handlers)\n .filter(Boolean)\n .map(async (handler) => {\n try {\n await handler.stopTracking();\n } catch (error) {\n log('warn', 'Failed to stop tracking', { error });\n }\n });\n\n await Promise.allSettled(handlerCleanups);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n this.suppressNextScrollTimer = null;\n }\n\n this.managers.event?.flushImmediatelySync();\n\n this.managers.event?.stop();\n\n this.emitter.removeAllListeners();\n\n this.set('hasStartSession', false);\n this.set('suppressNextScroll', false);\n this.set('sessionId', null);\n\n this.isInitialized = false;\n this.handlers = {};\n }\n\n private setupState(config: Config = {}): void {\n this.set('config', config);\n\n const userId = UserManager.getId(this.managers.storage as StorageManager);\n this.set('userId', userId);\n\n const collectApiUrl = getCollectApiUrl(config);\n this.set('collectApiUrl', collectApiUrl);\n\n const device = getDeviceType();\n this.set('device', device);\n\n const pageUrl = normalizeUrl(window.location.href, config.sensitiveQueryParams);\n this.set('pageUrl', pageUrl);\n\n const mode = detectQaMode() ? Mode.QA : undefined;\n\n if (mode) {\n this.set('mode', mode);\n }\n }\n\n private async setupIntegrations(): Promise<void> {\n const config = this.get('config');\n const measurementId = config.integrations?.googleAnalytics?.measurementId;\n\n if (measurementId?.trim()) {\n try {\n this.integrations.googleAnalytics = new GoogleAnalyticsIntegration();\n await this.integrations.googleAnalytics.initialize();\n } catch {\n this.integrations.googleAnalytics = undefined;\n }\n }\n }\n\n private async initializeHandlers(): Promise<void> {\n this.handlers.session = new SessionHandler(\n this.managers.storage as StorageManager,\n this.managers.event as EventManager,\n );\n\n await this.handlers.session.startTracking();\n\n const onPageView = (): void => {\n this.set('suppressNextScroll', true);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n }\n\n this.suppressNextScrollTimer = window.setTimeout(() => {\n this.set('suppressNextScroll', false);\n }, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESS_MULTIPLIER);\n };\n\n this.handlers.pageView = new PageViewHandler(this.managers.event as EventManager, onPageView);\n this.handlers.pageView.startTracking();\n\n this.handlers.click = new ClickHandler(this.managers.event as EventManager);\n this.handlers.click.startTracking();\n\n this.handlers.scroll = new ScrollHandler(this.managers.event as EventManager);\n this.handlers.scroll.startTracking();\n\n this.handlers.performance = new PerformanceHandler(this.managers.event as EventManager);\n this.handlers.performance.startTracking().catch((error) => {\n log('warn', 'Failed to start performance tracking', { error });\n });\n\n this.handlers.error = new ErrorHandler(this.managers.event as EventManager);\n this.handlers.error.startTracking();\n }\n}\n","import { App } from './app';\nimport { MetadataType, Config, EmitterCallback, EmitterMap } from './types';\nimport { log, validateAndNormalizeConfig } from './utils';\nimport { TestBridge } from './test-bridge';\nimport { INITIALIZATION_TIMEOUT_MS } from './constants';\nimport './types/window.types';\n\ninterface PendingListener {\n event: keyof EmitterMap;\n callback: EmitterCallback<EmitterMap[keyof EmitterMap]>;\n}\n\n// Buffer for listeners registered before init()\nconst pendingListeners: PendingListener[] = [];\n\nlet app: App | null = null;\nlet isInitializing = false;\nlet isDestroying = false;\n\nexport const init = async (config?: Config): Promise<void> => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[TraceLog] This library can only be used in a browser environment');\n }\n\n if (window.__traceLogDisabled) {\n return;\n }\n\n if (app) {\n return;\n }\n\n if (isInitializing) {\n return;\n }\n\n isInitializing = true;\n\n try {\n const validatedConfig = validateAndNormalizeConfig(config ?? {});\n const instance = new App();\n\n try {\n // Attach buffered listeners BEFORE init() so they capture initial events\n pendingListeners.forEach(({ event, callback }) => {\n instance.on(event, callback as EmitterCallback<EmitterMap[typeof event]>);\n });\n pendingListeners.length = 0;\n\n // Wrap initialization with timeout using Promise.race\n const initPromise = instance.init(validatedConfig);\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`[TraceLog] Initialization timeout after ${INITIALIZATION_TIMEOUT_MS}ms`));\n }, INITIALIZATION_TIMEOUT_MS);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n\n app = instance;\n } catch (error) {\n try {\n await instance.destroy(true);\n } catch (cleanupError) {\n log('error', 'Failed to cleanup partially initialized app', { error: cleanupError });\n }\n\n throw error;\n }\n } catch (error) {\n app = null;\n throw error;\n } finally {\n isInitializing = false;\n }\n};\n\nexport const event = (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]): void => {\n if (!app) {\n throw new Error('[TraceLog] TraceLog not initialized. Please call init() first.');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Cannot send events while TraceLog is being destroyed');\n }\n\n app.sendCustomEvent(name, metadata);\n};\n\nexport const on = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (!app || isInitializing) {\n // Buffer listeners registered before or during init()\n pendingListeners.push({ event, callback } as PendingListener);\n return;\n }\n\n app.on(event, callback);\n};\n\nexport const off = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (!app) {\n // Remove from pending listeners if not yet initialized\n const index = pendingListeners.findIndex((l) => l.event === event && l.callback === callback);\n if (index !== -1) {\n pendingListeners.splice(index, 1);\n }\n return;\n }\n\n app.off(event, callback);\n};\n\nexport const isInitialized = (): boolean => {\n return app !== null;\n};\n\nexport const destroy = async (): Promise<void> => {\n if (!app) {\n throw new Error('[TraceLog] App not initialized');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Destroy operation already in progress');\n }\n\n isDestroying = true;\n\n try {\n await app.destroy();\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Clear TestBridge reference in dev mode to prevent stale references\n if (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined' && window.__traceLogBridge) {\n // Don't call destroy on bridge (would cause recursion), just clear reference\n window.__traceLogBridge = undefined as any;\n }\n } catch (error) {\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Log error but don't re-throw - destroy should always complete successfully\n // Applications should be able to tear down TraceLog even if internal cleanup fails\n log('warn', 'Error during destroy, forced cleanup completed', { error });\n } finally {\n isDestroying = false;\n }\n};\n\nif (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined') {\n const injectTestingBridge = (): void => {\n window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectTestingBridge);\n } else {\n injectTestingBridge();\n }\n}\n\n/**\n * Internal sync function - ONLY for TestBridge in development\n *\n * WARNING: This function is internal and should NEVER be called directly.\n * It's only exported for TestBridge synchronization in dev mode.\n *\n * @internal\n */\nexport const __setAppInstance = (instance: App | null): void => {\n if (instance !== null) {\n const hasRequiredMethods =\n typeof instance === 'object' &&\n 'init' in instance &&\n 'destroy' in instance &&\n 'on' in instance &&\n 'off' in instance;\n\n if (!hasRequiredMethods) {\n throw new Error('[TraceLog] Invalid app instance type');\n }\n }\n\n // Prevent overwriting an already initialized app (except when clearing)\n if (app !== null && instance !== null && app !== instance) {\n throw new Error('[TraceLog] Cannot overwrite existing app instance. Call destroy() first.');\n }\n\n app = instance;\n};\n","import { WEB_VITALS_THRESHOLDS } from './constants/performance.constants';\nimport { PII_PATTERNS } from './constants/error.constants';\n\nexport const PERFORMANCE_CONFIG = {\n WEB_VITALS_THRESHOLDS, // Business thresholds for performance analysis\n} as const;\n\nexport const DATA_PROTECTION = {\n PII_PATTERNS, // Patterns for sensitive data protection\n} as const;\n\nexport const ENGAGEMENT_THRESHOLDS = {\n LOW_ACTIVITY_EVENT_COUNT: 50,\n HIGH_ACTIVITY_EVENT_COUNT: 1000,\n MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,\n MIN_EVENTS_FOR_TREND_ANALYSIS: 30,\n BOUNCE_RATE_SESSION_THRESHOLD: 1, // Sessions with 1 page view = bounce\n MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1000,\n MIN_SCROLL_DEPTH_ENGAGEMENT: 25, // 25% scroll depth for engagement\n} as const;\n\nexport const SESSION_ANALYTICS = {\n INACTIVITY_TIMEOUT_MS: 30 * 60 * 1000, // 30min for analytics (vs 15min client)\n SHORT_SESSION_THRESHOLD_MS: 30 * 1000,\n MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1000,\n LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1000,\n MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1000, // Filter outliers\n} as const;\n\nexport const DEVICE_ANALYTICS = {\n MOBILE_MAX_WIDTH: 768,\n TABLET_MAX_WIDTH: 1024,\n MOBILE_PERFORMANCE_FACTOR: 1.5, // Mobile typically 1.5x slower\n TABLET_PERFORMANCE_FACTOR: 1.2,\n} as const;\n\nexport const CONTENT_ANALYTICS = {\n MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,\n MIN_CLICKS_FOR_HOT_ELEMENT: 10, // Popular element threshold\n MIN_SCROLL_COMPLETION_PERCENT: 80, // Page consumption threshold\n MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1000,\n} as const;\n\nexport const INSIGHT_THRESHOLDS = {\n SIGNIFICANT_CHANGE_PERCENT: 20,\n MAJOR_CHANGE_PERCENT: 50,\n MIN_EVENTS_FOR_INSIGHT: 100,\n MIN_SESSIONS_FOR_INSIGHT: 10,\n MIN_CORRELATION_STRENGTH: 0.7, // Strong correlation threshold\n LOW_ERROR_RATE_PERCENT: 1,\n HIGH_ERROR_RATE_PERCENT: 5,\n CRITICAL_ERROR_RATE_PERCENT: 10,\n} as const;\n\nexport const TEMPORAL_ANALYSIS = {\n SHORT_TERM_TREND_HOURS: 24,\n MEDIUM_TERM_TREND_DAYS: 7,\n LONG_TERM_TREND_DAYS: 30,\n MIN_DATA_POINTS_FOR_TREND: 5,\n WEEKLY_PATTERN_MIN_WEEKS: 4,\n DAILY_PATTERN_MIN_DAYS: 14,\n} as const;\n\nexport const SEGMENTATION_ANALYTICS = {\n MIN_SEGMENT_SIZE: 10,\n MIN_COHORT_SIZE: 5,\n COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],\n MIN_FUNNEL_EVENTS: 20,\n} as const;\n\nexport const ANALYTICS_QUERY_LIMITS = {\n DEFAULT_EVENTS_LIMIT: 5,\n DEFAULT_SESSIONS_LIMIT: 5,\n DEFAULT_PAGES_LIMIT: 5,\n MAX_EVENTS_FOR_DEEP_ANALYSIS: 10000,\n MAX_TIME_RANGE_DAYS: 365,\n ANALYTICS_BATCH_SIZE: 1000, // For historical analysis\n} as const;\n\nexport const ANOMALY_DETECTION = {\n ANOMALY_THRESHOLD_SIGMA: 2.5,\n STRONG_ANOMALY_THRESHOLD_SIGMA: 3.0,\n TRAFFIC_DROP_ALERT_PERCENT: -30,\n TRAFFIC_SPIKE_ALERT_PERCENT: 200,\n MIN_BASELINE_DAYS: 7,\n MIN_EVENTS_FOR_ANOMALY_DETECTION: 50,\n} as const;\n\nexport const SPECIAL_PAGE_URLS = {\n PAGE_URL_EXCLUDED: 'excluded',\n PAGE_URL_UNKNOWN: 'unknown',\n} as const;\n","import { init, event, on, off, isInitialized, destroy } from './api';\n\n// Constants\nexport * from './app.constants';\n\n// Types\nexport * from './types';\n\n// TraceLog namespace containing all API methods\nexport const tracelog = {\n init,\n event,\n on,\n off,\n isInitialized,\n destroy,\n};\n","var e,n,t,r,i,o=-1,a=function(e){addEventListener(\"pageshow\",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r=\"navigate\";o>=0?r=\"back-forward-cache\":t&&(document.prerendering||u()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":t.type&&(r=t.type.replace(/_/g,\"-\")));return{name:e,value:void 0===n?-1:n,rating:\"good\",delta:0,entries:[],id:\"v4-\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?\"poor\":e>n[0]?\"needs-improvement\":\"good\"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener(\"visibilitychange\",(function(){\"hidden\"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return\"hidden\"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){\"hidden\"===document.visibilityState&&m>-1&&(m=\"visibilitychange\"===e.type?e.timeStamp:0,T())},y=function(){addEventListener(\"visibilitychange\",g,!0),addEventListener(\"prerenderingchange\",g,!0)},T=function(){removeEventListener(\"visibilitychange\",g,!0),removeEventListener(\"prerenderingchange\",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener(\"prerenderingchange\",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"FCP\"),o=s(\"paint\",(function(e){e.forEach((function(e){\"first-contentful-paint\"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f(\"FCP\"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f(\"CLS\",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s(\"layout-shift\",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f(\"CLS\",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){\"interactionCount\"in performance||e||(e=s(\"event\",M,{type:\"event\",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||\"first-input\"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),\"hidden\"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){\"PerformanceEventTiming\"in self&&\"interactionId\"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f(\"INP\"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s(\"event\",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:\"first-input\",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f(\"INP\"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"LCP\"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s(\"largest-contentful-paint\",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));[\"keydown\",\"click\"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f(\"LCP\"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):\"complete\"!==document.readyState?addEventListener(\"load\",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f(\"TTFB\"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f(\"TTFB\",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:\"first-input\",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;\"pointerdown\"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener(\"pointerup\",t,U),removeEventListener(\"pointercancel\",r,U)};addEventListener(\"pointerup\",t,U),addEventListener(\"pointercancel\",r,U)}(n,e):W(n,e)}},Z=function(e){[\"mousedown\",\"keydown\",\"touchstart\",\"pointerdown\"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f(\"FID\"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s(\"first-input\",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f(\"FID\"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};\n"],"names":["HTML_DATA_ATTR_PREFIX","INTERACTIVE_SELECTORS","UTM_PARAMS","VALIDATION_MESSAGES","XSS_PATTERNS","SpecialApiUrl","DeviceType","EmitterEvent","EventType","ScrollDirection","ErrorType","Mode","TraceLogValidationError","message","errorCode","layer","AppConfigValidationError","SessionTimeoutValidationError","SamplingRateValidationError","IntegrationValidationError","InitializationTimeoutError","timeoutMs","formatLogMsg","msg","error","sanitizedMessage","log","type","extra","data","showToClient","formattedMsg","method","sanitizedData","sanitizeLogData","sanitized","sensitiveKeys","key","value","lowerKey","sensitiveKey","coarsePointerQuery","noHoverQuery","initMediaQueries","getDeviceType","nav","width","hasCoarsePointer","hasNoHover","hasTouchSupport","ua","isMobileUA","isTabletUA","STORAGE_BASE_KEY","QA_MODE_KEY","USER_ID_KEY","QUEUE_KEY","id","SESSION_STORAGE_KEY","BROADCAST_CHANNEL_NAME","WEB_VITALS_THRESHOLDS","LONG_TASK_THROTTLE_MS","PII_PATTERNS","MAX_ERROR_MESSAGE_LENGTH","ERROR_SUPPRESSION_WINDOW_MS","MAX_TRACKED_ERRORS","MAX_TRACKED_ERRORS_HARD_LIMIT","QA_MODE_PARAM","QA_MODE_VALUE","detectQaMode","params","isQaMode","newSearch","newUrl","getUTMParameters","urlParams","utmParams","param","generateUUID","c","r","generateEventId","timestamp","random","bytes","b","isValidUrl","url","allowHttp","parsed","isHttps","isHttp","getCollectApiUrl","config","parts","projectId","cleanDomain","collectApiUrl","normalizeUrl","sensitiveQueryParams","urlObject","searchParams","hasChanged","removedParams","sanitizeString","xssPatternMatches","pattern","beforeReplace","sanitizeValue","depth","item","sanitizedObject","limitedEntries","value_","sanitizedKey","sanitizedValue","sanitizeMetadata","metadata","errorMessage","validateAppConfig","validateScrollContainerSelectors","validateIntegrations","isValidCssSelectorSyntax","selector","parenthesesCount","char","bracketsCount","selectors","selectorsArray","integrations","validateAndNormalizeConfig","normalizedConfig","isValidArrayItem","entries","isOnlyPrimitiveFields","object","isValidEventName","eventName","validateSingleMetadata","sanitizedMetadata","intro","jsonString","isValidMetadata","sanitizedArray","itemValidation","isEventValid","nameValidation","metadataValidation","Emitter","event","callback","callbacks","index","globalState","StateManager","SenderManager","storeManager","userId","body","success","persistedData","payload","controller","timeoutId","response","blob","enrichedBody","storageKey","persistedDataString","originalCallbacks","retryDelay","delay","resolve","EventManager","googleAnalytics","emitter","_eventCount","recoveredEvents","eventIds","e","page_url","from_page_url","scroll_data","click_data","custom_event","web_vitals","error_data","session_end_reason","isCriticalEvent","eventType","isSessionStart","currentPageUrl","currentSessionId","bufferedEvents","isSync","eventsToSend","eventMap","order","signature","events","a","now","fingerprint","x","y","nonCriticalIndex","removedEvent","samplingRate","eventIdSet","eventData","queue","UserManager","storageManager","storedUserId","newUserId","SessionManager","eventManager","action","sessionId","messageProjectId","reason","storedSession","sessionTimeout","lastActivity","storedData","session","recoveredSessionId","isRecovered","finalize","SessionHandler","PageViewHandler","onTrack","original","args","rawUrl","normalizedUrl","fromUrl","pageViewData","pathname","search","hash","referrer","title","ClickHandler","mouseEvent","target","clickedElement","trackingElement","relevantClickElement","coordinates","trackingData","attributeData","clickData","element","parent","rect","relativeX","relativeY","name","relevantElement","text","attributes","clickedText","relevantText","commonAttributes","result","attributeName","ScrollHandler","raw","container","attempt","elements","sel","handleScroll","scrollData","initialScrollTop","currentCount","newDepth","current","previous","scrollTop","scrollHeight","viewportHeight","maxScrollTop","lastScrollPos","direction","style","hasScrollableOverflow","hasOverflowContent","GoogleAnalyticsIntegration","measurementId","normalizedMetadata","script","reject","gaScriptConfig","StorageManager","retryError","keysToRemove","i","tracelogKeys","persistedEventsKeys","criticalPrefixes","nonCriticalKeys","prefix","storage","testKey","PerformanceHandler","obs","list","last","clsValue","currentNavId","navId","entry","worst","dur","onLCP","onCLS","onFCP","onTTFB","onINP","webVitals","report","metric","ttfb","duration","sample","reportedForNav","supported","cb","options","once","observer","callbackError","threshold","ErrorHandler","regex","lastSeenAt","excess","App","valid","force","handlerCleanups","handler","device","pageUrl","mode","onPageView","pendingListeners","app","isInitializing","isDestroying","init","validatedConfig","instance","initPromise","timeoutPromise","_","cleanupError","on","off","l","isInitialized","destroy","PERFORMANCE_CONFIG","DATA_PROTECTION","ENGAGEMENT_THRESHOLDS","SESSION_ANALYTICS","DEVICE_ANALYTICS","CONTENT_ANALYTICS","INSIGHT_THRESHOLDS","TEMPORAL_ANALYSIS","SEGMENTATION_ANALYTICS","ANALYTICS_QUERY_LIMITS","ANOMALY_DETECTION","SPECIAL_PAGE_URLS","tracelog","o","n","u","f","s","d","p","v","m","h","g","T","E","C","S","L","w","t","A","I","M","k","F","D","R","B","H","q","O","N","j","z","G","J","K","Q"],"mappings":"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","x_google_ignoreList":[39]}
|