@tracelog/lib 2.1.2 → 2.2.0-rc.80.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.
@@ -443,6 +443,12 @@ interface Config {
443
443
  collectApiUrl: string;
444
444
  /** Allow HTTP URLs (not recommended for production). @default false */
445
445
  allowHttp?: boolean;
446
+ /**
447
+ * Static HTTP headers to include in every request.
448
+ * For dynamic headers, use `setCustomHeaders()` instead.
449
+ * @example { 'X-Brand': 'my-brand', 'X-Tenant-Id': 'tenant-123' }
450
+ */
451
+ headers?: Record<string, string>;
446
452
  };
447
453
  };
448
454
  }
@@ -1238,8 +1244,10 @@ declare class EventManager extends StateManager {
1238
1244
  * @param storeManager - Storage manager for persistence
1239
1245
  * @param emitter - Optional event emitter for local event consumption
1240
1246
  * @param transformers - Optional event transformation hooks
1247
+ * @param staticHeaders - Optional static HTTP headers for custom backend (from config)
1248
+ * @param customHeadersProvider - Optional callback for dynamic headers
1241
1249
  */
1242
- constructor(storeManager: StorageManager, emitter?: Emitter | null, transformers?: TransformerMap);
1250
+ constructor(storeManager: StorageManager, emitter?: Emitter | null, transformers?: TransformerMap, staticHeaders?: Record<string, string>, customHeadersProvider?: CustomHeadersProvider);
1243
1251
  /**
1244
1252
  * Recovers persisted events from localStorage after a crash or page reload.
1245
1253
  *
@@ -1430,6 +1438,17 @@ declare class EventManager extends StateManager {
1430
1438
  * @see src/managers/README.md (lines 5-75) for flush details
1431
1439
  */
1432
1440
  flushImmediatelySync(): boolean;
1441
+ /**
1442
+ * Sets the custom headers provider callback for the custom integration.
1443
+ * Only affects requests to custom backend (not TraceLog SaaS).
1444
+ *
1445
+ * @param provider - Callback function that returns custom headers
1446
+ */
1447
+ setCustomHeadersProvider(provider: CustomHeadersProvider): void;
1448
+ /**
1449
+ * Removes the custom headers provider callback from the custom integration.
1450
+ */
1451
+ removeCustomHeadersProvider(): void;
1433
1452
  /**
1434
1453
  * Returns the current number of events in the main queue.
1435
1454
  *
@@ -2236,6 +2255,26 @@ interface TransformerMap {
2236
2255
  beforeSend?: BeforeSendTransformer;
2237
2256
  beforeBatch?: BeforeBatchTransformer;
2238
2257
  }
2258
+ /**
2259
+ * Callback function for providing dynamic HTTP headers.
2260
+ *
2261
+ * Called synchronously before each fetch request to custom backends.
2262
+ * Return empty object {} to send no custom headers.
2263
+ *
2264
+ * **Note**: Only applies to `custom` integration (not TraceLog SaaS).
2265
+ * Headers are NOT applied to sendBeacon requests (page unload).
2266
+ *
2267
+ * @returns Record of header names to values
2268
+ *
2269
+ * @example
2270
+ * ```typescript
2271
+ * tracelog.setCustomHeaders(() => ({
2272
+ * 'Authorization': `Bearer ${getAuthToken()}`,
2273
+ * 'X-Request-ID': crypto.randomUUID()
2274
+ * }));
2275
+ * ```
2276
+ */
2277
+ type CustomHeadersProvider = () => Record<string, string>;
2239
2278
 
2240
2279
  /**
2241
2280
  * Testing bridge interface for E2E and integration tests
@@ -2267,6 +2306,8 @@ interface TraceLogTestBridge {
2267
2306
  setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
2268
2307
  setTransformer(hook: TransformerHook, fn: BeforeSendTransformer | BeforeBatchTransformer): void;
2269
2308
  removeTransformer(hook: TransformerHook): void;
2309
+ setCustomHeaders(provider: CustomHeadersProvider): void;
2310
+ removeCustomHeaders(): void;
2270
2311
  getEventManager(): EventManager | undefined;
2271
2312
  getStorageManager(): StorageManager | null;
2272
2313
  getPerformanceHandler(): PerformanceHandler | null;
@@ -2384,7 +2425,6 @@ declare const MAX_CUSTOM_EVENT_STRING_SIZE: number;
2384
2425
  declare const MAX_CUSTOM_EVENT_KEYS = 10;
2385
2426
  declare const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;
2386
2427
  declare const MAX_NESTED_OBJECT_KEYS = 20;
2387
- declare const MAX_METADATA_NESTING_DEPTH = 1;
2388
2428
  declare const MAX_STRING_LENGTH = 1000;
2389
2429
  declare const MAX_STRING_LENGTH_IN_ARRAY = 500;
2390
2430
  declare const MAX_ARRAY_LENGTH = 100;
@@ -2440,6 +2480,8 @@ declare const tracelog: {
2440
2480
  off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
2441
2481
  setTransformer: typeof setTransformer;
2442
2482
  removeTransformer: (hook: TransformerHook) => void;
2483
+ setCustomHeaders: (provider: CustomHeadersProvider) => void;
2484
+ removeCustomHeaders: () => void;
2443
2485
  isInitialized: () => boolean;
2444
2486
  destroy: () => void;
2445
2487
  setQaMode: (enabled: boolean) => void;
@@ -2447,4 +2489,4 @@ declare const tracelog: {
2447
2489
  mergeGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
2448
2490
  };
2449
2491
 
2450
- export { AppConfigValidationError, type BeforeBatchTransformer, type BeforeSendTransformer, 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, EventType, type EventTypeName, type EventsQueue, 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_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, 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 };
2492
+ 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, EventType, type EventTypeName, type EventsQueue, 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, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, 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 };
@@ -443,6 +443,12 @@ interface Config {
443
443
  collectApiUrl: string;
444
444
  /** Allow HTTP URLs (not recommended for production). @default false */
445
445
  allowHttp?: boolean;
446
+ /**
447
+ * Static HTTP headers to include in every request.
448
+ * For dynamic headers, use `setCustomHeaders()` instead.
449
+ * @example { 'X-Brand': 'my-brand', 'X-Tenant-Id': 'tenant-123' }
450
+ */
451
+ headers?: Record<string, string>;
446
452
  };
