@tracelog/lib 2.1.2 → 2.2.0-rc.80.4

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,34 @@ 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, seen = /* @__PURE__ */ new Set()) => {
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) {
1141
+ if (seen.has(value)) {
1158
1142
  return false;
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
+ seen.add(value);
1145
+ if (Array.isArray(value)) {
1146
+ return value.every((item) => isSerializable(item, seen));
1147
+ }
1148
+ if (type === "object") {
1149
+ return Object.values(value).every((v) => isSerializable(v, seen));
1150
+ }
1151
+ return false;
1152
+ };
1153
+ var isOnlyPrimitiveFields = (object) => {
1154
+ if (typeof object !== "object" || object === null) {
1191
1155
  return false;
1192
1156
  }
1193
- return true;
1157
+ return isSerializable(object);
1194
1158
  };
1195
1159
 
1196
1160
  // src/utils/validations/metadata-validations.utils.ts
@@ -1585,6 +1549,8 @@ var SenderManager = class extends StateManager {
1585
1549
  integrationId;
1586
1550
  apiUrl;
1587
1551
  transformers;
1552
+ staticHeaders;
1553
+ customHeadersProvider;
1588
1554
  lastPermanentErrorLog = null;
1589
1555
  recoveryInProgress = false;
1590
1556
  lastMetadataTimestamp = 0;
@@ -1599,9 +1565,11 @@ var SenderManager = class extends StateManager {
1599
1565
  * @param integrationId - Optional integration identifier ('saas' or 'custom')
1600
1566
  * @param apiUrl - Optional API endpoint URL
1601
1567
  * @param transformers - Optional event transformation hooks
1568
+ * @param staticHeaders - Optional static HTTP headers (from config)
1569
+ * @param customHeadersProvider - Optional callback for dynamic headers
1602
1570
  * @throws Error if integrationId and apiUrl are not both provided or both undefined
1603
1571
  */
1604
- constructor(storeManager, integrationId, apiUrl, transformers = {}) {
1572
+ constructor(storeManager, integrationId, apiUrl, transformers = {}, staticHeaders = {}, customHeadersProvider) {
1605
1573
  super();
1606
1574
  if (integrationId && !apiUrl || !integrationId && apiUrl) {
1607
1575
  throw new Error("SenderManager: integrationId and apiUrl must either both be provided or both be undefined");
@@ -1610,6 +1578,8 @@ var SenderManager = class extends StateManager {
1610
1578
  this.integrationId = integrationId;
1611
1579
  this.apiUrl = apiUrl;
1612
1580
  this.transformers = transformers;
1581
+ this.staticHeaders = staticHeaders;
1582
+ this.customHeadersProvider = customHeadersProvider;
1613
1583
  }
1614
1584
  /**
1615
1585
  * Get the integration ID for this sender
@@ -1618,6 +1588,49 @@ var SenderManager = class extends StateManager {
1618
1588
  getIntegrationId() {
1619
1589
  return this.integrationId;
1620
1590
  }
1591
+ /**
1592
+ * Sets the custom headers provider callback.
1593
+ * Only applies to 'custom' integration (ignored for 'saas').
1594
+ *
1595
+ * @param provider - Callback function that returns custom headers
1596
+ */
1597
+ setCustomHeadersProvider(provider) {
1598
+ this.customHeadersProvider = provider;
1599
+ }
1600
+ /**
1601
+ * Removes the custom headers provider callback.
1602
+ */
1603
+ removeCustomHeadersProvider() {
1604
+ this.customHeadersProvider = void 0;
1605
+ }
1606
+ /**
1607
+ * Builds custom headers by merging static headers with dynamic headers from provider.
1608
+ * Only applies to 'custom' integration (returns empty object for 'saas').
1609
+ *
1610
+ * @returns Merged custom headers object (dynamic headers override static)
1611
+ * @private
1612
+ */
1613
+ getCustomHeaders() {
1614
+ if (this.integrationId !== "custom") {
1615
+ return {};
1616
+ }
1617
+ let dynamicHeaders = {};
1618
+ if (this.customHeadersProvider) {
1619
+ try {
1620
+ const result = this.customHeadersProvider();
1621
+ if (typeof result === "object" && result !== null && !Array.isArray(result)) {
1622
+ dynamicHeaders = result;
1623
+ } else {
1624
+ log("warn", "Custom headers provider returned invalid value, expected object", {
1625
+ data: { received: typeof result }
1626
+ });
1627
+ }
1628
+ } catch (error) {
1629
+ log("warn", "Custom headers provider threw an error, using static headers only", { error });
1630
+ }
1631
+ }
1632
+ return { ...this.staticHeaders, ...dynamicHeaders };
1633
+ }
1621
1634
  getQueueStorageKey() {
1622
1635
  const userId = this.get("userId") || "anonymous";
1623
1636
  const baseKey = QUEUE_KEY(userId);
@@ -1645,6 +1658,11 @@ var SenderManager = class extends StateManager {
1645
1658
  *
1646
1659
  * **Important**: No retry mechanism for failures. Events are NOT persisted.
1647
1660
  *
1661
+ * **Custom Headers Limitation**: Custom headers set via `setCustomHeaders()` are NOT applied
1662
+ * to sendBeacon requests due to browser API limitations. The sendBeacon API only supports
1663
+ * Content-Type header via Blob. For scenarios requiring custom headers, ensure async
1664
+ * sends complete before page unload.
1665
+ *
1648
1666
  * @param body - Event queue to send
1649
1667
  * @returns `true` if send succeeded or was skipped, `false` if failed
1650
1668
  *
@@ -2067,6 +2085,7 @@ var SenderManager = class extends StateManager {
2067
2085
  controller.abort();
2068
2086
  }, REQUEST_TIMEOUT_MS);
2069
2087
  try {
2088
+ const customHeaders = this.getCustomHeaders();
2070
2089
  const response = await fetch(url, {
2071
2090
  method: "POST",
2072
2091
  body: payload,
@@ -2074,6 +2093,7 @@ var SenderManager = class extends StateManager {
2074
2093
  credentials: "include",
2075
2094
  signal: controller.signal,
2076
2095
  headers: {
2096
+ ...customHeaders,
2077
2097
  "Content-Type": "application/json"
2078
2098
  }
2079
2099
  });
@@ -2536,8 +2556,10 @@ var EventManager = class extends StateManager {
2536
2556
  * @param storeManager - Storage manager for persistence
2537
2557
  * @param emitter - Optional event emitter for local event consumption
2538
2558
  * @param transformers - Optional event transformation hooks
2559
+ * @param staticHeaders - Optional static HTTP headers for custom backend (from config)
2560
+ * @param customHeadersProvider - Optional callback for dynamic headers
2539
2561
  */
2540
- constructor(storeManager, emitter = null, transformers = {}) {
2562
+ constructor(storeManager, emitter = null, transformers = {}, staticHeaders = {}, customHeadersProvider) {
2541
2563
  super();
2542
2564
  this.emitter = emitter;
2543
2565
  this.transformers = transformers;
@@ -2548,7 +2570,16 @@ var EventManager = class extends StateManager {
2548
2570
  this.dataSenders.push(new SenderManager(storeManager, "saas", collectApiUrls.saas, transformers));
2549
2571
  }
2550
2572
  if (collectApiUrls?.custom) {
2551
- this.dataSenders.push(new SenderManager(storeManager, "custom", collectApiUrls.custom, transformers));
2573
+ this.dataSenders.push(
2574
+ new SenderManager(
2575
+ storeManager,
2576
+ "custom",
2577
+ collectApiUrls.custom,
2578
+ transformers,
2579
+ staticHeaders,
2580
+ customHeadersProvider
2581
+ )
2582
+ );
2552
2583
  }
2553
2584
  this.saveSessionCountsDebounced = this.debounce((sessionId) => {
2554
2585
  this.saveSessionCounts(sessionId);
@@ -2955,6 +2986,29 @@ var EventManager = class extends StateManager {
2955
2986
  flushImmediatelySync() {
2956
2987
  return this.flushEvents(true);
2957
2988
  }
2989
+ /**
2990
+ * Sets the custom headers provider callback for the custom integration.
2991
+ * Only affects requests to custom backend (not TraceLog SaaS).
2992
+ *
2993
+ * @param provider - Callback function that returns custom headers
2994
+ */
2995
+ setCustomHeadersProvider(provider) {
2996
+ for (const sender of this.dataSenders) {
2997
+ if (sender.getIntegrationId() === "custom") {
2998
+ sender.setCustomHeadersProvider(provider);
2999
+ }
3000
+ }
3001
+ }
3002
+ /**
3003
+ * Removes the custom headers provider callback from the custom integration.
3004
+ */
3005
+ removeCustomHeadersProvider() {
3006
+ for (const sender of this.dataSenders) {
3007
+ if (sender.getIntegrationId() === "custom") {
3008
+ sender.removeCustomHeadersProvider();
3009
+ }
3010
+ }
3011
+ }
2958
3012
  /**
2959
3013
  * Returns the current number of events in the main queue.
2960
3014
  *
@@ -6051,6 +6105,7 @@ var App = class extends StateManager {
6051
6105
  suppressNextScrollTimer = null;
6052
6106
  emitter = new Emitter();
6053
6107
  transformers = {};
6108
+ customHeadersProvider;
6054
6109
  managers = {};
6055
6110
  handlers = {};
6056
6111
  get initialized() {
@@ -6070,7 +6125,14 @@ var App = class extends StateManager {
6070
6125
  this.managers.storage = new StorageManager();
6071
6126
  try {
6072
6127
  this.setupState(config);
6073
- this.managers.event = new EventManager(this.managers.storage, this.emitter, this.transformers);
6128
+ const staticHeaders = config.integrations?.custom?.headers ?? {};
6129
+ this.managers.event = new EventManager(
6130
+ this.managers.storage,
6131
+ this.emitter,
6132
+ this.transformers,
6133
+ staticHeaders,
6134
+ this.customHeadersProvider
6135
+ );
6074
6136
  this.initializeHandlers();
6075
6137
  await this.managers.event.recoverPersistedEvents().catch((error) => {
6076
6138
  log("warn", "Failed to recover persisted events", { error });
@@ -6133,6 +6195,34 @@ var App = class extends StateManager {
6133
6195
  getTransformer(hook) {
6134
6196
  return this.transformers[hook];
6135
6197
  }
6198
+ /**
6199
+ * Sets a callback to provide custom HTTP headers for requests to custom backends.
6200
+ * Only applies to custom backend integration (not TraceLog SaaS).
6201
+ *
6202
+ * @param provider - Callback function that returns custom headers
6203
+ * @throws {Error} If provider is not a function
6204
+ * @internal Called from api.setCustomHeaders()
6205
+ */
6206
+ setCustomHeaders(provider) {
6207
+ if (typeof provider !== "function") {
6208
+ throw new Error(`[TraceLog] Custom headers provider must be a function, received: ${typeof provider}`);
6209
+ }
6210
+ this.customHeadersProvider = provider;
6211
+ if (this.managers.event) {
6212
+ this.managers.event.setCustomHeadersProvider(provider);
6213
+ }
6214
+ }
6215
+ /**
6216
+ * Removes the custom headers provider callback.
6217
+ *
6218
+ * @internal Called from api.removeCustomHeaders()
6219
+ */
6220
+ removeCustomHeaders() {
6221
+ this.customHeadersProvider = void 0;
6222
+ if (this.managers.event) {
6223
+ this.managers.event.removeCustomHeadersProvider();
6224
+ }
6225
+ }
6136
6226
  /**
6137
6227
  * Destroys the TraceLog instance and cleans up all resources.
6138
6228
  *
@@ -6158,6 +6248,7 @@ var App = class extends StateManager {
6158
6248
  this.emitter.removeAllListeners();
6159
6249
  this.transformers.beforeSend = void 0;
6160
6250
  this.transformers.beforeBatch = void 0;
6251
+ this.customHeadersProvider = void 0;
6161
6252
  this.set("suppressNextScroll", false);
6162
6253
  this.set("sessionId", null);
6163
6254
  this.isInitialized = false;
@@ -6312,6 +6403,7 @@ var App = class extends StateManager {
6312
6403
  // src/api.ts
6313
6404
  var pendingListeners = [];
6314
6405
  var pendingTransformers = [];
6406
+ var pendingCustomHeadersProvider = null;
6315
6407
  var app = null;
6316
6408
  var isInitializing = false;
6317
6409
  var isDestroying = false;
@@ -6346,6 +6438,10 @@ var init = async (config) => {
6346
6438
  }
6347
6439
  });
6348
6440
  pendingTransformers.length = 0;
6441
+ if (pendingCustomHeadersProvider) {
6442
+ instance.setCustomHeaders(pendingCustomHeadersProvider);
6443
+ pendingCustomHeadersProvider = null;
6444
+ }
6349
6445
  const initPromise = instance.init(validatedConfig);
6350
6446
  const timeoutPromise = new Promise((_, reject) => {
6351
6447
  setTimeout(() => {
@@ -6444,6 +6540,35 @@ var removeTransformer = (hook) => {
6444
6540
  }
6445
6541
  app.removeTransformer(hook);
6446
6542
  };
6543
+ var setCustomHeaders = (provider) => {
6544
+ if (typeof window === "undefined" || typeof document === "undefined") {
6545
+ return;
6546
+ }
6547
+ if (typeof provider !== "function") {
6548
+ throw new Error(`[TraceLog] Custom headers provider must be a function, received: ${typeof provider}`);
6549
+ }
6550
+ if (!app || isInitializing) {
6551
+ pendingCustomHeadersProvider = provider;
6552
+ return;
6553
+ }
6554
+ if (isDestroying) {
6555
+ throw new Error("[TraceLog] Cannot set custom headers while TraceLog is being destroyed");
6556
+ }
6557
+ app.setCustomHeaders(provider);
6558
+ };
6559
+ var removeCustomHeaders = () => {
6560
+ if (typeof window === "undefined" || typeof document === "undefined") {
6561
+ return;
6562
+ }
6563
+ if (!app) {
6564
+ pendingCustomHeadersProvider = null;
6565
+ return;
6566
+ }
6567
+ if (isDestroying) {
6568
+ throw new Error("[TraceLog] Cannot remove custom headers while TraceLog is being destroyed");
6569
+ }
6570
+ app.removeCustomHeaders();
6571
+ };
6447
6572
  var isInitialized = () => {
6448
6573
  if (typeof window === "undefined" || typeof document === "undefined") {
6449
6574
  return false;
@@ -6468,6 +6593,7 @@ var destroy = () => {
6468
6593
  isInitializing = false;
6469
6594
  pendingListeners.length = 0;
6470
6595
  pendingTransformers.length = 0;
6596
+ pendingCustomHeadersProvider = null;
6471
6597
  if (false) ;
6472
6598
  isDestroying = false;
6473
6599
  } catch (error) {
@@ -6475,6 +6601,7 @@ var destroy = () => {
6475
6601
  isInitializing = false;
6476
6602
  pendingListeners.length = 0;
6477
6603
  pendingTransformers.length = 0;
6604
+ pendingCustomHeadersProvider = null;
6478
6605
  isDestroying = false;
6479
6606
  log("warn", "Error during destroy, forced cleanup completed", { error });
6480
6607
  }
@@ -6518,6 +6645,8 @@ var tracelog = {
6518
6645
  off,
6519
6646
  setTransformer,
6520
6647
  removeTransformer,
6648
+ setCustomHeaders,
6649
+ removeCustomHeaders,
6521
6650
  isInitialized,
6522
6651
  destroy,
6523
6652
  setQaMode: setQaMode2,
@@ -6525,6 +6654,6 @@ var tracelog = {
6525
6654
  mergeGlobalMetadata
6526
6655
  };
6527
6656
 
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 };
6657
+ 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
6658
  //# sourceMappingURL=public-api.js.map
6530
6659
  //# sourceMappingURL=public-api.js.map