@tracelog/lib 2.10.0 → 3.0.0

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.
@@ -78,66 +78,10 @@ interface InitResult {
78
78
  sessionId: string;
79
79
  }
80
80
 
81
- /**
82
- * Element configuration for viewport tracking with optional identifiers
83
- */
84
- interface ViewportElement {
85
- /**
86
- * CSS selector for the element
87
- * @example '.hero' | '.cta-button' | '#pricing'
88
- */
89
- selector: string;
90
- /**
91
- * Optional unique identifier for analytics
92
- * Used to distinguish between multiple elements with the same selector
93
- * @example 'homepage-hero' | 'pricing-cta' | 'customer-testimonials'
94
- */
95
- id?: string;
96
- /**
97
- * Optional human-readable name for dashboards and reports
98
- * @example 'Homepage Hero Banner' | 'Pricing Page CTA' | 'Customer Testimonials Section'
99
- */
100
- name?: string;
101
- }
102
- /**
103
- * Configuration for viewport visibility tracking
104
- */
105
- interface ViewportConfig {
106
- /**
107
- * Elements to track with optional identifiers
108
- * Provides analytics support with business identifiers
109
- * @example [{ selector: '.hero', id: 'homepage-hero', name: 'Homepage Hero Banner' }]
110
- */
111
- elements: ViewportElement[];
112
- /**
113
- * Minimum percentage of element that must be visible (0-1)
114
- * @default 0.5 (50%)
115
- */
116
- threshold?: number;
117
- /**
118
- * Minimum time (ms) element must be visible to count as a view
119
- * @default 1000 (1 second)
120
- */
121
- minDwellTime?: number;
122
- /**
123
- * Cooldown period (ms) before same element can fire visibility event again
124
- * Prevents repeated events from carousels, sticky headers, and scrolling patterns
125
- * @default 60000 (60 seconds)
126
- */
127
- cooldownPeriod?: number;
128
- /**
129
- * Maximum number of elements to track simultaneously (Phase 3)
130
- * Prevents memory/server issues with broad selectors
131
- * @default 100
132
- */
133
- maxTrackedElements?: number;
134
- }
135
-
136
81
  /**
137
82
  * Coordinate information from a click event
138
- * Includes absolute and relative positioning
139
83
  */
140
- type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;
84
+ type ClickCoordinates = Pick<ClickData, 'x' | 'y'>;
141
85
  /**
142
86
  * Web performance metric types tracked by the library
143
87
  * - LCP: Largest Contentful Paint
@@ -145,9 +89,8 @@ type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;
145
89
  * - INP: Interaction to Next Paint
146
90
  * - FCP: First Contentful Paint
147
91
  * - TTFB: Time to First Byte
148
- * - LONG_TASK: Tasks exceeding 50ms
149
92
  */
150
- type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB' | 'LONG_TASK';
93
+ type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB';
151
94
  /**
152
95
  * Event type name
153
96
  */
@@ -169,32 +112,13 @@ declare enum EventType {
169
112
  /** Performance metrics */
170
113
  WEB_VITALS = "web_vitals",
171
114
  /** JavaScript errors and rejections */
172
- ERROR = "error",
173
- /** Element visibility tracking */
174
- VIEWPORT_VISIBLE = "viewport_visible"
115
+ ERROR = "error"
175
116
  }
176
117
  /**
177
- * Per-session event counts structure for rate limiting
178
- *
179
- * **Purpose**: Tracks how many events of each type have been generated
180
- * during the current session to enforce per-session limits and prevent
181
- * runaway event generation.
182
- *
183
- * **Usage**:
184
- * - Persisted to localStorage: `tlog:{userId}:session_counts:{sessionId}`
185
- * - Restored on page reload to maintain limits across navigations
186
- * - Debounced writes for performance (500ms delay)
187
- *
188
- * **Limits** (from config.constants.ts):
189
- * - Total: 1000 events per session
190
- * - Clicks: 500 per session
191
- * - Page Views: 100 per session
192
- * - Custom: 500 per session
193
- * - Viewport: 200 per session
194
- * - Scroll: 120 per session
195
- *
196
- * @see src/managers/event.manager.ts for implementation
197
- * @see src/constants/config.constants.ts for limit values
118
+ * Per-session event counts structure for rate limiting.
119
+ *
120
+ * Persisted to localStorage: `tlog:{userId}:session_counts:{sessionId}`
121
+ * Restored on page reload to maintain limits across navigations.
198
122
  */