447
453
  };
448
454
  }
@@ -1238,8 +1244,10 @@ declare class EventManager extends StateManager {
1238
1244
  * @param storeManager - Storage manager for persistence
1239
1245
  * @param emitter - Optional event emitter for local event consumption
1240
1246
  * @param transformers - Optional event transformation hooks
1247
+ * @param staticHeaders - Optional static HTTP headers for custom backend (from config)
1248
+ * @param customHeadersProvider - Optional callback for dynamic headers
1241
1249
  */
1242
- constructor(storeManager: StorageManager, emitter?: Emitter | null, transformers?: TransformerMap);
1250
+ constructor(storeManager: StorageManager, emitter?: Emitter | null, transformers?: TransformerMap, staticHeaders?: Record<string, string>, customHeadersProvider?: CustomHeadersProvider);
1243
1251
  /**
1244
1252
  * Recovers persisted events from localStorage after a crash or page reload.
1245
1253
  *
@@ -1430,6 +1438,17 @@ declare class EventManager extends StateManager {
1430
1438
  * @see src/managers/README.md (lines 5-75) for flush details
1431
1439
  */
1432
1440
  flushImmediatelySync(): boolean;
1441
+ /**
1442
+ * Sets the custom headers provider callback for the custom integration.
1443
+ * Only affects requests to custom backend (not TraceLog SaaS).
1444
+ *
1445
+ * @param provider - Callback function that returns custom headers
1446
+ */
1447
+ setCustomHeadersProvider(provider: CustomHeadersProvider): void;
1448
+ /**
1449
+ * Removes the custom headers provider callback from the custom integration.
1450
+ */
1451
+ removeCustomHeadersProvider(): void;
1433
1452
  /**
1434
1453
  * Returns the current number of events in the main queue.
1435
1454
  *
@@ -2236,6 +2255,26 @@ interface TransformerMap {
2236
2255
  beforeSend?: BeforeSendTransformer;
2237
2256
  beforeBatch?: BeforeBatchTransformer;
2238
2257
  }
2258
+ /**
2259
+ * Callback function for providing dynamic HTTP headers.
2260
+ *
2261
+ * Called synchronously before each fetch request to custom backends.
2262
+ * Return empty object {} to send no custom headers.
2263
+ *
2264
+ * **Note**: Only applies to `custom` integration (not TraceLog SaaS).
2265
+ * Headers are NOT applied to sendBeacon requests (page unload).
2266
+ *
2267
+ * @returns Record of header names to values
2268
+ *
2269
+ * @example
2270
+ * ```typescript
2271
+ * tracelog.setCustomHeaders(() => ({
2272
+ * 'Authorization': `Bearer ${getAuthToken()}`,
2273
+ * 'X-Request-ID': crypto.randomUUID()
2274
+ * }));
2275
+ * ```
2276
+ */
2277
+ type CustomHeadersProvider = () => Record<string, string>;
2239
2278
 
2240
2279
  /**
2241
2280
  * Testing bridge interface for E2E and integration tests
@@ -2267,6 +2306,8 @@ interface TraceLogTestBridge {
2267
2306
  setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
2268
2307
  setTransformer(hook: TransformerHook, fn: BeforeSendTransformer | BeforeBatchTransformer): void;
2269
2308
  removeTransformer(hook: TransformerHook): void;
2309
+ setCustomHeaders(provider: CustomHeadersProvider): void;
2310
+ removeCustomHeaders(): void;
2270
2311
  getEventManager(): EventManager | undefined;
2271
2312
  getStorageManager(): StorageManager | null;
2272
2313
  getPerformanceHandler(): PerformanceHandler | null;
@@ -2384,7 +2425,6 @@ declare const MAX_CUSTOM_EVENT_STRING_SIZE: number;
2384
2425
  declare const MAX_CUSTOM_EVENT_KEYS = 10;
2385
2426
  declare const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;
2386
2427
  declare const MAX_NESTED_OBJECT_KEYS = 20;
2387
- declare const MAX_METADATA_NESTING_DEPTH = 1;
2388
2428
  declare const MAX_STRING_LENGTH = 1000;
2389
2429
  declare const MAX_STRING_LENGTH_IN_ARRAY = 500;
2390
2430
  declare const MAX_ARRAY_LENGTH = 100;
@@ -2440,6 +2480,8 @@ declare const tracelog: {
2440
2480
  off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
2441
2481
  setTransformer: typeof setTransformer;
2442
2482
  removeTransformer: (hook: TransformerHook) => void;
2483
+ setCustomHeaders: (provider: CustomHeadersProvider) => void;
2484
+ removeCustomHeaders: () => void;
2443
2485
  isInitialized: () => boolean;
2444
2486
  destroy: () => void;
2445
2487
  setQaMode: (enabled: boolean) => void;
@@ -2447,4 +2489,4 @@ declare const tracelog: {
2447
2489
  mergeGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
2448
2490
  };
2449
2491
 
2450
- export { AppConfigValidationError, type BeforeBatchTransformer, type BeforeSendTransformer, 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, EventType, type EventTypeName, type EventsQueue, 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_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, 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 };
2492
+ 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, EventType, type EventTypeName, type EventsQueue, 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, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, 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 };
@@ -39,12 +39,11 @@ var MAX_CUSTOM_EVENT_STRING_SIZE = 8 * 1024;
39
39
  var MAX_CUSTOM_EVENT_KEYS = 10;
40
40
  var MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;
41
41
  var MAX_NESTED_OBJECT_KEYS = 20;
42
- var MAX_METADATA_NESTING_DEPTH = 1;
43
42
  var MAX_TEXT_LENGTH = 255;
44
43
  var MAX_STRING_LENGTH = 1e3;
45
44
  var MAX_STRING_LENGTH_IN_ARRAY = 500;
46
45
  var MAX_ARRAY_LENGTH = 100;
47
- var MAX_OBJECT_DEPTH = 3;
46
+ var MAX_OBJECT_DEPTH = 10;
48
47
  var PRECISION_TWO_DECIMALS = 2;
49
48
  var MAX_BEACON_PAYLOAD_SIZE = 64 * 1024;
50
49
  var MAX_FINGERPRINTS = 1500;
@@ -556,7 +555,7 @@ var LONG_TASK_THROTTLE_MS = 1e3;
556
555
  var MAX_NAVIGATION_HISTORY = 50;
557
556
 
558
557
  // package.json
559
- var version = "2.1.1";
558
+ var version = "2.2.0";
560
559
 
561
560
  // src/constants/version.constants.ts
562
561
  var LIB_VERSION = version;
@@ -852,9 +851,6 @@ var sanitizeString = (value) => {
852
851
  return result;
853
852
  };
854
853
  var sanitizeValue = (value, depth = 0) => {
855
- if (depth > MAX_OBJECT_DEPTH) {
856
- return null;
857
- }
858
854
  if (value === null || value === void 0) {
859
855
  return null;
860
856
  }
@@ -870,6 +866,9 @@ var sanitizeValue = (value, depth = 0) => {
870
866
  if (typeof value === "boolean") {
871
867
  return value;
872
868
  }
869
+ if (depth > MAX_OBJECT_DEPTH) {
870
+ return null;
871
+ }
873
872
  if (Array.isArray(value)) {
874
873
  const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);
875
874
  const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);
@@ -1128,69 +1127,30 @@ var validateAndNormalizeConfig = (config) => {
1128
1127
  };
1129
1128
 
1130
1129
  // src/utils/validations/type-guards.utils.ts
1131
- var isValidArrayItem = (item) => {
1132
- if (typeof item === "string") {
1130
+ var isSerializable = (value) => {
1131
+ if (value === null || value === void 0) {
1133
1132
  return true;
1134
1133
  }
1135
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
1136
- const entries = Object.entries(item);
1137
- if (entries.length > MAX_NESTED_OBJECT_KEYS) {
1138
- return false;
1139
- }
1140
- for (const [, value] of entries) {
1141
- if (value === null || value === void 0) {
1142
- continue;
1143
- }
1144
- const type = typeof value;
1145
- if (type !== "string" && type !== "number" && type !== "boolean") {
1146
- return false;
1147
- }
1148
- }
1134
+ const type = typeof value;
1135
+ if (type === "string" || type === "number" || type === "boolean") {
1149
1136
  return true;
1150
1137
  }
1151
- return false;
1152
- };
1153
- var isOnlyPrimitiveFields = (object, depth = 0) => {
1154
- if (typeof object !== "object" || object === null) {
1138
+ if (type === "function" || type === "symbol" || type === "bigint") {
1155
1139
  return false;
1156
1140
  }
1157
- if (depth > MAX_METADATA_NESTING_DEPTH) {
1158
- return false;
1141
+ if (Array.isArray(value)) {
1142
+ return value.every((item) => isSerializable(item));
1159
1143
  }
1160
- for (const value of Object.values(object)) {
1161
- if (value === null || value === void 0) {
1162
- continue;
1163
- }
1164
- const type = typeof value;
1165
- if (type === "string" || type === "number" || type === "boolean") {
1166
- continue;
1167
- }
1168
- if (Array.isArray(value)) {
1169
- if (value.length === 0) {
1170
- continue;
1171
- }
1172
- const firstItem = value[0];
1173
- const isStringArray = typeof firstItem === "string";
1174
- if (isStringArray) {
1175
- if (!value.every((item) => typeof item === "string")) {
1176
- return false;
1177
- }
1178
- } else {
1179
- if (!value.every((item) => isValidArrayItem(item))) {
1180
- return false;
1181
- }
1182
- }
1183
- continue;
1184
- }
1185
- if (type === "object" && depth === 0) {
1186
- if (!isOnlyPrimitiveFields(value, depth + 1)) {
1187
- return false;
1188
- }
1189
- continue;
1190
- }
1144
+ if (type === "object") {
1145
+ return Object.values(value).every((v) => isSerializable(v));
1146
+ }
1147
+ return false;
1148
+ };
1149
+ var isOnlyPrimitiveFields = (object) => {
1150
+ if (typeof object !== "object" || object === null) {
1191
1151
  return false;
1192
1152
  }
1193
- return true;
1153
+ return isSerializable(object);
1194
1154
  };
1195
1155
 
1196
1156
  // src/utils/validations/metadata-validations.utils.ts
@@ -1585,6 +1545,8 @@ var SenderManager = class extends StateManager {
1585
1545
  integrationId;
1586
1546
  apiUrl;
1587
1547
  transformers;
1548
+ staticHeaders;
1549
+ customHeadersProvider;
1588
1550
  lastPermanentErrorLog = null;
1589
1551
  recoveryInProgress = false;
1590
1552
  lastMetadataTimestamp = 0;
@@ -1599,9 +1561,11 @@ var SenderManager = class extends StateManager {
1599
1561
  * @param integrationId - Optional integration identifier ('saas' or 'custom')
1600
1562
  * @param apiUrl - Optional API endpoint URL
1601
1563
  * @param transformers - Optional event transformation hooks
1564
+ * @param staticHeaders - Optional static HTTP headers (from config)
1565
+ * @param customHeadersProvider - Optional callback for dynamic headers
1602
1566
  * @throws Error if integrationId and apiUrl are not both provided or both undefined
1603
1567
  */
1604
- constructor(storeManager, integrationId, apiUrl, transformers = {}) {
1568
+ constructor(storeManager, integrationId, apiUrl, transformers = {}, staticHeaders = {}, customHeadersProvider) {
1605
1569
  super();
1606
1570
  if (integrationId && !apiUrl || !integrationId && apiUrl) {
1607
1571
  throw new Error("SenderManager: integrationId and apiUrl must either both be provided or both be undefined");
@@ -1610,6 +1574,8 @@ var SenderManager = class extends StateManager {
1610
1574
  this.integrationId = integrationId;
1611
1575
  this.apiUrl = apiUrl;
1612
1576
  this.transformers = transformers;
1577
+ this.staticHeaders = staticHeaders;
1578
+ this.customHeadersProvider = customHeadersProvider;
1613
1579
  }
1614
1580
  /**
1615
1581
  * Get the integration ID for this sender
@@ -1618,6 +1584,49 @@ var SenderManager = class extends StateManager {
1618
1584
  getIntegrationId() {
1619
1585
  return this.integrationId;
1620
1586
  }
1587
+ /**
1588
+ * Sets the custom headers provider callback.
1589
+ * Only applies to 'custom' integration (ignored for 'saas').
1590
+ *
1591
+ * @param provider - Callback function that returns custom headers
1592
+ */
1593
+ setCustomHeadersProvider(provider) {
1594
+ this.customHeadersProvider = provider;
1595
+ }
1596
+ /**
1597
+ * Removes the custom headers provider callback.
1598
+ */
1599
+ removeCustomHeadersProvider() {
1600
+ this.customHeadersProvider = void 0;
1601
+ }
1602
+ /**
1603
+ * Builds custom headers by merging static headers with dynamic headers from provider.
1604
+ * Only applies to 'custom' integration (returns empty object for 'saas').
1605
+ *
1606
+ * @returns Merged custom headers object (dynamic headers override static)
1607
+ * @private
1608
+ */
1609
+ getCustomHeaders() {
1610
+ if (this.integrationId !== "custom") {
1611
+ return {};
1612
+ }
1613
+ let dynamicHeaders = {};
1614
+ if (this.customHeadersProvider) {
1615
+ try {
1616
+ const result = this.customHeadersProvider();
1617
+ if (typeof result === "object" && result !== null && !Array.isArray(result)) {
1618
+ dynamicHeaders = result;
1619
+ } else {
1620
+ log("warn", "Custom headers provider returned invalid value, expected object", {
1621
+ data: { received: typeof result }
1622
+ });
1623
+ }
1624
+ } catch (error) {
1625
+ log("warn", "Custom headers provider threw an error, using static headers only", { error });
1626
+ }
1627
+ }
1628
+ return { ...this.staticHeaders, ...dynamicHeaders };
1629
+ }
1621
1630
  getQueueStorageKey() {
1622
1631
  const userId = this.get("userId") || "anonymous";
1623
1632
  const baseKey = QUEUE_KEY(userId);
@@ -1645,6 +1654,11 @@ var SenderManager = class extends StateManager {
1645
1654
  *
1646
1655
  * **Important**: No retry mechanism for failures. Events are NOT persisted.
1647
1656
  *
1657
+ * **Custom Headers Limitation**: Custom headers set via `setCustomHeaders()` are NOT applied
1658
+ * to sendBeacon requests due to browser API limitations. The sendBeacon API only supports
1659
+ * Content-Type header via Blob. For scenarios requiring custom headers, ensure async
1660
+ * sends complete before page unload.
1661
+ *
1648
1662
  * @param body - Event queue to send
1649
1663
  * @returns `true` if send succeeded or was skipped, `false` if failed
1650
1664
  *
@@ -2067,6 +2081,7 @@ var SenderManager = class extends StateManager {
2067
2081
  controller.abort();
2068
2082
  }, REQUEST_TIMEOUT_MS);
2069
2083
  try {
2084
+ const customHeaders = this.getCustomHeaders();
2070
2085
  const response = await fetch(url, {
2071
2086
  method: "POST",
2072
2087
  body: payload,
@@ -2074,6 +2089,7 @@ var SenderManager = class extends StateManager {
2074
2089
  credentials: "include",
2075
2090
  signal: controller.signal,
2076
2091
  headers: {
2092
+ ...customHeaders,
2077
2093
  "Content-Type": "application/json"
2078
2094
  }
2079
2095
  });
@@ -2536,8 +2552,10 @@ var EventManager = class extends StateManager {
2536
2552
  * @param storeManager - Storage manager for persistence
2537
2553
  * @param emitter - Optional event emitter for local event consumption
2538
2554
  * @param transformers - Optional event transformation hooks
2555
+ * @param staticHeaders - Optional static HTTP headers for custom backend (from config)
2556
+ * @param customHeadersProvider - Optional callback for dynamic headers
2539
2557
  */
2540
- constructor(storeManager, emitter = null, transformers = {}) {
2558
+ constructor(storeManager, emitter = null, transformers = {}, staticHeaders = {}, customHeadersProvider) {
2541
2559
  super();
2542
2560
  this.emitter = emitter;
2543
2561
  this.transformers = transformers;
@@ -2548,7 +2566,16 @@ var EventManager = class extends StateManager {
2548
2566
  this.dataSenders.push(new SenderManager(storeManager, "saas", collectApiUrls.saas, transformers));
2549
2567
  }
2550
2568
  if (collectApiUrls?.custom) {
2551
- this.dataSenders.push(new SenderManager(storeManager, "custom", collectApiUrls.custom, transformers));
2569
+ this.dataSenders.push(
2570
+ new SenderManager(
2571
+ storeManager,
2572
+ "custom",
2573
+ collectApiUrls.custom,
2574
+ transformers,
2575
+ staticHeaders,
2576
+ customHeadersProvider
2577
+ )
2578
+ );
2552
2579
  }
2553
2580
  this.saveSessionCountsDebounced = this.debounce((sessionId) => {
2554
2581
  this.saveSessionCounts(sessionId);
@@ -2955,6 +2982,29 @@ var EventManager = class extends StateManager {
2955
2982
  flushImmediatelySync() {
2956
2983
  return this.flushEvents(true);
2957
2984
  }
2985
+ /**
2986
+ * Sets the custom headers provider callback for the custom integration.
2987
+ * Only affects requests to custom backend (not TraceLog SaaS).
2988
+ *
2989
+ * @param provider - Callback function that returns custom headers
2990
+ */
2991
+ setCustomHeadersProvider(provider) {
2992
+ for (const sender of this.dataSenders) {
2993
+ if (sender.getIntegrationId() === "custom") {
2994
+ sender.setCustomHeadersProvider(provider);
2995
+ }
2996
+ }
2997
+ }
2998
+ /**
2999
+ * Removes the custom headers provider callback from the custom integration.
3000
+ */
3001
+ removeCustomHeadersProvider() {
3002
+ for (const sender of this.dataSenders) {
3003
+ if (sender.getIntegrationId() === "custom") {
3004
+ sender.removeCustomHeadersProvider();
3005
+ }
3006
+ }
3007
+ }
2958
3008
  /**
2959
3009
  * Returns the current number of events in the main queue.
2960
3010
  *
@@ -6051,6 +6101,7 @@ var App = class extends StateManager {
6051
6101
  suppressNextScrollTimer = null;
6052
6102
  emitter = new Emitter();
6053
6103
  transformers = {};
6104
+ customHeadersProvider;
6054
6105
  managers = {};
6055
6106
  handlers = {};
6056
6107
  get initialized() {
@@ -6070,7 +6121,14 @@ var App = class extends StateManager {
6070
6121
  this.managers.storage = new StorageManager();
6071
6122
  try {
6072
6123
  this.setupState(config);
6073
- this.managers.event = new EventManager(this.managers.storage, this.emitter, this.transformers);
6124
+ const staticHeaders = config.integrations?.custom?.headers ?? {};
6125
+ this.managers.event = new EventManager(
6126
+ this.managers.storage,
6127
+ this.emitter,
6128
+ this.transformers,
6129
+ staticHeaders,
6130
+ this.customHeadersProvider
6131
+ );
6074
6132
  this.initializeHandlers();
6075
6133
  await this.managers.event.recoverPersistedEvents().catch((error) => {
6076
6134
  log("warn", "Failed to recover persisted events", { error });
@@ -6133,6 +6191,34 @@ var App = class extends StateManager {
6133
6191
  getTransformer(hook) {
6134
6192
  return this.transformers[hook];
6135
6193
  }
6194
+ /**
6195
+ * Sets a callback to provide custom HTTP headers for requests to custom backends.
6196
+ * Only applies to custom backend integration (not TraceLog SaaS).
6197
+ *
6198
+ * @param provider - Callback function that returns custom headers
6199
+ * @throws {Error} If provider is not a function
6200
+ * @internal Called from api.setCustomHeaders()
6201
+ */
6202
+ setCustomHeaders(provider) {
6203
+ if (typeof provider !== "function") {
6204
+ throw new Error(`[TraceLog] Custom headers provider must be a function, received: ${typeof provider}`);
6205
+ }
6206
+ this.customHeadersProvider = provider;
6207
+ if (this.managers.event) {
6208
+ this.managers.event.setCustomHeadersProvider(provider);
6209
+ }
6210
+ }
6211
+ /**
6212
+ * Removes the custom headers provider callback.
6213
+ *
6214
+ * @internal Called from api.removeCustomHeaders()
6215
+ */
6216
+ removeCustomHeaders() {
6217
+ this.customHeadersProvider = void 0;
6218
+ if (this.managers.event) {
6219
+ this.managers.event.removeCustomHeadersProvider();
6220
+ }
6221
+ }
6136
6222
  /**
6137
6223
  * Destroys the TraceLog instance and cleans up all resources.
6138
6224
  *
@@ -6158,6 +6244,7 @@ var App = class extends StateManager {
6158
6244
  this.emitter.removeAllListeners();
6159
6245
  this.transformers.beforeSend = void 0;
6160
6246
  this.transformers.beforeBatch = void 0;
6247
+ this.customHeadersProvider = void 0;
6161
6248
  this.set("suppressNextScroll", false);
6162
6249
  this.set("sessionId", null);
6163
6250
  this.isInitialized = false;
@@ -6312,6 +6399,7 @@ var App = class extends StateManager {
6312
6399
  // src/api.ts
6313
6400
  var pendingListeners = [];
6314
6401
  var pendingTransformers = [];
6402
+ var pendingCustomHeadersProvider = null;
6315
6403
  var app = null;
6316
6404
  var isInitializing = false;
6317
6405
  var isDestroying = false;
@@ -6346,6 +6434,10 @@ var init = async (config) => {
6346
6434
  }
6347
6435
  });
6348
6436
  pendingTransformers.length = 0;
6437
+ if (pendingCustomHeadersProvider) {
6438
+ instance.setCustomHeaders(pendingCustomHeadersProvider);
6439
+ pendingCustomHeadersProvider = null;
6440
+ }
6349
6441
  const initPromise = instance.init(validatedConfig);
6350
6442
  const timeoutPromise = new Promise((_, reject) => {
6351
6443
  setTimeout(() => {
@@ -6444,6 +6536,35 @@ var removeTransformer = (hook) => {
6444
6536
  }
6445
6537
  app.removeTransformer(hook);
6446
6538
  };
6539
+ var setCustomHeaders = (provider) => {
6540
+ if (typeof window === "undefined" || typeof document === "undefined") {
6541
+ return;
6542
+ }
6543
+ if (typeof provider !== "function") {
6544
+ throw new Error(`[TraceLog] Custom headers provider must be a function, received: ${typeof provider}`);
6545
+ }
6546
+ if (!app || isInitializing) {
6547
+ pendingCustomHeadersProvider = provider;
6548
+ return;
6549
+ }
6550
+ if (isDestroying) {
6551
+ throw new Error("[TraceLog] Cannot set custom headers while TraceLog is being destroyed");
6552
+ }
6553
+ app.setCustomHeaders(provider);
6554
+ };
6555
+ var removeCustomHeaders = () => {
6556
+ if (typeof window === "undefined" || typeof document === "undefined") {
6557
+ return;
6558
+ }
6559
+ if (!app) {
6560
+ pendingCustomHeadersProvider = null;
6561
+ return;
6562
+ }
6563
+ if (isDestroying) {
6564
+ throw new Error("[TraceLog] Cannot remove custom headers while TraceLog is being destroyed");
6565
+ }
6566
+ app.removeCustomHeaders();
6567
+ };
6447
6568
  var isInitialized = () => {
6448
6569
  if (typeof window === "undefined" || typeof document === "undefined") {
6449
6570
  return false;
@@ -6468,6 +6589,7 @@ var destroy = () => {
6468
6589
  isInitializing = false;
6469
6590
  pendingListeners.length = 0;
6470
6591
  pendingTransformers.length = 0;
6592
+ pendingCustomHeadersProvider = null;
6471
6593
  if (false) ;
6472
6594
  isDestroying = false;
6473
6595
  } catch (error) {
@@ -6475,6 +6597,7 @@ var destroy = () => {
6475
6597
  isInitializing = false;
6476
6598
  pendingListeners.length = 0;
6477
6599
  pendingTransformers.length = 0;
6600
+ pendingCustomHeadersProvider = null;
6478
6601
  isDestroying = false;
6479
6602
  log("warn", "Error during destroy, forced cleanup completed", { error });
6480
6603
  }
@@ -6518,6 +6641,8 @@ var tracelog = {
6518
6641
  off,
6519
6642
  setTransformer,
6520
6643
  removeTransformer,
6644
+ setCustomHeaders,
6645
+ removeCustomHeaders,
6521
6646
  isInitialized,
6522
6647
  destroy,
6523
6648
  setQaMode: setQaMode2,
@@ -6525,6 +6650,6 @@ var tracelog = {
6525
6650
  mergeGlobalMetadata
6526
6651
  };
6527
6652
 
6528
- export { AppConfigValidationError, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, EmitterEvent, ErrorType, EventType, 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_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, Mode, PII_PATTERNS, PermanentError, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TraceLogValidationError, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
6653
+ export { AppConfigValidationError, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, EmitterEvent, ErrorType, EventType, 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, Mode, PII_PATTERNS, PermanentError, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TraceLogValidationError, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
6529
6654
  //# sourceMappingURL=public-api.js.map
6530
6655
  //# sourceMappingURL=public-api.js.map