199
123
  interface SessionEventCounts {
200
124
  /** Total events across all types */
@@ -205,8 +129,6 @@ interface SessionEventCounts {
205
129
  [EventType.PAGE_VIEW]: number;
206
130
  /** Custom events count */
207
131
  [EventType.CUSTOM]: number;
208
- /** Viewport visibility events count */
209
- [EventType.VIEWPORT_VISIBLE]: number;
210
132
  /** Scroll events count */
211
133
  [EventType.SCROLL]: number;
212
134
  /** Index signature for dynamic event type access */
@@ -240,12 +162,6 @@ interface ScrollData {
240
162
  direction: ScrollDirection;
241
163
  /** CSS selector of the scrolled container */
242
164
  container_selector: string;
243
- /** Whether this is the primary viewport scroll */
244
- is_primary: boolean;
245
- /** Scroll velocity in pixels per second */
246
- velocity: number;
247
- /** Maximum scroll depth reached during session (0-100) */
248
- max_depth_reached: number;
249
165
  }
250
166
  /**
251
167
  * Click event data capturing user interaction details
@@ -255,10 +171,6 @@ interface ClickData {
255
171
  x: number;
256
172
  /** Absolute Y coordinate in viewport (pixels) */
257
173
  y: number;
258
- /** Relative X position within element (0-1) */
259
- relativeX: number;
260
- /** Relative Y position within element (0-1) */
261
- relativeY: number;
262
174
  /** Element ID attribute */
263
175
  id?: string;
264
176
  /** Element class attribute */
@@ -269,16 +181,6 @@ interface ClickData {
269
181
  text?: string;
270
182
  /** Link href for anchor elements */
271
183
  href?: string;
272
- /** Element title attribute */
273
- title?: string;
274
- /** Image alt text for img elements */
275
- alt?: string;
276
- /** ARIA role attribute */
277
- role?: string;
278
- /** ARIA label attribute */
279
- ariaLabel?: string;
280
- /** Custom data attributes (data-*) */
281
- dataAttributes?: Record<string, string>;
282
184
  }
283
185
  /**
284
186
  * Element data for specialized click tracking
@@ -308,21 +210,10 @@ interface EventOptions {
308
210
  /**
309
211
  * If `true`, the event queue is flushed via `navigator.sendBeacon()`
310
212
  * immediately after this event is tracked. The browser guarantees the
311
- * request is queued for delivery even if the page is about to unload
312
- * (e.g., `window.location.href = '/thanks'` right after tracking a
313
- * purchase). Async fetch would be cancelled by the navigation;
314
- * sendBeacon survives.
213
+ * request is queued for delivery even if the page is about to unload.
315
214
  *
316
215
  * Use for high-value events where loss is unacceptable (Purchase, Signup,
317
- * AddPaymentInfo). The critical event plus any previously queued events
318
- * are sent in a single request — this does not bypass the queue.
319
- *
320
- * **Limitations** (inherited from `sendBeacon`):
321
- * - 64KB payload cap. If the combined queue + critical event exceeds it,
322
- * the failed batch is persisted to localStorage and recovered on next
323
- * `init()` via its idempotency token.
324
- * - No retry on failure (fire-and-forget).
325
- * - Custom headers are not applied (browser API limitation).
216
+ * AddPaymentInfo).
326
217
  *
327
218
  * @default false
328
219
  */
@@ -379,27 +270,6 @@ interface PageViewData {
379
270
  referrer?: string;
380
271
  /** Page title from document */
381
272
  title?: string;
382
- /** URL pathname */
383
- pathname?: string;
384
- /** URL query string */
385
- search?: string;
386
- /** URL hash fragment */
387
- hash?: string;
388
- }
389
- /**
390
- * Data captured when element becomes visible
391
- */
392
- interface ViewportEventData {
393
- /** CSS selector that matched the element */
394
- selector: string;
395
- /** Optional unique identifier for analytics (if configured) */
396
- id?: string;
397
- /** Optional human-readable name (if configured) */
398
- name?: string;
399
- /** Actual time (ms) element was visible before event fired */
400
- dwellTime: number;
401
- /** Actual visibility ratio when event fired (0-1) */
402
- visibilityRatio: number;
403
273
  }
404
274
  /**
405
275
  * Complete event data structure
@@ -430,8 +300,6 @@ interface EventData {
430
300
  page_view?: PageViewData;
431
301
  /** Error details (when type is ERROR) */
432
302
  error_data?: ErrorData;
433
- /** Viewport visibility details (when type is VIEWPORT_VISIBLE) */
434
- viewport_data?: ViewportEventData;
435
303
  /** Campaign tracking parameters */
436
304
  utm?: UTM;
437
305
  }
@@ -442,11 +310,6 @@ interface EventData {
442
310
  * their original `_session_id`, so `EventManager.buildBatchesWithIds()` can
443
311
  * still attribute them correctly instead of emitting `session_id: null` to the
444
312
  * wire.
445
- *
446
- * **Internal only.** The leading underscore mirrors `EventsQueue._metadata` —
447
- * this field is stripped from `events[]` at batch construction time, since the
448
- * backend's `EventDto` uses `forbidNonWhitelisted: true` and the wrapper
449
- * `EventsQueue.session_id` is the contract.
450
313
  */
451
314
  interface QueuedEvent extends EventData {
452
315
  _session_id: string;
@@ -470,10 +333,6 @@ interface Config {
470
333
  errorSampling?: number;
471
334
  /** Event sampling rate between 0 and 1. @default 1 */
472
335
  samplingRate?: number;
473
- /** CSS selector to manually override primary scroll container detection. */
474
- primaryScrollSelector?: string;
475
- /** Viewport visibility tracking configuration. */
476
- viewport?: ViewportConfig;
477
336
  /** Page view throttle duration in milliseconds to prevent rapid navigation spam. @default 1000 */
478
337
  pageViewThrottleMs?: number;
479
338
  /** Click throttle duration in milliseconds to prevent double-clicks and rapid spam. @default 300 */
@@ -497,11 +356,7 @@ interface Config {
497
356
  /**
498
357
  * Opt-in: when `true`, the event queue is flushed after every SPA navigation
499
358
  * (`pushState`, `replaceState`, `popstate`, `hashchange`). Defaults to `false`
500
- * because per-route flushing can multiply request volume on SPA-heavy apps
501
- * (one request per route change vs. one per `sendIntervalMs`). Enable only
502
- * if you need delivery between route changes that's faster than
503
- * `sendIntervalMs`; `flushOnPageHidden` (default `true`) already covers the
504
- * common tab-close / app-background case on every stack. No-op for MPAs.
359
+ * because per-route flushing can multiply request volume on SPA-heavy apps.
505
360
  * @default false
506
361
  */
507
362
  flushOnSpaNavigation?: boolean;
@@ -512,36 +367,14 @@ interface Config {
512
367
  * @default true
513
368
  */
514
369
  flushOnPageHidden?: boolean;
515
- /** Optional configuration for third-party integrations. */
370
+ /** TraceLog SaaS integration. */
516
371
  integrations?: {
517
- /** TraceLog integration options. */
518
372
  tracelog?: {
519
- /** Required project ID TraceLog SaaS integration. */
373
+ /** Required project ID for TraceLog SaaS integration. */
520
374
  projectId: string;
521
375
  /** Enable Shopify cart attribute linking for webhook revenue attribution. */
522
376
  shopify?: boolean;
523
377
  };
524
- /** Custom integration options. */
525
- custom?: {
526
- /** Endpoint for collecting events. */
527
- collectApiUrl: string;
528
- /** Allow HTTP URLs (not recommended for production). @default false */
529
- allowHttp?: boolean;
530
- /**
531
- * Static HTTP headers to include in every request.
532
- * For dynamic headers, use `setCustomHeaders()` instead.
533
- * @example { 'X-Brand': 'my-brand', 'X-Tenant-Id': 'tenant-123' }
534
- */
535
- headers?: Record<string, string>;
536
- /**
537
- * Controls whether cookies and credentials are sent with fetch requests.
538
- * - `'include'`: Always send cookies (even cross-origin) — required for cookie-based auth
539
- * - `'same-origin'`: Only send cookies for same-origin requests
540
- * - `'omit'`: Never send cookies
541
- * @default 'include'
542
- */
543
- fetchCredentials?: RequestCredentials;
544
- };
545
378
  };
546
379
  }
547
380
  declare enum SpecialApiUrl {
@@ -748,90 +581,15 @@ declare enum Mode {
748
581
  QA = "qa"
749
582
  }
750
583
 
751
- /**
752
- * Primary scroll event type (main viewport scroll)
753
- *
754
- * **Purpose**: Type-safe representation of primary viewport scroll events
755
- *
756
- * Primary scroll events track the main page/viewport scrolling,
757
- * which is the most important scroll metric for engagement analysis.
758
- */
759
- type PrimaryScrollEvent = EventData & {
760
- type: EventType.SCROLL;
761
- scroll_data: ScrollData & {
762
- is_primary: true;
763
- };
764
- };
765
- /**
766
- * Secondary scroll event type (scrollable container scroll)
767
- *
768
- * **Purpose**: Type-safe representation of container-specific scroll events
769
- *
770
- * Secondary scroll events track scrolling within specific elements
771
- * (e.g., modals, sidebars, embedded content) for granular engagement analysis.
772
- */
773
- type SecondaryScrollEvent = EventData & {
774
- type: EventType.SCROLL;
775
- scroll_data: ScrollData & {
776
- is_primary: false;
777
- };
778
- };
779
- /**
780
- * Type guard to check if an event is a primary scroll event
781
- *
782
- * **Purpose**: Runtime type narrowing for primary viewport scrolls
783
- *
784
- * **Use Cases**:
785
- * - Filter events to process only main viewport scrolling
786
- * - Separate primary from secondary scroll analytics
787
- * - Type-safe event processing in transformers
788
- *
789
- * @param event - Event to check
790
- * @returns `true` if event is a primary scroll event
791
- *
792
- * @example
793
- * ```typescript
794
- * if (isPrimaryScrollEvent(event)) {
795
- * // event.scroll_data.is_primary is guaranteed to be true
796
- * console.log('Main viewport scrolled to', event.scroll_data.depth, '%');
797
- * }
798
- * ```
799
- */
800
- declare const isPrimaryScrollEvent: (event: EventData) => event is PrimaryScrollEvent;
801
- /**
802
- * Type guard to check if an event is a secondary scroll event
803
- *
804
- * **Purpose**: Runtime type narrowing for container-specific scrolls
805
- *
806
- * **Use Cases**:
807
- * - Filter events to process only container scrolling
808
- * - Analyze engagement with specific page sections
809
- * - Type-safe event processing in transformers
810
- *
811
- * @param event - Event to check
812
- * @returns `true` if event is a secondary scroll event
813
- *
814
- * @example
815
- * ```typescript
816
- * if (isSecondaryScrollEvent(event)) {
817
- * // event.scroll_data.is_primary is guaranteed to be false
818
- * console.log('Container scrolled:', event.scroll_data.container_selector);
819
- * }
820
- * ```
821
- */
822
- declare const isSecondaryScrollEvent: (event: EventData) => event is SecondaryScrollEvent;
823
-
824
584
  interface State {
825
585
  /** QA mode flag - when true, custom events are logged to console */
826
586
  mode?: Mode;
827
587
  /**
828
588
  * Collection of API URLs for different integrations.
829
589
  * - saas: TraceLog SaaS endpoint (if projectId configured)
830
- * - custom: Custom backend endpoint (if collectApiUrl configured)
831
590
  */
832
591
  collectApiUrls: {
833
592
  saas?: string;
834
- custom?: string;
835
593
  };
836
594
  config: Config;
837
595
  sessionId: string | null;
@@ -847,6 +605,15 @@ interface State {
847
605
  identity?: IdentifyData;
848
606
  }
849
607
 
608
+ /**
609
+ * Regular expressions used to detect and redact common PII patterns from
610
+ * free-form text (click text, error messages, stack traces, etc.).
611
+ *
612
+ * Mirrors the patterns relied on by `ClickHandler` and `ErrorHandler`. Adding
613
+ * a pattern here automatically widens coverage for both handlers.
614
+ */
615
+ declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
616
+
850
617
  /**
851
618
  * Type-safe event emitter for TraceLog internal events
852
619
  *
@@ -1007,35 +774,15 @@ declare class Emitter {
1007
774
  /**
1008
775
  * Abstract base class providing centralized, type-safe state management.
1009
776
  *
1010
- * **Purpose**: Foundation for all TraceLog managers and handlers, providing
1011
- * synchronized access to shared application state.
1012
- *
1013
- * **Architecture**:
1014
- * - All managers/handlers extend this class
1015
- * - Single global state instance shared across all subclasses
1016
- * - Type-safe operations via generic methods
1017
- * - In-memory only (no automatic persistence)
1018
- *
1019
- * **Supported State Properties**:
1020
- * - **Core State**: `collectApiUrls`, `config`, `sessionId`, `userId`, `device`, `pageUrl`
1021
- * - **Control Flags**: `mode` (QA/production), `hasStartSession`, `suppressNextScroll`
1022
- * - **Runtime Counters**: `scrollEventCount` (optional)
1023
- *
1024
- * **Implementation Details**:
1025
- * - Synchronous operations (no async overhead)
1026
- * - Memory-efficient (minimal object creation)
1027
- * - No built-in logging (consumers handle their own state logging)
1028
- * - Read-only snapshots via `getState()` prevent accidental mutations
1029
- *
1030
- * @see src/managers/README.md (lines 170-201) for detailed documentation
777
+ * All managers/handlers extend this class. The global state is shared
778
+ * across every subclass instance.
1031
779
  *
1032
780
  * @example
1033
781
  * ```typescript
1034
782
  * class MyManager extends StateManager {
1035
783
  * initialize() {
1036
- * const userId = this.get('userId'); // Read state
1037
- * this.set('mode', 'qa'); // Write state
1038
- * const snapshot = this.getState(); // Readonly copy
784
+ * const userId = this.get('userId');
785
+ * this.set('mode', 'qa');
1039
786
  * }
1040
787
  * }
1041
788
  * ```
@@ -1043,52 +790,14 @@ declare class Emitter {
1043
790
  declare abstract class StateManager {
1044
791
  /**
1045
792
  * Retrieves a value from global state.
1046
- *
1047
- * Type-safe getter with compile-time key validation.
1048
- *
1049
- * @template T - State key type (compile-time validated)
1050
- * @param key - State property key
1051
- * @returns Current value for the given key (may be undefined)
1052
- *
1053
- * @example
1054
- * ```typescript
1055
- * const userId = this.get('userId');
1056
- * const config = this.get('config');
1057
- * const sessionId = this.get('sessionId');
1058
- * ```
1059
793
  */
1060
794
  protected get<T extends keyof State>(key: T): State[T];
1061
795
  /**
1062
796
  * Sets a value in global state.
1063
- *
1064
- * Type-safe setter with compile-time type checking.
1065
- * Changes are immediately visible to all StateManager subclasses.
1066
- *
1067
- * @template T - State key type (compile-time validated)
1068
- * @param key - State property key
1069
- * @param value - New value (type must match State[T])
1070
- *
1071
- * @example
1072
- * ```typescript
1073
- * this.set('sessionId', 'session-123');
1074
- * this.set('mode', Mode.QA);
1075
- * this.set('hasStartSession', true);
1076
- * ```
1077
797
  */
1078
798
  protected set<T extends keyof State>(key: T, value: State[T]): void;
1079
799
  /**
1080
800
  * Returns an immutable snapshot of the entire global state.
1081
- *
1082
- * Creates a shallow copy to prevent accidental mutations.
1083
- * Use for debugging or when multiple state properties are needed.
1084
- *
1085
- * @returns Readonly shallow copy of global state
1086
- *
1087
- * @example
1088
- * ```typescript
1089
- * const snapshot = this.getState();
1090
- * console.log(snapshot.userId, snapshot.sessionId);
1091
- * ```
1092
801
  */
1093
802
  protected getState(): Readonly<State>;
1094
803
  }
@@ -1096,212 +805,29 @@ declare abstract class StateManager {
1096
805
  /**
1097
806
  * Robust localStorage and sessionStorage wrapper with automatic fallback to in-memory storage.
1098
807
  *
1099
- * **Purpose**: Provides consistent storage APIs across all browser environments,
1100
- * handling quota limits, privacy modes, and SSR scenarios gracefully.
1101
- *
1102
- * **Core Functionality**:
1103
- * - **Dual Storage**: localStorage (persistent) and sessionStorage (tab-scoped)
1104
- * - **Automatic Fallback**: In-memory Maps when browser storage unavailable
1105
- * - **Quota Handling**: Intelligent cleanup on QuotaExceededError
1106
- * - **SSR-Safe**: No-op in Node.js environments
1107
- *
1108
- * **Key Features**:
1109
- * - Separate fallback Maps for each storage type
1110
- * - Storage quota error handling with automatic cleanup and retry
1111
- * - Intelligent cleanup: Prioritizes removing persisted events over critical data
1112
- * - Preserves: session, user, device, and config keys during cleanup
1113
- * - Test key validation during initialization (`__tracelog_test__`)
1114
- * - Public `isAvailable()` and `hasQuotaError()` for conditional logic
1115
- * - Explicit `clear()` method for TraceLog-namespaced data only (`tracelog_*` prefix)
1116
- *
1117
- * **Cleanup Strategy** (on QuotaExceededError):
1118
- * 1. Remove persisted events (`tracelog_persisted_events_*`) - usually largest data
1119
- * 2. If no persisted events, remove up to 5 non-critical keys
1120
- * 3. Preserve critical keys: `tracelog_session_*`, `tracelog_user_id`, `tracelog_device_id`, `tracelog_config`
1121
- *
1122
- * @see src/managers/README.md (lines 203-226) for detailed documentation
1123
- *
1124
- * @example
1125
- * ```typescript
1126
- * const storage = new StorageManager();
1127
- *
1128
- * // localStorage operations
1129
- * storage.setItem('key', 'value');
1130
- * const value = storage.getItem('key');
1131
- * storage.removeItem('key');
1132
- *
1133
- * // sessionStorage operations
1134
- * storage.setSessionItem('session_key', 'data');
1135
- * const sessionValue = storage.getSessionItem('session_key');
1136
- *
1137
- * // Check availability
1138
- * if (storage.isAvailable()) {
1139
- * // localStorage is working
1140
- * }
1141
- *
1142
- * // Check for quota issues
1143
- * if (storage.hasQuotaError()) {
1144
- * // Data may not persist
1145
- * }
1146
- * ```
808
+ * - Dual storage: localStorage (persistent) + sessionStorage (tab-scoped).
809
+ * - Automatic in-memory fallback when browser storage unavailable (privacy modes, SSR).
810
+ * - On `QuotaExceededError`: single-pass cleanup — purges `tracelog_persisted_events_*`
811
+ * first (largest, recoverable), retries once. Preserves session/user/device/config keys.
1147
812
  */
1148
813
  declare class StorageManager {
1149
814
  private readonly storage;
1150
815
  private readonly sessionStorageRef;
1151
816
  private readonly fallbackStorage;
1152
817
  private readonly fallbackSessionStorage;
1153
- private hasQuotaExceededError;
1154
818
  constructor();
1155
- /**
1156
- * Retrieves an item from localStorage.
1157
- *
1158
- * Automatically falls back to in-memory storage if localStorage unavailable.
1159
- *
1160
- * @param key - Storage key
1161
- * @returns Stored value or null if not found
1162
- */
1163
819
  getItem(key: string): string | null;
1164
- /**
1165
- * Stores an item in localStorage with automatic quota handling.
1166
- *
1167
- * **Behavior**:
1168
- * 1. Updates fallback storage first (ensures consistency)
1169
- * 2. Attempts to store in localStorage
1170
- * 3. On QuotaExceededError: Triggers cleanup and retries once
1171
- * 4. Falls back to in-memory storage if retry fails
1172
- *
1173
- * **Cleanup on Quota Error**:
1174
- * - Removes persisted events (largest data)
1175
- * - Removes up to 5 non-critical keys
1176
- * - Preserves session, user, device, and config keys
1177
- *
1178
- * @param key - Storage key
1179
- * @param value - String value to store
1180
- */
1181
820
  setItem(key: string, value: string): void;
1182
- /**
1183
- * Removes an item from localStorage and fallback storage.
1184
- *
1185
- * Safe to call even if key doesn't exist (idempotent).
1186
- *
1187
- * @param key - Storage key to remove
1188
- */
1189
821
  removeItem(key: string): void;
1190
822
  /**
1191
- * Clears all TraceLog-related items from storage.
1192
- *
1193
- * Only removes keys with `tracelog_` prefix (safe for shared storage).
1194
- * Clears both localStorage and fallback storage.
1195
- *
1196
- * **Use Cases**:
1197
- * - User logout/privacy actions
1198
- * - Development/testing cleanup
1199
- * - Reset analytics state
1200
- */
1201
- clear(): void;
1202
- /**
1203
- * Checks if localStorage is available.
1204
- *
1205
- * @returns true if localStorage is working, false if using fallback
1206
- */
1207
- isAvailable(): boolean;
1208
- /**
1209
- * Checks if a QuotaExceededError has occurred during this session.
1210
- *
1211
- * **Purpose**: Detect when localStorage is full and data may not persist.
1212
- * Allows application to show warnings or adjust behavior.
1213
- *
1214
- * **Note**: Flag is set on first QuotaExceededError and never reset.
1215
- *
1216
- * @returns true if quota exceeded at any point during this session
1217
- */
1218
- hasQuotaError(): boolean;
1219
- /**
1220
- * Implements two-phase cleanup strategy to free storage space when quota exceeded.
1221
- *
1222
- * **Purpose**: Removes TraceLog data intelligently to make room for new writes
1223
- * while preserving critical user state (session, user ID, device ID, config).
1224
- *
1225
- * **Two-Phase Cleanup Strategy**:
1226
- * 1. **Phase 1 (Priority)**: Remove all persisted events (`tracelog_persisted_events_*`)
1227
- * - These are typically the largest data items (batches of events)
1228
- * - Safe to remove as they represent recoverable failed sends
1229
- * - Returns immediately if any persisted events found and removed
1230
- *
1231
- * 2. **Phase 2 (Fallback)**: Remove up to 5 non-critical keys
1232
- * - Only executed if no persisted events found
1233
- * - Preserves critical keys: session data, user ID, device ID, config
1234
- * - Limits to 5 keys to avoid excessive cleanup time
1235
- *
1236
- * **Critical Keys (Never Removed)**:
1237
- * - `tracelog_session_*` - Active session data
1238
- * - `tracelog_user_id` - User identification
1239
- * - `tracelog_device_id` - Device fingerprint
1240
- * - `tracelog_config` - Configuration cache
1241
- *
1242
- * **Error Handling**:
1243
- * - Individual key removal failures silently ignored (continue cleanup)
1244
- * - Overall cleanup errors logged and return false
1245
- *
1246
- * @returns true if any data was successfully removed, false if nothing cleaned up
823
+ * Single-pass cleanup for QuotaExceededError. Purges persisted-events keys
824
+ * (largest, safe to discard — recoverable) and up to 5 other non-critical
825
+ * tracelog_* keys in one pass. Preserves session/user/device/config keys.
1247
826
  */
1248
827
  private cleanupOldData;
1249
- /**
1250
- * Initializes storage with feature detection and write-test validation.
1251
- *
1252
- * **Purpose**: Validates storage availability by performing actual write/remove test,
1253
- * preventing false positives in privacy modes where storage API exists but throws on write.
1254
- *
1255
- * **Validation Strategy**:
1256
- * 1. SSR Safety: Returns null in Node.js environments (`typeof window === 'undefined'`)
1257
- * 2. API Check: Verifies storage object exists on window
1258
- * 3. Write Test: Attempts to write test key (`__tracelog_test__`)
1259
- * 4. Cleanup: Removes test key immediately after validation
1260
- *
1261
- * **Why Write Test is Critical**:
1262
- * - Safari private browsing: storage API exists but throws QuotaExceededError on write
1263
- * - iOS private mode: storage appears available but operations fail
1264
- * - Incognito modes: API exists but writes are silently ignored or throw
1265
- *
1266
- * **Fallback Behavior**:
1267
- * - Returns null if storage unavailable or test fails
1268
- * - Caller automatically falls back to in-memory Map storage
1269
- *
1270
- * @param type - Storage type to initialize ('localStorage' | 'sessionStorage')
1271
- * @returns Storage instance if available and writable, null otherwise
1272
- */
1273
828
  private initializeStorage;
1274
- /**
1275
- * Retrieves an item from sessionStorage.
1276
- *
1277
- * Automatically falls back to in-memory storage if sessionStorage unavailable.
1278
- *
1279
- * @param key - Storage key
1280
- * @returns Stored value or null if not found
1281
- */
1282
829
  getSessionItem(key: string): string | null;
1283
- /**
1284
- * Stores an item in sessionStorage with quota error detection.
1285
- *
1286
- * **Behavior**:
1287
- * 1. Updates fallback storage first (ensures consistency)
1288
- * 2. Attempts to store in sessionStorage
1289
- * 3. On QuotaExceededError: Logs error and uses fallback (no retry/cleanup)
1290
- *
1291
- * **Note**: sessionStorage quota errors are rare (typically 5-10MB per tab).
1292
- * No automatic cleanup unlike localStorage.
1293
- *
1294
- * @param key - Storage key
1295
- * @param value - String value to store
1296
- */
1297
830
  setSessionItem(key: string, value: string): void;
1298
- /**
1299
- * Removes an item from sessionStorage and fallback storage.
1300
- *
1301
- * Safe to call even if key doesn't exist (idempotent).
1302
- *
1303
- * @param key - Storage key to remove
1304
- */
1305
831
  removeSessionItem(key: string): void;
1306
832
  }
1307
833
 
@@ -1371,7 +897,6 @@ declare class StorageManager {
1371
897
  declare class EventManager extends StateManager {
1372
898
  private readonly dataSenders;
1373
899
  private readonly emitter;
1374
- private readonly transformers;
1375
900
  private readonly timeManager;
1376
901
  private readonly recentEventFingerprints;
1377
902
  private readonly perEventRateLimits;
@@ -1389,18 +914,10 @@ declare class EventManager extends StateManager {
1389
914
  /**
1390
915
  * Creates an EventManager instance.
1391
916
  *
1392
- * **Initialization**:
1393
- * - Creates SenderManager instances for configured integrations (SaaS/Custom)
1394
- * - Initializes event emitter for local consumption
1395
- *
1396
917
  * @param storeManager - Storage manager for persistence
1397
918
  * @param emitter - Optional event emitter for local event consumption
1398
- * @param transformers - Optional event transformation hooks
1399
- * @param staticHeaders - Optional static HTTP headers for custom backend (from config)
1400
- * @param customHeadersProvider - Optional callback for dynamic headers
1401
- * @param fetchCredentials - Fetch credentials mode for custom backend. @default 'include'
1402
919
  */
1403
- constructor(storeManager: StorageManager, emitter?: Emitter | null, transformers?: TransformerMap, staticHeaders?: Record<string, string>, customHeadersProvider?: CustomHeadersProvider, fetchCredentials?: RequestCredentials);
920
+ constructor(storeManager: StorageManager, emitter?: Emitter | null);
1404
921
  /**
1405
922
  * Recovers persisted events from localStorage after a crash or page reload.
1406
923
  *
@@ -1485,7 +1002,7 @@ declare class EventManager extends StateManager {
1485
1002
  *
1486
1003
  * @see src/managers/README.md (lines 5-75) for detailed tracking logic
1487
1004
  */
1488
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, viewport_data, page_view, }: Partial<EventData>): void;
1005
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, page_view, }: Partial<EventData>): void;
1489
1006
  /**
1490
1007
  * Stops event tracking and clears all queues and buffers.
1491
1008
  *
@@ -1601,17 +1118,6 @@ declare class EventManager extends StateManager {
1601
1118
  * @see src/managers/README.md (lines 5-75) for flush details
1602
1119
  */
1603
1120
  flushImmediatelySync(): boolean;
1604
- /**
1605
- * Sets the custom headers provider callback for the custom integration.
1606
- * Only affects requests to custom backend (not TraceLog SaaS).
1607
- *
1608
- * @param provider - Callback function that returns custom headers
1609
- */
1610
- setCustomHeadersProvider(provider: CustomHeadersProvider): void;
1611
- /**
1612
- * Removes the custom headers provider callback from the custom integration.
1613
- */
1614
- removeCustomHeadersProvider(): void;
1615
1121
  /**
1616
1122
  * Returns the current number of events in the main queue.
1617
1123
  *
@@ -1909,7 +1415,6 @@ declare class EventManager extends StateManager {
1909
1415
  * - Custom threshold overrides via webVitalsThresholds config
1910
1416
  * - Navigation-based deduplication with 50-navigation FIFO history
1911
1417
  * - CLS accumulation with reset on navigation change
1912
- * - Long task throttling (maximum 1 event per second)
1913
1418
  * - Automatic fallback to Performance Observer if web-vitals library fails
1914
1419
  * - Final values only (reportAllChanges: false for all metrics)
1915
1420
  *
@@ -1921,7 +1426,6 @@ declare class EventManager extends StateManager {
1921
1426
  * - FCP (First Contentful Paint): Initial rendering time
1922
1427
  * - TTFB (Time to First Byte): Server response time
1923
1428
  * - INP (Interaction to Next Paint): Responsiveness measure
1924
- * - LONG_TASK: Tasks blocking main thread (>50ms, throttled to 1/second)
1925
1429
  *
1926
1430
  * **Filtering Modes**:
1927
1431
  * - 'all': Track all positive metric values (threshold = 0)
@@ -1942,7 +1446,6 @@ declare class PerformanceHandler extends StateManager {
1942
1446
  private readonly navigationHistory;
1943
1447
  private readonly observers;
1944
1448
  private vitalThresholds;
1945
- private lastLongTaskSentAt;
1946
1449
  private navigationCounter;
1947
1450
  constructor(eventManager: EventManager);
1948
1451
  /**
@@ -1955,7 +1458,6 @@ declare class PerformanceHandler extends StateManager {
1955
1458
  * - Reads webVitalsMode from config ('all', 'needs-improvement', 'poor')
1956
1459
  * - Merges webVitalsThresholds with mode defaults for custom thresholds
1957
1460
  * - Initializes web-vitals library observers (LCP, CLS, FCP, TTFB, INP)
1958
- * - Starts long task observation with 1/second throttling
1959
1461
  *
1960
1462
  * @returns Promise that resolves when tracking is initialized
1961
1463
  */
@@ -1973,7 +1475,6 @@ declare class PerformanceHandler extends StateManager {
1973
1475
  private observeWebVitalsFallback;
1974
1476
  private initWebVitals;
1975
1477
  private reportTTFB;
1976
- private observeLongTasks;
1977
1478
  private sendVital;
1978
1479
  private trackWebVital;
1979
1480
  /**
@@ -2015,45 +1516,70 @@ declare class PerformanceHandler extends StateManager {
2015
1516
  * - Message truncation (500 character limit)
2016
1517
  * - Burst detection (>10 errors/second triggers 5-second cooldown)
2017
1518
  * - Deduplication within 5-second window per error type+message
1519
+ * - Per-pageview signature cap (`MAX_ERRORS_PER_SIGNATURE_PER_PAGEVIEW`): after the
1520
+ * 5s dedup window expires, the same `(normalizedMessage, filename, line)` may only
1521
+ * recur up to N times per pageview. Counter resets on `pagehide`, `SESSION_START`,
1522
+ * and `PAGE_VIEW` (covers SPA navigation via patched History API + popstate/hashchange).
2018
1523
  *
2019
1524
  * **Privacy Protection**:
2020
1525
  * - Automatically redacts PII from error messages before storage
2021
1526
  * - Sanitizes emails, phone numbers, credit cards, IBAN, API keys, Bearer tokens
2022
1527
  *
2023
- * @see src/handlers/README.md (lines 167-218) for detailed documentation
1528
+ * @see src/handlers/README.md (`## ErrorHandler` section) for detailed documentation
2024
1529
  */
2025
1530
  declare class ErrorHandler extends StateManager {
2026
1531
  private readonly eventManager;
1532
+ private readonly emitter?;
2027
1533
  private readonly recentErrors;
1534
+ private readonly pageviewSignatureCounts;
2028
1535
  private errorBurstCounter;
2029
1536
  private burstWindowStart;
2030
1537
  private burstBackoffUntil;
2031
- constructor(eventManager: EventManager);
1538
+ private pagehideHandler;
1539
+ private pageviewResetListener;
1540
+ constructor(eventManager: EventManager, emitter?: Emitter);
2032
1541
  /**
2033
1542
  * Starts tracking JavaScript errors and promise rejections.
2034
1543
  *
2035
1544
  * - Registers global error event listener
2036
1545
  * - Registers unhandledrejection event listener
1546
+ * - Registers pagehide listener to reset the per-pageview signature counter
1547
+ * - Subscribes to emitter SESSION_START + PAGE_VIEW to reset the counter on new
1548
+ * sessions and SPA route changes (the only signal `pagehide` does not cover)
2037
1549
  */
2038
1550
  startTracking(): void;
2039
1551
  /**
2040
1552
  * Stops tracking errors and cleans up resources.
2041
1553
  *
2042
1554
  * - Removes error event listeners
2043
- * - Clears recent errors map
1555
+ * - Removes pagehide listener and unsubscribes from emitter
1556
+ * - Clears recent errors and pageview signature counters
2044
1557
  * - Resets burst detection counters
2045
1558
  */
2046
1559
  stopTracking(): void;
1560
+ /**
1561
+ * Clears the per-pageview signature counter.
1562
+ *
1563
+ * Public so `App` or tests can drive a reset explicitly; the handler itself wires
1564
+ * `pagehide` and emitter `SESSION_START` / `PAGE_VIEW` in `startTracking()`.
1565
+ */
1566
+ resetPageviewCounter(): void;
2047
1567
  /**
2048
1568
  * Checks sampling rate and burst detection
2049
1569
  * Returns false if in cooldown period after burst detection
2050
1570
  */
2051
1571
  private shouldSample;
1572
+ /**
1573
+ * Returns true when the per-pageview signature cap has been hit for this error.
1574
+ * Dropped errors do not increment the counter — the 5s suppression window already
1575
+ * silences identical repeats, and double-counting here would skew the cap for any
1576
+ * later signature that recycles the same map key after a counter reset.
1577
+ */
1578
+ private shouldThrottleBySignature;
2052
1579
  private readonly handleError;
2053
1580
  private readonly handleRejection;
2054
1581
  private extractRejectionMessage;
2055
1582
  private sanitize;
2056
- private sanitizePii;
2057
1583
  private shouldSuppressError;
2058
1584
  private static readonly TRUNCATION_SUFFIX;
2059
1585
  private truncateStack;
@@ -2280,128 +1806,36 @@ declare class ClickHandler extends StateManager {
2280
1806
  private getElementPath;
2281
1807
  private findTrackingElement;
2282
1808
  private getRelevantClickElement;
2283
- /**
2284
- * Clamps relative coordinate values to [0, 1] range with 3 decimal precision.
2285
- *
2286
- * @param value - Raw relative coordinate value
2287
- * @returns Clamped value between 0 and 1 with 3 decimal places (e.g., 0.123)
2288
- *
2289
- * @example
2290
- * clamp(1.234) // returns 1.000
2291
- * clamp(0.12345) // returns 0.123
2292
- * clamp(-0.5) // returns 0.000
2293
- */
2294
- private clamp;
2295
1809
  private calculateClickCoordinates;
2296
1810
  private extractTrackingData;
2297
1811
  private generateClickData;
2298
- /**
2299
- * Sanitizes text by replacing PII patterns with [REDACTED].
2300
- *
2301
- * Protects against:
2302
- * - Email addresses
2303
- * - Phone numbers (US format)
2304
- * - Credit card numbers
2305
- * - IBAN numbers
2306
- * - API keys/tokens
2307
- * - Bearer tokens
2308
- *
2309
- * @param text - Raw text content from element
2310
- * @returns Sanitized text with PII replaced by [REDACTED]
2311
- *
2312
- * @example
2313
- * sanitizeText('Email: user@example.com') // returns 'Email: [REDACTED]'
2314
- * sanitizeText('Card: 1234-5678-9012-3456') // returns 'Card: [REDACTED]'
2315
- * sanitizeText('Bearer token123') // returns '[REDACTED]'
2316
- */
2317
- private sanitizeText;
2318
1812
  private getRelevantText;
2319
- private extractElementAttributes;
2320
1813
  private createCustomEventData;
2321
1814
  }
2322
1815
 
2323
1816
  /**
2324
- * Tracks scroll depth, direction, velocity, and container identification across multiple scrollable elements.
1817
+ * Tracks scroll depth and direction across the window and any detected scrollable containers.
2325
1818
  *
2326
- * **Features**:
2327
- * - Automatic container detection with intelligent retry (5 attempts @ 200ms intervals)
2328
- * - Manual override via primaryScrollSelector config
2329
- * - Smart filtering with multiple guardrails:
2330
- * - Visibility check (element must be connected to DOM with dimensions)
2331
- * - Scrollability check (content must overflow container)
2332
- * - Significant movement (minimum 10px position delta)
2333
- * - Depth change (minimum 5% depth change between events)
2334
- * - Rate limiting (minimum 500ms interval between events per container)
2335
- * - Session cap (maximum 120 events per session with single warning)
2336
- * - Multi-container support with per-container debouncing (250ms)
2337
- * - Velocity calculation for engagement analysis
2338
- * - Max depth tracking per session
2339
- * - Primary vs secondary container classification
2340
- *
2341
- * **Events Generated**: `scroll`
2342
- *
2343
- * **Analytics Fields**:
2344
- * - depth: Current scroll depth (0-100%)
2345
- * - direction: 'up' | 'down'
2346
- * - container_selector: CSS selector or 'window'
2347
- * - is_primary: Boolean indicating main scroll container
2348
- * - velocity: Scroll speed in px/s
2349
- * - max_depth_reached: Peak engagement per container
2350
- *
2351
- * **Container Detection**:
2352
- * - Uses TreeWalker for performance
2353
- * - Pre-filters elements with overflow: auto/scroll CSS properties
2354
- * - Validates visibility and scrollability
2355
- * - Retries up to 5 times for dynamically loaded content (SPAs)
2356
- * - Falls back to window-only if no containers found
1819
+ * **Captured fields**: `depth` (0-100), `direction` (up/down), `container_selector`.
2357
1820
  *
2358
- * @example
2359
- * ```typescript
2360
- * const handler = new ScrollHandler(eventManager);
2361
- * handler.startTracking();
2362
- * // Automatically detects and tracks scrollable containers
2363
- * handler.stopTracking();
2364
- * ```
1821
+ * **Guardrails**:
1822
+ * - Significant movement (minimum 10px position delta)
1823
+ * - Depth change (minimum 5% delta between events)
1824
+ * - Rate limiting (minimum 500ms interval between events per container)
1825
+ * - Session cap (maximum 120 events per session)
1826
+ * - Multi-container support with 250ms per-container debouncing
2365
1827
  */
2366
1828
  declare class ScrollHandler extends StateManager {
2367
1829
  private readonly eventManager;
2368
1830
  private readonly containers;
2369
1831
  private limitWarningLogged;
2370
- private minDepthChange;
2371
- private minIntervalMs;
2372
- private maxEventsPerSession;
2373
1832
  private containerDiscoveryTimeoutId;
2374
1833
  constructor(eventManager: EventManager);
2375
- /**
2376
- * Starts tracking scroll events across all detected scrollable containers.
2377
- *
2378
- * Automatically detects scrollable containers using TreeWalker with retry logic:
2379
- * - Searches DOM for elements with overflow: auto/scroll
2380
- * - Validates visibility and scrollability
2381
- * - Retries up to 5 times with 200ms intervals for dynamic content
2382
- * - Falls back to window-only tracking if no containers found
2383
- * - Applies primaryScrollSelector config override if provided
2384
- *
2385
- * Attaches debounced scroll listeners (250ms per container) with smart filtering:
2386
- * - Significant movement (10px minimum)
2387
- * - Depth change (5% minimum)
2388
- * - Rate limiting (500ms minimum interval)
2389
- * - Session cap (120 events maximum)
2390
- */
2391
1834
  startTracking(): void;
2392
- /**
2393
- * Stops tracking scroll events and cleans up resources.
2394
- *
2395
- * Removes all scroll event listeners, clears debounce timers, cancels retry attempts,
2396
- * and resets session state (event counter, warning flags). Prevents memory leaks by
2397
- * properly cleaning up all containers and timers.
2398
- */
2399
1835
  stopTracking(): void;
2400
1836
  private tryDetectScrollContainers;
2401
- private applyPrimaryScrollSelectorIfConfigured;
2402
1837
  private findScrollableElements;
2403
1838
  private getElementSelector;
2404
- private determineIfPrimary;
2405
1839
  private setupScrollContainer;
2406
1840
  private processScrollEvent;
2407
1841
  private shouldEmitScrollEvent;
@@ -2409,7 +1843,6 @@ declare class ScrollHandler extends StateManager {
2409
1843
  private hasElapsedMinimumInterval;
2410
1844
  private hasSignificantDepthChange;
2411
1845
  private logLimitOnce;
2412
- private applyConfigOverrides;
2413
1846
  private isWindowScrollable;
2414
1847
  private clearContainerTimer;
2415
1848
  private getScrollDirection;
@@ -2419,106 +1852,7 @@ declare class ScrollHandler extends StateManager {
2419
1852
  private getViewportHeight;
2420
1853
  private getScrollHeight;
2421
1854
  private isElementScrollable;
2422
- private applyPrimaryScrollSelector;
2423
- private updateContainerPrimary;
2424
- }
2425
-
2426
- /**
2427
- * Handles viewport visibility tracking using IntersectionObserver API.
2428
- * Fires events when elements become visible for a minimum dwell time.
2429
- */
2430
- declare class ViewportHandler extends StateManager {
2431
- private readonly eventManager;
2432
- private readonly trackedElements;
2433
- private observer;
2434
- private mutationObserver;
2435
- private mutationDebounceTimer;
2436
- private config;
2437
- constructor(eventManager: EventManager);
2438
- /**
2439
- * Starts tracking viewport visibility for configured elements
2440
- */
2441
- startTracking(): void;
2442
- /**
2443
- * Stops tracking and cleans up resources
2444
- */
2445
- stopTracking(): void;
2446
- /**
2447
- * Query and observe all elements matching configured elements
2448
- */
2449
- private observeElements;
2450
- /**
2451
- * Handles intersection events from IntersectionObserver
2452
- */
2453
- private readonly handleIntersection;
2454
- /**
2455
- * Fires a viewport visible event
2456
- */
2457
- private fireViewportEvent;
2458
- /**
2459
- * Sets up MutationObserver to detect dynamically added elements
2460
- */
2461
- private setupMutationObserver;
2462
- /**
2463
- * Cleans up tracking for removed DOM nodes
2464
- */
2465
- private cleanupRemovedNodes;
2466
- }
2467
-
2468
- /**
2469
- * Transform individual events before sending to backend.
2470
- * Applied per-event, can filter by returning null.
2471
- *
2472
- * @param event - The event to transform
2473
- * @returns Transformed event or null to filter
2474
- */
2475
- type BeforeSendTransformer = (event: EventData) => EventData | null;
2476
- /**
2477
- * Transform entire batch before sending to backend.
2478
- * Applied per-batch (10s interval or 50 events), can filter by returning null.
2479
- *
2480
- * **Multi-batch flushes**: when the queue spans more than one session (e.g.
2481
- * after an idle-timeout renewal), one flush produces one batch per session,
2482
- * and this transformer is invoked **once per session-batch**. Avoid stateful
2483
- * transformers that assume a single invocation per flush.
2484
- *
2485
- * @param batch - The batch to transform
2486
- * @returns Transformed batch or null to filter
2487
- */
2488
- type BeforeBatchTransformer = (batch: EventsQueue) => EventsQueue | null;
2489
- /**
2490
- * Runtime transformer hooks that can be updated after initialization
2491
- * - 'beforeSend': Transform per-event before sending to backend
2492
- * - 'beforeBatch': Transform entire batch before sending to backend
2493
- */
2494
- type TransformerHook = 'beforeSend' | 'beforeBatch';
2495
- /**
2496
- * Strongly-typed transformer map for internal storage
2497
- */
2498
- interface TransformerMap {
2499
- beforeSend?: BeforeSendTransformer;
2500
- beforeBatch?: BeforeBatchTransformer;
2501
1855
  }
2502
- /**
2503
- * Callback function for providing dynamic HTTP headers.
2504
- *
2505
- * Called synchronously before each fetch request to custom backends.
2506
- * Return empty object {} to send no custom headers.
2507
- *
2508
- * **Note**: Only applies to `custom` integration (not TraceLog SaaS).
2509
- * Headers are NOT applied to sendBeacon requests (page unload).
2510
- *
2511
- * @returns Record of header names to values
2512
- *
2513
- * @example
2514
- * ```typescript
2515
- * tracelog.setCustomHeaders(() => ({
2516
- * 'Authorization': `Bearer ${getAuthToken()}`,
2517
- * 'X-Request-ID': crypto.randomUUID()
2518
- * }));
2519
- * ```
2520
- */
2521
- type CustomHeadersProvider = () => Record<string, string>;
2522
1856
 
2523
1857
  /**
2524
1858
  * Testing bridge interface for E2E and integration tests
@@ -2540,18 +1874,9 @@ interface TraceLogTestBridge {
2540
1874
  get<T extends keyof State>(key: T): State[T];
2541
1875
  getFullState(): Readonly<State>;
2542
1876
  getState(): Readonly<State>;
2543
- updateGlobalMetadata(metadata: Record<string, unknown>): void;
2544
- mergeGlobalMetadata(metadata: Record<string, unknown>): void;
2545
1877
  getSessionData(): Record<string, unknown> | null;
2546
1878
  getQueueLength(): number;
2547
1879
  getQueueEvents(): EventData[];
2548
- setQaMode(enabled: boolean): void;
2549
- setTransformer(hook: 'beforeSend', fn: BeforeSendTransformer): void;
2550
- setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
2551
- setTransformer(hook: TransformerHook, fn: BeforeSendTransformer | BeforeBatchTransformer): void;
2552
- removeTransformer(hook: TransformerHook): void;
2553
- setCustomHeaders(provider: CustomHeadersProvider): void;
2554
- removeCustomHeaders(): void;
2555
1880
  getEventManager(): EventManager | undefined;
2556
1881
  getStorageManager(): StorageManager | null;
2557
1882
  getPerformanceHandler(): PerformanceHandler | null;
@@ -2560,7 +1885,6 @@ interface TraceLogTestBridge {
2560
1885
  getPageViewHandler(): PageViewHandler | null;
2561
1886
  getClickHandler(): ClickHandler | null;
2562
1887
  getScrollHandler(): ScrollHandler | null;
2563
- getViewportHandler(): ViewportHandler | null;
2564
1888
  getHandlers(): {
2565
1889
  performance: PerformanceHandler | null;
2566
1890
  error: ErrorHandler | null;
@@ -2568,7 +1892,6 @@ interface TraceLogTestBridge {
2568
1892
  pageView: PageViewHandler | null;
2569
1893
  click: ClickHandler | null;
2570
1894
  scroll: ScrollHandler | null;
2571
- viewport: ViewportHandler | null;
2572
1895
  };
2573
1896
  identify(userId: string, traits?: Record<string, string>): void;
2574
1897
  resetIdentity(): Promise<void>;
@@ -2636,31 +1959,6 @@ declare global {
2636
1959
  }
2637
1960
  }
2638
1961
 
2639
- /**
2640
- * Transforms events at runtime before sending to custom backend.
2641
- *
2642
- * Note: Only applies to custom backend integration. TraceLog SaaS ignores transformers.
2643
- *
2644
- * @param hook - 'beforeSend' (per-event) or 'beforeBatch' (batch-level)
2645
- * @param fn - Transformer function. Return null to filter event/batch.
2646
- * @throws {Error} If called during destroy()
2647
- * @throws {Error} If fn is not a function
2648
- *
2649
- * @example
2650
- * ```typescript
2651
- * tracelog.setTransformer('beforeSend', (data) => {
2652
- * if ('type' in data) {
2653
- * return { ...data, appVersion: '1.0.0' };
2654
- * }
2655
- * return data;
2656
- * });
2657
- * ```
2658
- *
2659
- * @see {@link https://github.com/tracelog/tracelog-lib/blob/main/API_REFERENCE.md#settransformer} for integration behavior
2660
- */
2661
- declare function setTransformer(hook: 'beforeSend', fn: BeforeSendTransformer): void;
2662
- declare function setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
2663
-
2664
1962
  /**
2665
1963
  * Consolidated configuration constants for TraceLog
2666
1964
  * This file centralizes all timing, limits, browser, and initialization constants
@@ -2675,16 +1973,6 @@ declare const MAX_STRING_LENGTH = 1000;
2675
1973
  declare const MAX_STRING_LENGTH_IN_ARRAY = 500;
2676
1974
  declare const MAX_ARRAY_LENGTH = 1000;
2677
1975
 
2678
- /**
2679
- * Error handling and PII sanitization constants for TraceLog
2680
- * Centralizes patterns and limits for error tracking and data protection
2681
- */
2682
- /**
2683
- * Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)
2684
- * These patterns are used to replace sensitive information with [REDACTED] in error messages
2685
- */
2686
- declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
2687
-
2688
1976
  /**
2689
1977
  * Performance monitoring and web vitals constants for TraceLog
2690
1978
  * Centralizes thresholds and configuration for performance tracking
@@ -2692,20 +1980,15 @@ declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, Re
2692
1980
 
2693
1981
  /**
2694
1982
  * Web Vitals "good" thresholds (75th percentile boundaries)
2695
- * Metrics below or equal to these values are considered good performance.
2696
1983
  * Reference: https://web.dev/articles/vitals
2697
1984
  */
2698
1985
  declare const WEB_VITALS_GOOD_THRESHOLDS: Record<WebVitalType, number>;
2699
1986
  /**
2700
1987
  * Web Vitals "needs improvement" thresholds
2701
- * Metrics exceeding these values need attention but aren't critically poor.
2702
- * Reference: https://web.dev/articles/vitals
2703
1988
  */
2704
1989
  declare const WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS: Record<WebVitalType, number>;
2705
1990
  /**
2706
1991
  * Web Vitals "poor" thresholds
2707
- * Metrics exceeding these values indicate poor performance requiring immediate attention.
2708
- * Reference: https://web.dev/articles/vitals
2709
1992
  */
2710
1993
  declare const WEB_VITALS_POOR_THRESHOLDS: Record<WebVitalType, number>;
2711
1994
  /**
@@ -2724,21 +2007,12 @@ declare const tracelog: {
2724
2007
  event: (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[], options?: EventOptions) => void;
2725
2008
  on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
2726
2009
  off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
2727
- setTransformer: typeof setTransformer;
2728
- removeTransformer: (hook: TransformerHook) => void;
2729
- setCustomHeaders: (provider: CustomHeadersProvider) => void;
2730
- removeCustomHeaders: () => void;
2731
2010
  isInitialized: () => boolean;
2732
2011
  getSessionId: () => string | null;
2733
2012
  getUserId: () => string | null;
2734
2013
  destroy: () => void;
2735
- setQaMode: (enabled: boolean) => void;
2736
- updateGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
2737
- mergeGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
2738
2014
  identify: (userId: string, traits?: Record<string, string>) => void;
2739
2015
  resetIdentity: () => Promise<void>;
2740
- flushImmediately: () => Promise<boolean>;
2741
- flushImmediatelySync: () => boolean;
2742
2016
  };
2743
2017
 
2744
- export { AppConfigValidationError, type BeforeBatchTransformer, type BeforeSendTransformer, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, type CustomHeadersProvider, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, type DeviceInfo, DeviceType, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, type EventOptions, EventType, type EventTypeName, type EventsQueue, type IdentifyData, type InitResult, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, type QueueMetadata, type QueuedEvent, RateLimitError, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, TimeoutError, type TraceLogTestBridge, TraceLogValidationError, type TransformerHook, type TransformerMap, type UTM, type ViewportConfig, type ViewportElement, type ViewportEventData, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
2018
+ export { AppConfigValidationError, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, type DeviceInfo, DeviceType, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, type EventOptions, EventType, type EventTypeName, type EventsQueue, type IdentifyData, type InitResult, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type QueueMetadata, type QueuedEvent, RateLimitError, SamplingRateValidationError, type ScrollData, ScrollDirection, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, TimeoutError, type TraceLogTestBridge, TraceLogValidationError, type UTM, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, tracelog };