@amplitude/session-replay-browser 1.47.0-sr-trc-debug-log.4 → 1.47.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.
Files changed (100) hide show
  1. package/README.md +203 -0
  2. package/lib/cjs/beacon-transport.d.ts +2 -0
  3. package/lib/cjs/beacon-transport.d.ts.map +1 -1
  4. package/lib/cjs/beacon-transport.js +39 -1
  5. package/lib/cjs/beacon-transport.js.map +1 -1
  6. package/lib/cjs/config/joined-config.d.ts +1 -6
  7. package/lib/cjs/config/joined-config.d.ts.map +1 -1
  8. package/lib/cjs/config/joined-config.js +23 -64
  9. package/lib/cjs/config/joined-config.js.map +1 -1
  10. package/lib/cjs/config/local-config.d.ts +4 -6
  11. package/lib/cjs/config/local-config.d.ts.map +1 -1
  12. package/lib/cjs/config/local-config.js +3 -19
  13. package/lib/cjs/config/local-config.js.map +1 -1
  14. package/lib/cjs/config/types.d.ts +74 -19
  15. package/lib/cjs/config/types.d.ts.map +1 -1
  16. package/lib/cjs/config/types.js.map +1 -1
  17. package/lib/cjs/index.d.ts +1 -0
  18. package/lib/cjs/index.d.ts.map +1 -1
  19. package/lib/cjs/index.js.map +1 -1
  20. package/lib/cjs/plugins/url-tracking-plugin.d.ts +0 -13
  21. package/lib/cjs/plugins/url-tracking-plugin.d.ts.map +1 -1
  22. package/lib/cjs/plugins/url-tracking-plugin.js +2 -6
  23. package/lib/cjs/plugins/url-tracking-plugin.js.map +1 -1
  24. package/lib/cjs/session-replay.d.ts +0 -33
  25. package/lib/cjs/session-replay.d.ts.map +1 -1
  26. package/lib/cjs/session-replay.js +40 -339
  27. package/lib/cjs/session-replay.js.map +1 -1
  28. package/lib/cjs/targeting/targeting-manager.d.ts +1 -4
  29. package/lib/cjs/targeting/targeting-manager.d.ts.map +1 -1
  30. package/lib/cjs/targeting/targeting-manager.js +10 -56
  31. package/lib/cjs/targeting/targeting-manager.js.map +1 -1
  32. package/lib/cjs/track-destination.d.ts +5 -1
  33. package/lib/cjs/track-destination.d.ts.map +1 -1
  34. package/lib/cjs/track-destination.js +212 -55
  35. package/lib/cjs/track-destination.js.map +1 -1
  36. package/lib/cjs/version.d.ts +1 -1
  37. package/lib/cjs/version.d.ts.map +1 -1
  38. package/lib/cjs/version.js +1 -1
  39. package/lib/cjs/version.js.map +1 -1
  40. package/lib/cjs/worker/index.js +1 -1
  41. package/lib/esm/beacon-transport.d.ts +2 -0
  42. package/lib/esm/beacon-transport.d.ts.map +1 -1
  43. package/lib/esm/beacon-transport.js +39 -1
  44. package/lib/esm/beacon-transport.js.map +1 -1
  45. package/lib/esm/config/joined-config.d.ts +1 -6
  46. package/lib/esm/config/joined-config.d.ts.map +1 -1
  47. package/lib/esm/config/joined-config.js +23 -64
  48. package/lib/esm/config/joined-config.js.map +1 -1
  49. package/lib/esm/config/local-config.d.ts +4 -6
  50. package/lib/esm/config/local-config.d.ts.map +1 -1
  51. package/lib/esm/config/local-config.js +4 -20
  52. package/lib/esm/config/local-config.js.map +1 -1
  53. package/lib/esm/config/types.d.ts +74 -19
  54. package/lib/esm/config/types.d.ts.map +1 -1
  55. package/lib/esm/config/types.js.map +1 -1
  56. package/lib/esm/index.d.ts +1 -0
  57. package/lib/esm/index.d.ts.map +1 -1
  58. package/lib/esm/index.js.map +1 -1
  59. package/lib/esm/plugins/url-tracking-plugin.d.ts +0 -13
  60. package/lib/esm/plugins/url-tracking-plugin.d.ts.map +1 -1
  61. package/lib/esm/plugins/url-tracking-plugin.js +2 -6
  62. package/lib/esm/plugins/url-tracking-plugin.js.map +1 -1
  63. package/lib/esm/session-replay.d.ts +0 -33
  64. package/lib/esm/session-replay.d.ts.map +1 -1
  65. package/lib/esm/session-replay.js +40 -339
  66. package/lib/esm/session-replay.js.map +1 -1
  67. package/lib/esm/targeting/targeting-manager.d.ts +1 -4
  68. package/lib/esm/targeting/targeting-manager.d.ts.map +1 -1
  69. package/lib/esm/targeting/targeting-manager.js +10 -56
  70. package/lib/esm/targeting/targeting-manager.js.map +1 -1
  71. package/lib/esm/track-destination.d.ts +5 -1
  72. package/lib/esm/track-destination.d.ts.map +1 -1
  73. package/lib/esm/track-destination.js +212 -55
  74. package/lib/esm/track-destination.js.map +1 -1
  75. package/lib/esm/version.d.ts +1 -1
  76. package/lib/esm/version.d.ts.map +1 -1
  77. package/lib/esm/version.js +1 -1
  78. package/lib/esm/version.js.map +1 -1
  79. package/lib/esm/worker/index.js +1 -1
  80. package/lib/scripts/index-min.js +1 -1
  81. package/lib/scripts/index-min.js.gz +0 -0
  82. package/lib/scripts/index-min.js.map +1 -1
  83. package/lib/scripts/observers-min.js +1 -1
  84. package/lib/scripts/observers-min.js.gz +0 -0
  85. package/lib/scripts/session-replay-browser-min.js +1 -1
  86. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  87. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  88. package/lib/scripts/targeting-min.js +1 -1
  89. package/lib/scripts/targeting-min.js.gz +0 -0
  90. package/lib/scripts/worker-min.js +1 -1
  91. package/lib/scripts/worker-min.js.gz +0 -0
  92. package/package.json +4 -4
  93. package/lib/cjs/diagnostics.d.ts +0 -50
  94. package/lib/cjs/diagnostics.d.ts.map +0 -1
  95. package/lib/cjs/diagnostics.js +0 -67
  96. package/lib/cjs/diagnostics.js.map +0 -1
  97. package/lib/esm/diagnostics.d.ts +0 -50
  98. package/lib/esm/diagnostics.d.ts.map +0 -1
  99. package/lib/esm/diagnostics.js +0 -64
  100. package/lib/esm/diagnostics.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"track-destination.js","sourceRoot":"","sources":["../../src/track-destination.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, getGlobalScope, ILogger, ServerZone, Status } from '@amplitude/analytics-core';\nimport { getCurrentUrl, getServerUrl } from './helpers';\nimport {\n MAX_RETRIES_EXCEEDED_MESSAGE,\n MISSING_API_KEY_MESSAGE,\n MISSING_DEVICE_ID_MESSAGE,\n SESSION_KILLED_MESSAGE,\n UNEXPECTED_ERROR_MESSAGE,\n UNEXPECTED_NETWORK_ERROR_MESSAGE,\n} from './messages';\nimport {\n SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination,\n SessionReplayDestination,\n SessionReplayDestinationContext,\n} from './typings/session-replay';\nimport { VERSION } from './version';\nimport {\n MAX_URL_LENGTH,\n KB_SIZE,\n MAX_KEEPALIVE_BYTES,\n WAF_PAYLOAD_TOO_LARGE_PATTERN,\n EVENT_SKIPPED_HEADER,\n EVENT_SKIP_CODE_THROTTLED,\n EVENT_SKIP_CODE_INVALID_RANGE,\n EVENT_SKIP_CODE_CAPTURE_DISABLED,\n THROTTLED_FLUSH_PAUSE_MS,\n MERGE_AFTER_THROTTLE_SOFT_CAP,\n SEND_TIMEOUT_MS,\n} from './constants';\nimport { gzipJson } from './utils/gzip';\n\ninterface WorkerCompleteMessage {\n type: 'complete';\n id: string;\n err?: string;\n // null when the response was a clean 200 (no skip header), undefined when the\n // request did not produce a 200, otherwise the server's skip-code string.\n skipCode?: string | null;\n}\ninterface WorkerLogMessage {\n type: 'log' | 'warn';\n id: string;\n message: string;\n}\ninterface WorkerPayloadTooLargeMessage {\n type: 'payload_too_large';\n id: string;\n isWaf: boolean;\n}\ntype WorkerMessage = WorkerCompleteMessage | WorkerLogMessage | WorkerPayloadTooLargeMessage;\n\nexport type PayloadBatcher = ({ version, events }: { version: number; events: string[] }) => {\n version: number;\n events: unknown[];\n};\n\n// Bounded so a long-lived SDK instance can't accumulate kill records indefinitely;\n// sessions are time-bounded in practice, this cap is just a defensive ceiling.\nconst MAX_KILLED_SESSIONS = 256;\n\n// Defensive ceiling on retained timed-out worker requests (see timedOutWorkerRequests).\n// In normal operation each entry is removed when the worker's late message arrives; this\n// cap only guards the pathological case of a wedged worker that never replies at all.\nconst MAX_TIMED_OUT_WORKER_REQUESTS = 256;\n\nexport class SessionReplayTrackDestination implements AmplitudeSessionReplayTrackDestination {\n loggerProvider: ILogger;\n storageKey = '';\n trackServerUrl?: string;\n retryTimeout = 1000;\n // Defaults to true (gzip enabled) so existing call sites that don't pass the flag\n // retain pre-flag behavior. The local-config layer also defaults to true; this\n // belt-and-braces default protects direct constructor callers (e.g. tests).\n private enableTransportCompression: boolean;\n // Milliseconds before an in-flight send is aborted; <= 0 disables the abort/timeout.\n // Defaults to SEND_TIMEOUT_MS. Configurable so large slow-but-succeeding uploads aren't\n // killed (and retried) at an over-aggressive default. See config.sendTimeoutMs.\n private sendTimeoutMs: number;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n payloadBatcher: PayloadBatcher;\n queue: SessionReplayDestinationContext[] = [];\n private worker?: Worker;\n private sendIdCounter = 0;\n private pendingWorkerRequests = new Map<\n string,\n { context: SessionReplayDestinationContext; resolve: () => void; timeout?: ReturnType<typeof setTimeout> }\n >();\n // Requests the main thread stopped awaiting after SEND_TIMEOUT_MS (so the serial flush\n // loop could proceed) but whose worker may still be retrying in the background. We keep\n // the context — bounded, like killedSessions — so a *late* worker complete/payload_too_large\n // can still run completeRequest and settle the store record. Without this the late message\n // is dropped (its id is gone from pendingWorkerRequests), so a successful late delivery would\n // leave the IDB/memory record behind for sendStoredEvents to re-upload as duplicate replay data.\n private timedOutWorkerRequests = new Map<string, SessionReplayDestinationContext>();\n // Server back-pressure state, fed by the X-Session-Replay-Event-Skipped header on 200s.\n // The server uses this header (instead of 4xx) to signal a deliberate no-retry drop so SDKs\n // don't retry-storm. We honor it here by slowing or stopping our flush schedule.\n private flushPauseUntilMs = 0;\n // Set when schedule() defers a flush because we're inside a throttle pause; consumed by\n // flush() to merge same-session contexts before sending. Throttling is enforced by request\n // count, so collapsing N queued batches into one POST directly reduces throttle pressure.\n private mergeOnNextFlush = false;\n // Set by markCoalesceNextFlush() before the page-load backlog is enqueued; consumed by\n // flush() to coalesce the drained persisted sequences. Distinct from\n // mergeOnNextFlush so the drain isn't conflated with a throttle pause for logging.\n private coalesceNextFlush = false;\n // Gates the merge log to once per throttle pause window — mirroring the throttle log's\n // transition-only gating — so a sustained throttle scenario doesn't spam logs every cycle.\n private mergeLogFiredThisPause = false;\n private killedSessions = new Set<string | number>();\n\n constructor({\n trackServerUrl,\n loggerProvider,\n payloadBatcher,\n workerScript,\n enableTransportCompression,\n sendTimeoutMs,\n }: {\n trackServerUrl?: string;\n loggerProvider: ILogger;\n payloadBatcher?: PayloadBatcher;\n workerScript?: string;\n enableTransportCompression?: boolean;\n sendTimeoutMs?: number;\n }) {\n this.loggerProvider = loggerProvider;\n this.payloadBatcher = payloadBatcher ? payloadBatcher : (payload) => payload;\n this.trackServerUrl = trackServerUrl;\n this.enableTransportCompression = enableTransportCompression ?? true;\n this.sendTimeoutMs = sendTimeoutMs ?? SEND_TIMEOUT_MS;\n\n if (workerScript) {\n try {\n const blob = new Blob([workerScript], { type: 'application/javascript' });\n const blobUrl = URL.createObjectURL(blob);\n const worker = new Worker(blobUrl);\n worker.onerror = (e) => {\n e.preventDefault();\n loggerProvider.error(\n `Track destination worker failed, falling back to main-thread sending: ${e.message} (${e.filename}:${e.lineno})`,\n );\n worker.terminate();\n this.worker = undefined;\n // Resolve pending promises so flush() doesn't hang. Do NOT call completeRequest\n // here — the events were never delivered, so onComplete must not fire and the\n // IDB/memory store entries must remain intact for recovery by sendStoredEvents.\n for (const [, pending] of this.pendingWorkerRequests) {\n // Cancel the per-request timeout — onerror already settles every pending\n // promise, so leaving the timer armed would fire a spurious timeout warn later.\n if (pending.timeout) clearTimeout(pending.timeout);\n loggerProvider.warn(`Session replay event send failed due to worker crash: ${e.message}`);\n pending.resolve();\n }\n this.pendingWorkerRequests.clear();\n // The worker is gone, so no late completion can arrive for timed-out requests either.\n // Drop the retained contexts to free memory; their store records stay intact (we never\n // completeRequest here) so sendStoredEvents can recover them on next init.\n this.timedOutWorkerRequests.clear();\n };\n worker.onmessage = (e: MessageEvent<WorkerMessage>) => {\n const msg = e.data;\n if (msg.type === 'log') {\n loggerProvider.log(msg.message);\n } else if (msg.type === 'warn') {\n loggerProvider.warn(msg.message);\n } else if (msg.type === 'payload_too_large') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\n if (pending.timeout) clearTimeout(pending.timeout);\n this.handlePayloadTooLargeResponse(pending.context, msg.isWaf);\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n } else {\n // Late message for a request the main thread already timed out: the worker still\n // determined the payload was too large, so split-and-retry off the original record.\n const timedOut = this.timedOutWorkerRequests.get(msg.id);\n if (timedOut) {\n this.timedOutWorkerRequests.delete(msg.id);\n this.handlePayloadTooLargeResponse(timedOut, msg.isWaf);\n }\n }\n } else if (msg.type === 'complete') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\n if (pending.timeout) clearTimeout(pending.timeout);\n if (msg.skipCode !== undefined) {\n this.applyServerDirective(pending.context.sessionId, msg.skipCode);\n }\n this.completeRequest({ context: pending.context });\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n } else {\n // Late completion for a request the main thread already timed out. The worker's\n // actual outcome (delivered, or retries exhausted) is authoritative, so settle the\n // store record by it rather than leaving it behind for sendStoredEvents to re-upload.\n const timedOut = this.timedOutWorkerRequests.get(msg.id);\n if (timedOut) {\n this.timedOutWorkerRequests.delete(msg.id);\n if (msg.skipCode !== undefined) {\n this.applyServerDirective(timedOut.sessionId, msg.skipCode);\n }\n this.completeRequest({ context: timedOut });\n }\n }\n }\n };\n this.worker = worker;\n } catch (error) {\n loggerProvider.error('Failed to create track destination worker, falling back to main-thread sending:', error);\n }\n }\n }\n\n sendEventsList(destinationData: SessionReplayDestination) {\n this.addToQueue({\n ...destinationData,\n attempts: 0,\n timeout: 0,\n });\n }\n\n /**\n * Marks the next scheduled flush to coalesce its queued contexts by destination identity.\n * Callers use this immediately before enqueuing the page-load backlog drain (many persisted\n * sequences replayed back-to-back on init via sendStoredEvents). Because those enqueues are\n * synchronous and the flush is deferred to the next tick via schedule(0), the whole backlog\n * lands in the queue before the flag is consumed — collapsing N small POSTs into far fewer\n * and avoiding the request flood observed on page load. Steady-state live capture\n * never sets this flag, so its sending behavior is unchanged.\n *\n * Schedules a flush so the flag is always consumed by the next flush, even when every\n * backlog sequence is dropped before reaching the queue (e.g. all events oversized) and no\n * enqueue schedules one itself. Otherwise the flag would stick and a later unrelated live\n * flush could coalesce live batches as if they were a page-load drain.\n */\n markCoalesceNextFlush() {\n this.coalesceNextFlush = true;\n this.schedule(0);\n }\n\n /**\n * Sends events via navigator.sendBeacon on page exit.\n * Beacon payloads are sent as uncompressed JSON because sendBeacon does not support\n * Content-Encoding, and small incremental batches don't benefit much from compression.\n * The full snapshot has already been sent eagerly via fetch, so the beacon only needs\n * to cover the remaining incremental events since the last fetch flush.\n */\n sendBeacon({\n events,\n sessionId,\n deviceId,\n apiKey,\n serverZone,\n }: {\n events: string[];\n sessionId: string | number;\n deviceId: string;\n apiKey: string;\n serverZone?: keyof typeof ServerZone;\n }) {\n const MAX_BEACON_BYTES = 64 * 1024;\n const byteLength = (s: string) => new Blob([s]).size;\n let trimmedEvents = events;\n let payload = JSON.stringify({ version: 2, events: trimmedEvents });\n if (byteLength(payload) > MAX_BEACON_BYTES) {\n // Binary search for the largest prefix that fits within the beacon size limit.\n // Uses Blob.size to get the UTF-8 byte count, which is what sendBeacon measures.\n let lo = 0;\n let hi = trimmedEvents.length;\n while (lo < hi) {\n const mid = Math.floor((lo + hi + 1) / 2);\n if (byteLength(JSON.stringify({ version: 2, events: trimmedEvents.slice(0, mid) })) <= MAX_BEACON_BYTES) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n trimmedEvents = trimmedEvents.slice(0, lo);\n payload = JSON.stringify({ version: 2, events: trimmedEvents });\n this.loggerProvider.warn(\n `sendBeacon payload exceeded 64 KB limit, trimmed from ${events.length} to ${trimmedEvents.length} events`,\n );\n }\n if (trimmedEvents.length === 0) {\n return;\n }\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: 'replay',\n api_key: apiKey,\n });\n const serverUrl = `${getServerUrl(serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n const globalScope = getGlobalScope();\n try {\n // Wrap in a Blob to set Content-Type: application/json; a plain string would\n // cause the browser to send Content-Type: text/plain, which the server rejects.\n const payloadBlob = new Blob([payload], { type: 'application/json' });\n const sent = globalScope?.navigator?.sendBeacon?.(serverUrl, payloadBlob);\n if (sent === false) {\n this.loggerProvider.warn('sendBeacon failed to queue session replay payload');\n }\n } catch {\n // Best effort — no fallback on page exit.\n }\n }\n\n addToQueue(...list: SessionReplayDestinationContext[]) {\n const tryable = list.filter((context) => {\n if (this.killedSessions.has(context.sessionId)) {\n // Server has signaled capture_disabled or session_in_invalid_range for this session;\n // drop the batch (and clean up its IDB record via onComplete) instead of POSTing.\n this.completeRequest({\n context,\n err: SESSION_KILLED_MESSAGE,\n });\n return false;\n }\n if (context.attempts < (context.flushMaxRetries || 0)) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: MAX_RETRIES_EXCEEDED_MESSAGE,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n this.schedule(0);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n // If the server signaled throttling on a recent 200, defer the next flush until the\n // pause window ends. This lets us keep batching events without retry-storming the server.\n const pauseRemaining = this.flushPauseUntilMs - Date.now();\n const isPaused = pauseRemaining > 0;\n const effectiveTimeout = pauseRemaining > timeout ? pauseRemaining : timeout;\n if (isPaused) {\n // Mark the upcoming flush for merge: contexts piling up during the pause should\n // be coalesced into one POST per (session, device, api, type, ...) group.\n this.mergeOnNextFlush = true;\n }\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, effectiveTimeout);\n }\n\n async flush(useRetry = false) {\n let list = this.queue;\n this.queue = [];\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n if (this.mergeOnNextFlush) {\n this.mergeOnNextFlush = false;\n // A throttle merge already coalesces by identity; clear the drain flag too so the\n // same backlog isn't passed through a redundant second merge on a later flush.\n this.coalesceNextFlush = false;\n list = this.mergeQueueAfterThrottle(list);\n } else if (this.coalesceNextFlush) {\n this.coalesceNextFlush = false;\n list = this.mergeDrainBacklog(list);\n }\n\n for (const context of list) {\n await this.send(context, useRetry);\n }\n }\n\n /**\n * Post-throttle release path: coalesce the queued contexts, then log once per pause window.\n * Delegates the actual merging to the shared coalesceByIdentity helper so the drain path\n * (mergeDrainBacklog) and this path stay byte-for-byte identical in how they merge.\n */\n private mergeQueueAfterThrottle(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n const merged = this.coalesceByIdentity(list);\n if (merged.length < list.length && !this.mergeLogFiredThisPause) {\n this.mergeLogFiredThisPause = true;\n this.loggerProvider.log(\n `Session replay throttle pause ended; merged ${list.length} queued batches into ${merged.length} request(s)`,\n );\n }\n return merged;\n }\n\n /**\n * Page-load backlog drain path: on init the SDK replays every persisted sequence\n * from a prior session via sendStoredEvents. Enqueued back-to-back they would flush as N\n * separate POSTs — a request flood on page load that feeds volume spikes and throttling.\n * Reuses the exact same identity-grouped merge as the post-throttle path so the backlog\n * collapses into far fewer requests, with onComplete fanned out so each source IDB record\n * is still cleaned up exactly once on success.\n */\n private mergeDrainBacklog(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n const merged = this.coalesceByIdentity(list);\n if (merged.length < list.length) {\n this.loggerProvider.log(\n `Session replay coalesced ${list.length} persisted page-load backlog batches into ${merged.length} request(s)`,\n );\n }\n return merged;\n }\n\n /**\n * Coalesces queued contexts that share the same destination identity into fewer requests.\n * Identity covers everything that affects the request URL, routing, or per-request semantics\n * — splitting on any difference keeps each merged POST indistinguishable from the source\n * contexts it replaced.\n *\n * Greedy concat with a soft byte-length cap (`MERGE_AFTER_THROTTLE_SOFT_CAP`) keeps merged\n * payloads well under the 413 ceiling; on the rare oversized merge, the existing\n * split-and-retry path still bisects safely.\n *\n * The merged context's `onComplete` fans out to every source context's callback so each\n * underlying IDB sequence record is cleaned up exactly once on success.\n */\n private coalesceByIdentity(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n if (list.length <= 1) return list;\n\n const groups = new Map<string, SessionReplayDestinationContext[]>();\n for (const ctx of list) {\n // Anything that can change the URL, headers, or backend routing must split groups.\n const key = [\n ctx.sessionId,\n ctx.deviceId ?? '',\n ctx.apiKey ?? '',\n ctx.type,\n ctx.serverZone ?? '',\n ctx.sampleRate,\n ctx.version?.type ?? '',\n ctx.version?.version ?? '',\n ].join('|');\n const arr = groups.get(key);\n if (arr) arr.push(ctx);\n else groups.set(key, [ctx]);\n }\n\n const merged: SessionReplayDestinationContext[] = [];\n for (const group of groups.values()) {\n if (group.length === 1) {\n merged.push(group[0]);\n continue;\n }\n let current: SessionReplayDestinationContext | null = null;\n let currentBytes = 0;\n const flushCurrent = () => {\n if (current) merged.push(current);\n current = null;\n currentBytes = 0;\n };\n for (const ctx of group) {\n // UTF-8 byte size, matching how the events store enforces MAX_EVENT_LIST_SIZE\n // (see base-events-store.ts:getStringSize). Using char length would let a CJK/\n // emoji-heavy payload sneak past the cap.\n const ctxBytes = ctx.events.reduce((sum, e) => sum + new Blob([e]).size, 0);\n if (current === null) {\n // Reset attempts to 0 on the merged context so the post-throttle delivery gets a\n // full retry budget. The throttle pause has already absorbed back-pressure; the\n // alternative (Math.max of source attempts) would collapse N source budgets into\n // one and end-of-life all N IDB records on a single retry exhaustion.\n current = { ...ctx, events: [...ctx.events], attempts: 0 };\n currentBytes = ctxBytes;\n continue;\n }\n if (currentBytes + ctxBytes > MERGE_AFTER_THROTTLE_SOFT_CAP) {\n flushCurrent();\n current = { ...ctx, events: [...ctx.events], attempts: 0 };\n currentBytes = ctxBytes;\n continue;\n }\n const prevOnComplete = current.onComplete;\n const ctxOnComplete = ctx.onComplete;\n current.events = current.events.concat(ctx.events);\n currentBytes += ctxBytes;\n current.onComplete = async () => {\n // allSettled (not all): an underlying store cleanup failure in one shouldn't\n // block the other, and the merged onComplete is invoked fire-and-forget via\n // `void context.onComplete()` — a rejection from `Promise.all` would surface\n // as an unhandled rejection. Errors stay encapsulated in the source callbacks.\n await Promise.allSettled([prevOnComplete(), ctxOnComplete()]);\n };\n }\n flushCurrent();\n }\n\n return merged;\n }\n\n async send(context: SessionReplayDestinationContext, useRetry = true) {\n // A kill directive can arrive between flush() snapshotting the queue and us reaching\n // each context. Re-check before hitting the network so we don't waste POSTs on a\n // session the server has already told us to stop sending for.\n if (this.killedSessions.has(context.sessionId)) {\n return this.completeRequest({ context, err: SESSION_KILLED_MESSAGE });\n }\n const apiKey = context.apiKey;\n if (!apiKey) {\n return this.completeRequest({ context, err: MISSING_API_KEY_MESSAGE });\n }\n const deviceId = context.deviceId;\n if (!deviceId) {\n return this.completeRequest({ context, err: MISSING_DEVICE_ID_MESSAGE });\n }\n\n const payload = this.payloadBatcher({\n version: 1,\n events: context.events,\n });\n\n if (payload.events.length === 0) {\n this.completeRequest({ context });\n return;\n }\n\n const { worker } = this;\n if (worker) {\n return this.sendViaWorker(worker, context, payload, useRetry);\n }\n\n return this.sendOnMainThread(apiKey, deviceId, context, payload, useRetry);\n }\n\n private async sendViaWorker(\n worker: Worker,\n context: SessionReplayDestinationContext,\n payload: { version: number; events: unknown[] },\n useRetry: boolean,\n ): Promise<void> {\n const id = `${++this.sendIdCounter}`;\n return new Promise<void>((resolve) => {\n // The worker only resolves this promise when it posts back complete/payload_too_large.\n // If the worker's own fetch hangs, no message ever arrives, so this promise — and the\n // serial flush loop awaiting it — would hang forever while pendingWorkerRequests grows\n // unbounded. On timeout we resolve so flush() proceeds, but deliberately do NOT call\n // completeRequest: like the worker-crash path above, the events were never confirmed\n // delivered, so onComplete must not fire and the IDB/memory store must stay intact for\n // recovery by sendStoredEvents.\n // sendTimeoutMs <= 0 disables the wait timer entirely: we then rely solely on the\n // worker's own complete/payload_too_large message to settle. This reintroduces the\n // hang risk this timer guards against, so it is an explicit experiment opt-out.\n const timeout =\n this.sendTimeoutMs > 0\n ? setTimeout(() => {\n const pending = this.pendingWorkerRequests.get(id);\n if (!pending) return;\n this.pendingWorkerRequests.delete(id);\n // Retain the context so a *late* worker complete/payload_too_large can still settle the\n // store record (see timedOutWorkerRequests). Without this, a worker that ultimately\n // delivers after we stopped awaiting would leave the record behind → duplicate upload.\n this.rememberTimedOutRequest(id, pending.context);\n this.loggerProvider.warn(\n `Session replay worker send timed out after ${this.sendTimeoutMs}ms; leaving events for retry`,\n );\n pending.resolve();\n }, this.sendTimeoutMs)\n : undefined;\n this.pendingWorkerRequests.set(id, { context, resolve, timeout });\n worker.postMessage({\n type: 'send',\n id,\n payload,\n useRetry,\n context: {\n apiKey: context.apiKey,\n deviceId: context.deviceId,\n sessionId: context.sessionId,\n events: context.events,\n eventType: context.type,\n flushMaxRetries: context.flushMaxRetries ?? 0,\n sampleRate: context.sampleRate,\n serverZone: context.serverZone,\n trackServerUrl: this.trackServerUrl,\n version: context.version,\n currentUrl: getCurrentUrl(),\n sdkVersion: VERSION,\n enableTransportCompression: this.enableTransportCompression,\n sendTimeoutMs: this.sendTimeoutMs,\n },\n });\n });\n }\n\n private rememberTimedOutRequest(id: string, context: SessionReplayDestinationContext) {\n this.timedOutWorkerRequests.set(id, context);\n // Bound memory: a wedged worker that never replies must not let this grow without limit.\n // Map preserves insertion order, so deleting the first key evicts the oldest entry.\n if (this.timedOutWorkerRequests.size > MAX_TIMED_OUT_WORKER_REQUESTS) {\n for (const oldest of this.timedOutWorkerRequests.keys()) {\n this.timedOutWorkerRequests.delete(oldest);\n break;\n }\n }\n }\n\n private async sendOnMainThread(\n apiKey: string,\n deviceId: string,\n context: SessionReplayDestinationContext,\n payload: { version: number; events: unknown[] },\n useRetry: boolean,\n ): Promise<void> {\n const url = getCurrentUrl();\n const version = VERSION;\n const sampleRate = context.sampleRate;\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: `${context.sessionId}`,\n type: `${context.type}`,\n });\n const sessionReplayLibrary = `${context.version?.type ?? 'standalone'}/${context.version?.version ?? version}`;\n\n try {\n const payloadJson = JSON.stringify(payload);\n // Only await gzip when (a) the customer hasn't opted out and (b) CompressionStream\n // is actually available; skipping the await entirely preserves the synchronous\n // fast-path for browsers/environments (e.g. Jest) that don't support it, keeping\n // retry-timing tests unaffected.\n const globalScope = getGlobalScope();\n const gzipped =\n this.enableTransportCompression && globalScope && 'CompressionStream' in globalScope\n ? await gzipJson(payloadJson, globalScope)\n : null;\n const payloadSize = gzipped ? gzipped.byteLength : new Blob([payloadJson]).size;\n // fetch() has no native timeout. A request stuck \"pending\" forever would block the\n // serial flush loop indefinitely (head-of-line blocking), so we abort it after\n // SEND_TIMEOUT_MS. The abort surfaces as an AbortError in the catch below, where it's\n // routed as a retryable network failure when useRetry is true.\n const controller = new AbortController();\n const options: RequestInit = {\n headers: {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n Authorization: `Bearer ${apiKey}`,\n 'X-Client-Version': version,\n 'X-Client-Library': sessionReplayLibrary,\n 'X-Client-Url': url.substring(0, MAX_URL_LENGTH), // limit url length to 1000 characters to avoid ELB 400 error\n 'X-Client-Sample-Rate': `${sampleRate}`,\n 'X-Sampling-Hash-Alg': 'xxhash32',\n ...(gzipped ? { 'Content-Encoding': 'gzip' } : {}),\n },\n body: (gzipped ?? payloadJson) as BodyInit,\n method: 'POST',\n // keepalive lets the request survive page navigation, preventing 499 (client-closed) errors.\n // Must stay under the browser's 64 KB keepalive budget; large payloads skip it.\n keepalive: payloadSize <= MAX_KEEPALIVE_BYTES,\n signal: controller.signal,\n };\n\n const serverUrl = `${getServerUrl(context.serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n // Final defensive guard: never POST a zero-event payload. Upper layers (events-manager\n // oversize filter, send()'s post-batcher check, store-layer filters) should already\n // have caught this — but SR-4284 fleet logs show ~416 empty-body 400s/24h slipping\n // through somehow, so a cheap belt-and-braces check immediately before fetch prevents\n // any future regression from re-introducing the same server rejection.\n if (payload.events.length === 0) {\n this.completeRequest({ context });\n return;\n }\n // sendTimeoutMs <= 0 disables the abort: the request can then hang indefinitely\n // (head-of-line blocking the serial flush). Explicit experiment opt-out only.\n const sendTimeout =\n this.sendTimeoutMs > 0\n ? setTimeout(() => {\n controller.abort();\n }, this.sendTimeoutMs)\n : undefined;\n let res: Response;\n try {\n res = await fetch(serverUrl, options);\n } finally {\n // Clear on success and on error alike so a settled request never leaves an armed\n // timer that would abort a later reused controller or fire a stray callback.\n if (sendTimeout) clearTimeout(sendTimeout);\n }\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE });\n return;\n }\n if (res.status >= 200 && res.status < 300) {\n const skipCode = res.headers?.get?.(EVENT_SKIPPED_HEADER) ?? null;\n this.applyServerDirective(context.sessionId, skipCode);\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n let responseBody = '';\n if (res.status === 413) {\n try {\n responseBody = await res.text();\n } catch {\n // best effort\n }\n }\n await this.handleReponse(res.status, context, responseBody);\n }\n } catch (e) {\n // A send timeout aborts the fetch, which rejects with an AbortError. Treat that as a\n // transient network failure and route it through the same retry budget/backoff as a\n // 5xx (so a single stalled request doesn't permanently drop the batch) when retries\n // are enabled. completeRequest fires onComplete exactly once via either branch\n // (handleOtherResponse only completes on retry exhaustion), so onComplete can't fire\n // twice. Non-abort errors keep the original complete-with-error behavior.\n // Browsers reject an aborted fetch with a DOMException named 'AbortError', which is NOT an\n // Error instance — an `instanceof Error` check would misroute every send-timeout abort to\n // the fatal completeRequest path, defeating the retry. Match on the name across any thrown\n // object (DOMException or Error) instead.\n const isAbort = !!e && typeof e === 'object' && (e as { name?: unknown }).name === 'AbortError';\n if (isAbort && useRetry) {\n await this.handleOtherResponse(context);\n } else {\n this.completeRequest({ context, err: e as string });\n }\n }\n }\n\n async handleReponse(status: number, context: SessionReplayDestinationContext, responseBody = '') {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n case Status.Failed:\n case Status.Timeout: // 408: server timed out waiting for request, data not received\n case Status.RateLimit: // 429: retry with existing backoff rather than silently dropping\n await this.handleOtherResponse(context);\n break;\n case Status.PayloadTooLarge:\n this.handlePayloadTooLargeResponse(context, WAF_PAYLOAD_TOO_LARGE_PATTERN.test(responseBody));\n break;\n default:\n // 499 (client closed connection / upstream dropped) is also retryable\n if (status === 499) {\n await this.handleOtherResponse(context);\n break;\n }\n this.completeRequest({ context, err: UNEXPECTED_NETWORK_ERROR_MESSAGE });\n }\n }\n\n handlePayloadTooLargeResponse(context: SessionReplayDestinationContext, isWaf: boolean): void {\n const source = isWaf ? 'WAF (compressed payload too large)' : 'server (event too large)';\n const totalSizeKB = Math.round(context.events.reduce((sum, e) => sum + e.length, 0) / KB_SIZE);\n\n if (!isWaf) {\n this.completeRequest({\n context,\n err: `Session replay event batch dropped: ${source} rejected payload (${context.events.length} events, ${totalSizeKB} KB) — not retrying non-WAF 413`,\n });\n return;\n }\n\n if (context.events.length === 1) {\n this.completeRequest({\n context,\n err: `Session replay event dropped: single event (${totalSizeKB} KB, 1 event) rejected by ${source} — cannot split further`,\n });\n return;\n }\n\n this.loggerProvider.warn(\n `Session replay event batch rejected by ${source} (${context.events.length} events, ${totalSizeKB} KB total) — splitting and retrying`,\n );\n\n // Clean up the original IDB record, then re-enqueue both halves as new in-memory batches.\n // For a merged-on-throttle context (mergeQueueAfterThrottle), this onComplete is the\n // fanned-out callback covering N source IDB records — they'll all be cleaned up here.\n // Halves get noop onCompletes, so a page-close between this cleanup and a half delivery\n // means up to N source sequences are lost. The merge soft cap (1.4MB chars) is well under\n // the 10MB compressed 413 ceiling, so a 413 on a merged context is exceedingly rare in\n // practice; the alternative — deferring source cleanup until both halves complete — would\n // significantly complicate the retry path for marginal benefit.\n void context.onComplete();\n const noop = (): Promise<void> => Promise.resolve();\n const mid = Math.floor(context.events.length / 2);\n this.sendEventsList({ ...context, events: context.events.slice(0, mid), onComplete: noop });\n this.sendEventsList({ ...context, events: context.events.slice(mid), onComplete: noop });\n }\n\n handleSuccessResponse(context: SessionReplayDestinationContext) {\n const sizeOfEventsList = Math.round(new Blob(context.events).size / KB_SIZE);\n this.completeRequest({\n context,\n success: `Session replay event batch tracked successfully for session id ${context.sessionId}, size of events: ${sizeOfEventsList} KB`,\n });\n }\n\n async handleOtherResponse(context: SessionReplayDestinationContext) {\n const delay = Math.random() * context.attempts * this.retryTimeout;\n context.attempts++;\n if (context.attempts > (context.flushMaxRetries || 0)) {\n this.completeRequest({ context, err: MAX_RETRIES_EXCEEDED_MESSAGE });\n return;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n await this.send(context, true);\n }\n\n completeRequest({\n context,\n err,\n success,\n }: {\n context: SessionReplayDestinationContext;\n err?: string;\n success?: string;\n }) {\n void context.onComplete();\n if (err) {\n this.loggerProvider.warn(err);\n } else if (success) {\n this.loggerProvider.log(success);\n }\n }\n\n /**\n * Applies the server's back-pressure signal carried on a 200 response.\n *\n * - `EVENT_SKIP_CODE_THROTTLED` (server-side rate limit): pause the flush schedule\n * for `THROTTLED_FLUSH_PAUSE_MS` so we keep batching events instead of retry-storming.\n * - `EVENT_SKIP_CODE_CAPTURE_DISABLED` / `EVENT_SKIP_CODE_INVALID_RANGE`: hard kill\n * switch for this session — drop the queued contexts and stop accepting new ones.\n * New sessions are unaffected.\n * - `null` (clean 200, no header): clear any throttle pause; subsequent flushes resume\n * on the normal cadence.\n */\n private applyServerDirective(sessionId: string | number, skipCode: string | null) {\n if (skipCode === null) {\n this.flushPauseUntilMs = 0;\n this.mergeLogFiredThisPause = false;\n return;\n }\n if (skipCode === EVENT_SKIP_CODE_THROTTLED) {\n const wasInPause = this.flushPauseUntilMs > Date.now();\n this.flushPauseUntilMs = Date.now() + THROTTLED_FLUSH_PAUSE_MS;\n // Log only on pause-state transitions — a throttled server may reply to many\n // batches per minute, and one log per batch would flood the console.\n if (!wasInPause) {\n this.loggerProvider.log(\n `Session replay throttled by server; pausing flush schedule for ${THROTTLED_FLUSH_PAUSE_MS / 1000}s`,\n );\n }\n return;\n }\n if (skipCode === EVENT_SKIP_CODE_CAPTURE_DISABLED || skipCode === EVENT_SKIP_CODE_INVALID_RANGE) {\n this.killSession(sessionId, skipCode);\n }\n // Unknown skip codes are ignored — the server may add new ones, and our default\n // behavior (treat as a normal 200) preserves throughput rather than penalizing the\n // session for a code we don't recognize.\n }\n\n private killSession(sessionId: string | number, skipCode: string) {\n if (this.killedSessions.has(sessionId)) return;\n this.killedSessions.add(sessionId);\n // Set preserves insertion order, so deleting the first key evicts the oldest entry.\n if (this.killedSessions.size > MAX_KILLED_SESSIONS) {\n for (const oldest of this.killedSessions) {\n this.killedSessions.delete(oldest);\n break;\n }\n }\n this.loggerProvider.log(\n `Session replay capture stopped for session ${sessionId} by server directive ${skipCode}; remaining events will be dropped`,\n );\n // Drain any queued contexts for this session so their IDB records get cleaned up\n // via onComplete, instead of sitting in the queue waiting for a flush we'll never make.\n const remaining: SessionReplayDestinationContext[] = [];\n for (const queued of this.queue) {\n if (queued.sessionId === sessionId) {\n this.completeRequest({ context: queued, err: SESSION_KILLED_MESSAGE });\n } else {\n remaining.push(queued);\n }\n }\n this.queue = remaining;\n }\n}\n"]}
1
+ {"version":3,"file":"track-destination.js","sourceRoot":"","sources":["../../src/track-destination.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, getGlobalScope, ILogger, ServerZone, Status } from '@amplitude/analytics-core';\nimport { getCurrentUrl, getServerUrl } from './helpers';\nimport {\n MAX_RETRIES_EXCEEDED_MESSAGE,\n MISSING_API_KEY_MESSAGE,\n MISSING_DEVICE_ID_MESSAGE,\n SESSION_KILLED_MESSAGE,\n UNEXPECTED_ERROR_MESSAGE,\n UNEXPECTED_NETWORK_ERROR_MESSAGE,\n} from './messages';\nimport {\n SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination,\n SessionReplayDestination,\n SessionReplayDestinationContext,\n} from './typings/session-replay';\nimport { VERSION } from './version';\nimport {\n MAX_URL_LENGTH,\n KB_SIZE,\n MAX_KEEPALIVE_BYTES,\n WAF_PAYLOAD_TOO_LARGE_PATTERN,\n EVENT_SKIPPED_HEADER,\n EVENT_SKIP_CODE_THROTTLED,\n EVENT_SKIP_CODE_INVALID_RANGE,\n EVENT_SKIP_CODE_CAPTURE_DISABLED,\n THROTTLED_FLUSH_PAUSE_MS,\n MERGE_AFTER_THROTTLE_SOFT_CAP,\n SEND_TIMEOUT_MS,\n} from './constants';\nimport { gzipJson } from './utils/gzip';\nimport { SessionReplaySendEventsHandler } from './config/types';\n\ninterface WorkerCompleteMessage {\n type: 'complete';\n id: string;\n err?: string;\n // null when the response was a clean 200 (no skip header), undefined when the\n // request did not produce a 200, otherwise the server's skip-code string.\n skipCode?: string | null;\n}\ninterface WorkerLogMessage {\n type: 'log' | 'warn';\n id: string;\n message: string;\n}\ninterface WorkerPayloadTooLargeMessage {\n type: 'payload_too_large';\n id: string;\n isWaf: boolean;\n}\n// Worker asks the main thread to run the custom transport for one network attempt (the\n// callback can't cross postMessage, so it lives on the main thread). Replied to with a\n// 'fetch-response' message posted back into the worker.\ninterface WorkerFetchRequestMessage {\n type: 'fetch-request';\n requestId: string;\n url: string;\n method: 'POST';\n headers: Record<string, string>;\n // string | Uint8Array (not BodyInit) so it stays structured-cloneable across postMessage.\n body: string | Uint8Array;\n keepalive: boolean;\n}\ntype WorkerMessage =\n | WorkerCompleteMessage\n | WorkerLogMessage\n | WorkerPayloadTooLargeMessage\n | WorkerFetchRequestMessage;\n\nexport type PayloadBatcher = ({ version, events }: { version: number; events: string[] }) => {\n version: number;\n events: unknown[];\n};\n\n// Bounded so a long-lived SDK instance can't accumulate kill records indefinitely;\n// sessions are time-bounded in practice, this cap is just a defensive ceiling.\nconst MAX_KILLED_SESSIONS = 256;\n\n// Defensive ceiling on retained timed-out worker requests (see timedOutWorkerRequests).\n// In normal operation each entry is removed when the worker's late message arrives; this\n// cap only guards the pathological case of a wedged worker that never replies at all.\nconst MAX_TIMED_OUT_WORKER_REQUESTS = 256;\n\n// Settles with `promise`, but rejects early with an AbortError when `signal` fires. Used to apply\n// the send timeout to a custom transport whose own promise can't be cancelled: a hung transport\n// then surfaces as a retryable timeout (matching the built-in fetch and worker delegation paths)\n// instead of blocking the serial flush loop. The transport's promise keeps running; we just stop\n// awaiting it. `signal` is always supplied with the send-timeout controller's signal.\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n // Match how browsers reject an aborted fetch (DOMException 'AbortError'); sendOnMainThread's\n // catch keys off the name to route it through the retry budget rather than failing fatally.\n const err = new Error('Custom session replay transport aborted by send timeout');\n err.name = 'AbortError';\n reject(err);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n (err) => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\nexport class SessionReplayTrackDestination implements AmplitudeSessionReplayTrackDestination {\n loggerProvider: ILogger;\n storageKey = '';\n trackServerUrl?: string;\n retryTimeout = 1000;\n // Defaults to true (gzip enabled) so existing call sites that don't pass the flag\n // retain pre-flag behavior. The local-config layer also defaults to true; this\n // belt-and-braces default protects direct constructor callers (e.g. tests).\n private enableTransportCompression: boolean;\n // Milliseconds before an in-flight send is aborted; <= 0 disables the abort/timeout.\n // Defaults to SEND_TIMEOUT_MS. Configurable so large slow-but-succeeding uploads aren't\n // killed (and retried) at an over-aggressive default. See config.sendTimeoutMs.\n private sendTimeoutMs: number;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n payloadBatcher: PayloadBatcher;\n queue: SessionReplayDestinationContext[] = [];\n private worker?: Worker;\n private sendIdCounter = 0;\n private pendingWorkerRequests = new Map<\n string,\n { context: SessionReplayDestinationContext; resolve: () => void; timeout?: ReturnType<typeof setTimeout> }\n >();\n // Requests the main thread stopped awaiting after SEND_TIMEOUT_MS (so the serial flush\n // loop could proceed) but whose worker may still be retrying in the background. We keep\n // the context — bounded, like killedSessions — so a *late* worker complete/payload_too_large\n // can still run completeRequest and settle the store record. Without this the late message\n // is dropped (its id is gone from pendingWorkerRequests), so a successful late delivery would\n // leave the IDB/memory record behind for sendStoredEvents to re-upload as duplicate replay data.\n private timedOutWorkerRequests = new Map<string, SessionReplayDestinationContext>();\n // Server back-pressure state, fed by the X-Session-Replay-Event-Skipped header on 200s.\n // The server uses this header (instead of 4xx) to signal a deliberate no-retry drop so SDKs\n // don't retry-storm. We honor it here by slowing or stopping our flush schedule.\n private flushPauseUntilMs = 0;\n // Set when schedule() defers a flush because we're inside a throttle pause; consumed by\n // flush() to merge same-session contexts before sending. Throttling is enforced by request\n // count, so collapsing N queued batches into one POST directly reduces throttle pressure.\n private mergeOnNextFlush = false;\n // Set by markCoalesceNextFlush() before the page-load backlog is enqueued; consumed by\n // flush() to coalesce the drained persisted sequences. Distinct from\n // mergeOnNextFlush so the drain isn't conflated with a throttle pause for logging.\n private coalesceNextFlush = false;\n // Gates the merge log to once per throttle pause window — mirroring the throttle log's\n // transition-only gating — so a sustained throttle scenario doesn't spam logs every cycle.\n private mergeLogFiredThisPause = false;\n private killedSessions = new Set<string | number>();\n // Optional customer-supplied transport. When set, it replaces the internal fetch for every\n // event-upload attempt; retry/response handling stays where it is, so the callback sits\n // below retry and is invoked once per attempt.\n private handleSendEvents?: SessionReplaySendEventsHandler;\n\n constructor({\n trackServerUrl,\n loggerProvider,\n payloadBatcher,\n workerScript,\n enableTransportCompression,\n sendTimeoutMs,\n handleSendEvents,\n }: {\n trackServerUrl?: string;\n loggerProvider: ILogger;\n payloadBatcher?: PayloadBatcher;\n workerScript?: string;\n enableTransportCompression?: boolean;\n sendTimeoutMs?: number;\n handleSendEvents?: SessionReplaySendEventsHandler;\n }) {\n this.loggerProvider = loggerProvider;\n this.payloadBatcher = payloadBatcher ? payloadBatcher : (payload) => payload;\n this.trackServerUrl = trackServerUrl;\n this.enableTransportCompression = enableTransportCompression ?? true;\n this.sendTimeoutMs = sendTimeoutMs ?? SEND_TIMEOUT_MS;\n this.handleSendEvents = handleSendEvents;\n\n if (workerScript) {\n try {\n const blob = new Blob([workerScript], { type: 'application/javascript' });\n const blobUrl = URL.createObjectURL(blob);\n const worker = new Worker(blobUrl);\n worker.onerror = (e) => {\n e.preventDefault();\n loggerProvider.error(\n `Track destination worker failed, falling back to main-thread sending: ${e.message} (${e.filename}:${e.lineno})`,\n );\n worker.terminate();\n this.worker = undefined;\n // Resolve pending promises so flush() doesn't hang. Do NOT call completeRequest\n // here — the events were never delivered, so onComplete must not fire and the\n // IDB/memory store entries must remain intact for recovery by sendStoredEvents.\n for (const [, pending] of this.pendingWorkerRequests) {\n // Cancel the per-request timeout — onerror already settles every pending\n // promise, so leaving the timer armed would fire a spurious timeout warn later.\n if (pending.timeout) clearTimeout(pending.timeout);\n loggerProvider.warn(`Session replay event send failed due to worker crash: ${e.message}`);\n pending.resolve();\n }\n this.pendingWorkerRequests.clear();\n // The worker is gone, so no late completion can arrive for timed-out requests either.\n // Drop the retained contexts to free memory; their store records stay intact (we never\n // completeRequest here) so sendStoredEvents can recover them on next init.\n this.timedOutWorkerRequests.clear();\n };\n worker.onmessage = (e: MessageEvent<WorkerMessage>) => {\n const msg = e.data;\n if (msg.type === 'log') {\n loggerProvider.log(msg.message);\n } else if (msg.type === 'warn') {\n loggerProvider.warn(msg.message);\n } else if (msg.type === 'payload_too_large') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\n if (pending.timeout) clearTimeout(pending.timeout);\n this.handlePayloadTooLargeResponse(pending.context, msg.isWaf);\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n } else {\n // Late message for a request the main thread already timed out: the worker still\n // determined the payload was too large, so split-and-retry off the original record.\n const timedOut = this.timedOutWorkerRequests.get(msg.id);\n if (timedOut) {\n this.timedOutWorkerRequests.delete(msg.id);\n this.handlePayloadTooLargeResponse(timedOut, msg.isWaf);\n }\n }\n } else if (msg.type === 'complete') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\n if (pending.timeout) clearTimeout(pending.timeout);\n if (msg.skipCode !== undefined) {\n this.applyServerDirective(pending.context.sessionId, msg.skipCode);\n }\n this.completeRequest({ context: pending.context });\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n } else {\n // Late completion for a request the main thread already timed out. The worker's\n // actual outcome (delivered, or retries exhausted) is authoritative, so settle the\n // store record by it rather than leaving it behind for sendStoredEvents to re-upload.\n const timedOut = this.timedOutWorkerRequests.get(msg.id);\n if (timedOut) {\n this.timedOutWorkerRequests.delete(msg.id);\n if (msg.skipCode !== undefined) {\n this.applyServerDirective(timedOut.sessionId, msg.skipCode);\n }\n this.completeRequest({ context: timedOut });\n }\n }\n } else if (msg.type === 'fetch-request') {\n // Worker is delegating one network attempt to the custom transport (which lives on\n // the main thread). Run it and post the result back into the worker's retry loop.\n // Guard the fire-and-forget call: if posting the result back fails (e.g. the worker\n // was terminated mid-flight), surface it to the logger instead of leaving an\n // unhandled rejection.\n void this.handleDelegatedFetch(worker, msg).catch((e) => {\n loggerProvider.warn('Failed to handle delegated session replay fetch:', e);\n });\n }\n };\n this.worker = worker;\n } catch (error) {\n loggerProvider.error('Failed to create track destination worker, falling back to main-thread sending:', error);\n }\n }\n }\n\n sendEventsList(destinationData: SessionReplayDestination) {\n this.addToQueue({\n ...destinationData,\n attempts: 0,\n timeout: 0,\n });\n }\n\n /**\n * Marks the next scheduled flush to coalesce its queued contexts by destination identity.\n * Callers use this immediately before enqueuing the page-load backlog drain (many persisted\n * sequences replayed back-to-back on init via sendStoredEvents). Because those enqueues are\n * synchronous and the flush is deferred to the next tick via schedule(0), the whole backlog\n * lands in the queue before the flag is consumed — collapsing N small POSTs into far fewer\n * and avoiding the request flood observed on page load. Steady-state live capture\n * never sets this flag, so its sending behavior is unchanged.\n *\n * Schedules a flush so the flag is always consumed by the next flush, even when every\n * backlog sequence is dropped before reaching the queue (e.g. all events oversized) and no\n * enqueue schedules one itself. Otherwise the flag would stick and a later unrelated live\n * flush could coalesce live batches as if they were a page-load drain.\n */\n markCoalesceNextFlush() {\n this.coalesceNextFlush = true;\n this.schedule(0);\n }\n\n /**\n * Sends events via navigator.sendBeacon on page exit.\n * Beacon payloads are sent as uncompressed JSON because sendBeacon does not support\n * Content-Encoding, and small incremental batches don't benefit much from compression.\n * The full snapshot has already been sent eagerly via fetch, so the beacon only needs\n * to cover the remaining incremental events since the last fetch flush.\n */\n sendBeacon({\n events,\n sessionId,\n deviceId,\n apiKey,\n serverZone,\n }: {\n events: string[];\n sessionId: string | number;\n deviceId: string;\n apiKey: string;\n serverZone?: keyof typeof ServerZone;\n }) {\n const MAX_BEACON_BYTES = 64 * 1024;\n const byteLength = (s: string) => new Blob([s]).size;\n let trimmedEvents = events;\n let payload = JSON.stringify({ version: 2, events: trimmedEvents });\n if (byteLength(payload) > MAX_BEACON_BYTES) {\n // Binary search for the largest prefix that fits within the beacon size limit.\n // Uses Blob.size to get the UTF-8 byte count, which is what sendBeacon measures.\n let lo = 0;\n let hi = trimmedEvents.length;\n while (lo < hi) {\n const mid = Math.floor((lo + hi + 1) / 2);\n if (byteLength(JSON.stringify({ version: 2, events: trimmedEvents.slice(0, mid) })) <= MAX_BEACON_BYTES) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n trimmedEvents = trimmedEvents.slice(0, lo);\n payload = JSON.stringify({ version: 2, events: trimmedEvents });\n this.loggerProvider.warn(\n `sendBeacon payload exceeded 64 KB limit, trimmed from ${events.length} to ${trimmedEvents.length} events`,\n );\n }\n if (trimmedEvents.length === 0) {\n return;\n }\n // Custom-transport page-exit path: navigator.sendBeacon cannot carry custom headers, so a\n // JWT customer's exit batch would go out unauthenticated and be rejected by their proxy.\n // Instead, route it through the callback with keepalive (which survives unload AND carries\n // headers). Mirrors the main-send request shape: Authorization header + device_id/session_id/\n // type params (api_key is NOT placed in the URL, unlike the legacy beacon path below).\n if (this.handleSendEvents) {\n const exitParams = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: 'replay',\n });\n const exitUrl = `${getServerUrl(serverZone, this.trackServerUrl)}?${exitParams.toString()}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n Authorization: `Bearer ${apiKey}`,\n };\n this.loggerProvider.debug(\n `Routing session replay exit batch (${trimmedEvents.length} events) through custom transport for session id ${sessionId}.`,\n );\n try {\n // Fire-and-forget: we cannot await during unload. The request is well under 64 KB\n // (trimmed above) and keepalive: true is requested so it survives page teardown.\n void this.handleSendEvents({ url: exitUrl, method: 'POST', headers, body: payload, keepalive: true }).catch(\n (e) => {\n // best effort on exit, but still surface the failure so it's diagnosable in logs.\n this.loggerProvider.warn('Custom transport failed to send session replay exit batch:', e);\n },\n );\n } catch (e) {\n this.loggerProvider.warn('Custom transport threw while sending session replay exit batch:', e);\n }\n return;\n }\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: 'replay',\n api_key: apiKey,\n });\n const serverUrl = `${getServerUrl(serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n const globalScope = getGlobalScope();\n try {\n // Wrap in a Blob to set Content-Type: application/json; a plain string would\n // cause the browser to send Content-Type: text/plain, which the server rejects.\n const payloadBlob = new Blob([payload], { type: 'application/json' });\n const sent = globalScope?.navigator?.sendBeacon?.(serverUrl, payloadBlob);\n if (sent === false) {\n this.loggerProvider.warn('sendBeacon failed to queue session replay payload');\n }\n } catch {\n // Best effort — no fallback on page exit.\n }\n }\n\n addToQueue(...list: SessionReplayDestinationContext[]) {\n const tryable = list.filter((context) => {\n if (this.killedSessions.has(context.sessionId)) {\n // Server has signaled capture_disabled or session_in_invalid_range for this session;\n // drop the batch (and clean up its IDB record via onComplete) instead of POSTing.\n this.completeRequest({\n context,\n err: SESSION_KILLED_MESSAGE,\n });\n return false;\n }\n if (context.attempts < (context.flushMaxRetries || 0)) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: MAX_RETRIES_EXCEEDED_MESSAGE,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n this.schedule(0);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n // If the server signaled throttling on a recent 200, defer the next flush until the\n // pause window ends. This lets us keep batching events without retry-storming the server.\n const pauseRemaining = this.flushPauseUntilMs - Date.now();\n const isPaused = pauseRemaining > 0;\n const effectiveTimeout = pauseRemaining > timeout ? pauseRemaining : timeout;\n if (isPaused) {\n // Mark the upcoming flush for merge: contexts piling up during the pause should\n // be coalesced into one POST per (session, device, api, type, ...) group.\n this.mergeOnNextFlush = true;\n }\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, effectiveTimeout);\n }\n\n async flush(useRetry = false) {\n let list = this.queue;\n this.queue = [];\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n if (this.mergeOnNextFlush) {\n this.mergeOnNextFlush = false;\n // A throttle merge already coalesces by identity; clear the drain flag too so the\n // same backlog isn't passed through a redundant second merge on a later flush.\n this.coalesceNextFlush = false;\n list = this.mergeQueueAfterThrottle(list);\n } else if (this.coalesceNextFlush) {\n this.coalesceNextFlush = false;\n list = this.mergeDrainBacklog(list);\n }\n\n for (const context of list) {\n await this.send(context, useRetry);\n }\n }\n\n /**\n * Post-throttle release path: coalesce the queued contexts, then log once per pause window.\n * Delegates the actual merging to the shared coalesceByIdentity helper so the drain path\n * (mergeDrainBacklog) and this path stay byte-for-byte identical in how they merge.\n */\n private mergeQueueAfterThrottle(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n const merged = this.coalesceByIdentity(list);\n if (merged.length < list.length && !this.mergeLogFiredThisPause) {\n this.mergeLogFiredThisPause = true;\n this.loggerProvider.log(\n `Session replay throttle pause ended; merged ${list.length} queued batches into ${merged.length} request(s)`,\n );\n }\n return merged;\n }\n\n /**\n * Page-load backlog drain path: on init the SDK replays every persisted sequence\n * from a prior session via sendStoredEvents. Enqueued back-to-back they would flush as N\n * separate POSTs — a request flood on page load that feeds volume spikes and throttling.\n * Reuses the exact same identity-grouped merge as the post-throttle path so the backlog\n * collapses into far fewer requests, with onComplete fanned out so each source IDB record\n * is still cleaned up exactly once on success.\n */\n private mergeDrainBacklog(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n const merged = this.coalesceByIdentity(list);\n if (merged.length < list.length) {\n this.loggerProvider.log(\n `Session replay coalesced ${list.length} persisted page-load backlog batches into ${merged.length} request(s)`,\n );\n }\n return merged;\n }\n\n /**\n * Coalesces queued contexts that share the same destination identity into fewer requests.\n * Identity covers everything that affects the request URL, routing, or per-request semantics\n * — splitting on any difference keeps each merged POST indistinguishable from the source\n * contexts it replaced.\n *\n * Greedy concat with a soft byte-length cap (`MERGE_AFTER_THROTTLE_SOFT_CAP`) keeps merged\n * payloads well under the 413 ceiling; on the rare oversized merge, the existing\n * split-and-retry path still bisects safely.\n *\n * The merged context's `onComplete` fans out to every source context's callback so each\n * underlying IDB sequence record is cleaned up exactly once on success.\n */\n private coalesceByIdentity(list: SessionReplayDestinationContext[]): SessionReplayDestinationContext[] {\n if (list.length <= 1) return list;\n\n const groups = new Map<string, SessionReplayDestinationContext[]>();\n for (const ctx of list) {\n // Anything that can change the URL, headers, or backend routing must split groups.\n const key = [\n ctx.sessionId,\n ctx.deviceId ?? '',\n ctx.apiKey ?? '',\n ctx.type,\n ctx.serverZone ?? '',\n ctx.sampleRate,\n ctx.version?.type ?? '',\n ctx.version?.version ?? '',\n ].join('|');\n const arr = groups.get(key);\n if (arr) arr.push(ctx);\n else groups.set(key, [ctx]);\n }\n\n const merged: SessionReplayDestinationContext[] = [];\n for (const group of groups.values()) {\n if (group.length === 1) {\n merged.push(group[0]);\n continue;\n }\n let current: SessionReplayDestinationContext | null = null;\n let currentBytes = 0;\n const flushCurrent = () => {\n if (current) merged.push(current);\n current = null;\n currentBytes = 0;\n };\n for (const ctx of group) {\n // UTF-8 byte size, matching how the events store enforces MAX_EVENT_LIST_SIZE\n // (see base-events-store.ts:getStringSize). Using char length would let a CJK/\n // emoji-heavy payload sneak past the cap.\n const ctxBytes = ctx.events.reduce((sum, e) => sum + new Blob([e]).size, 0);\n if (current === null) {\n // Reset attempts to 0 on the merged context so the post-throttle delivery gets a\n // full retry budget. The throttle pause has already absorbed back-pressure; the\n // alternative (Math.max of source attempts) would collapse N source budgets into\n // one and end-of-life all N IDB records on a single retry exhaustion.\n current = { ...ctx, events: [...ctx.events], attempts: 0 };\n currentBytes = ctxBytes;\n continue;\n }\n if (currentBytes + ctxBytes > MERGE_AFTER_THROTTLE_SOFT_CAP) {\n flushCurrent();\n current = { ...ctx, events: [...ctx.events], attempts: 0 };\n currentBytes = ctxBytes;\n continue;\n }\n const prevOnComplete = current.onComplete;\n const ctxOnComplete = ctx.onComplete;\n current.events = current.events.concat(ctx.events);\n currentBytes += ctxBytes;\n current.onComplete = async () => {\n // allSettled (not all): an underlying store cleanup failure in one shouldn't\n // block the other, and the merged onComplete is invoked fire-and-forget via\n // `void context.onComplete()` — a rejection from `Promise.all` would surface\n // as an unhandled rejection. Errors stay encapsulated in the source callbacks.\n await Promise.allSettled([prevOnComplete(), ctxOnComplete()]);\n };\n }\n flushCurrent();\n }\n\n return merged;\n }\n\n async send(context: SessionReplayDestinationContext, useRetry = true) {\n // A kill directive can arrive between flush() snapshotting the queue and us reaching\n // each context. Re-check before hitting the network so we don't waste POSTs on a\n // session the server has already told us to stop sending for.\n if (this.killedSessions.has(context.sessionId)) {\n return this.completeRequest({ context, err: SESSION_KILLED_MESSAGE });\n }\n const apiKey = context.apiKey;\n if (!apiKey) {\n return this.completeRequest({ context, err: MISSING_API_KEY_MESSAGE });\n }\n const deviceId = context.deviceId;\n if (!deviceId) {\n return this.completeRequest({ context, err: MISSING_DEVICE_ID_MESSAGE });\n }\n\n const payload = this.payloadBatcher({\n version: 1,\n events: context.events,\n });\n\n if (payload.events.length === 0) {\n this.completeRequest({ context });\n return;\n }\n\n const { worker } = this;\n if (worker) {\n return this.sendViaWorker(worker, context, payload, useRetry);\n }\n\n return this.sendOnMainThread(apiKey, deviceId, context, payload, useRetry);\n }\n\n private async sendViaWorker(\n worker: Worker,\n context: SessionReplayDestinationContext,\n payload: { version: number; events: unknown[] },\n useRetry: boolean,\n ): Promise<void> {\n const id = `${++this.sendIdCounter}`;\n return new Promise<void>((resolve) => {\n // The worker only resolves this promise when it posts back complete/payload_too_large.\n // If the worker's own fetch hangs, no message ever arrives, so this promise — and the\n // serial flush loop awaiting it — would hang forever while pendingWorkerRequests grows\n // unbounded. On timeout we resolve so flush() proceeds, but deliberately do NOT call\n // completeRequest: like the worker-crash path above, the events were never confirmed\n // delivered, so onComplete must not fire and the IDB/memory store must stay intact for\n // recovery by sendStoredEvents.\n // sendTimeoutMs <= 0 disables the wait timer entirely: we then rely solely on the\n // worker's own complete/payload_too_large message to settle. This reintroduces the\n // hang risk this timer guards against, so it is an explicit experiment opt-out.\n const timeout =\n this.sendTimeoutMs > 0\n ? setTimeout(() => {\n const pending = this.pendingWorkerRequests.get(id);\n if (!pending) return;\n this.pendingWorkerRequests.delete(id);\n // Retain the context so a *late* worker complete/payload_too_large can still settle the\n // store record (see timedOutWorkerRequests). Without this, a worker that ultimately\n // delivers after we stopped awaiting would leave the record behind → duplicate upload.\n this.rememberTimedOutRequest(id, pending.context);\n this.loggerProvider.warn(\n `Session replay worker send timed out after ${this.sendTimeoutMs}ms; leaving events for retry`,\n );\n pending.resolve();\n }, this.sendTimeoutMs)\n : undefined;\n this.pendingWorkerRequests.set(id, { context, resolve, timeout });\n worker.postMessage({\n type: 'send',\n id,\n payload,\n useRetry,\n // Tell the worker to delegate each network attempt back to the main thread, where the\n // custom transport callback lives (functions can't cross postMessage). Absent/false\n // keeps the worker's own internal fetch — the unchanged path for existing integrations.\n useCustomTransport: !!this.handleSendEvents,\n context: {\n apiKey: context.apiKey,\n deviceId: context.deviceId,\n sessionId: context.sessionId,\n events: context.events,\n eventType: context.type,\n flushMaxRetries: context.flushMaxRetries ?? 0,\n sampleRate: context.sampleRate,\n serverZone: context.serverZone,\n trackServerUrl: this.trackServerUrl,\n version: context.version,\n currentUrl: getCurrentUrl(),\n sdkVersion: VERSION,\n enableTransportCompression: this.enableTransportCompression,\n sendTimeoutMs: this.sendTimeoutMs,\n },\n });\n });\n }\n\n private rememberTimedOutRequest(id: string, context: SessionReplayDestinationContext) {\n this.timedOutWorkerRequests.set(id, context);\n // Bound memory: a wedged worker that never replies must not let this grow without limit.\n // Map preserves insertion order, so deleting the first key evicts the oldest entry.\n if (this.timedOutWorkerRequests.size > MAX_TIMED_OUT_WORKER_REQUESTS) {\n for (const oldest of this.timedOutWorkerRequests.keys()) {\n this.timedOutWorkerRequests.delete(oldest);\n break;\n }\n }\n }\n\n // Runs the custom transport on the main thread for a single attempt the worker delegated,\n // then posts the result back into the worker's retry loop as a 'fetch-response'. We read only\n // what the worker's status handling needs: the skip header on a 2xx and the body text on a\n // 413 (for WAF detection). A thrown/rejected transport is reported as an error so the worker\n // surfaces it the same way a thrown fetch would (no retry) — matching the main-thread path.\n private async handleDelegatedFetch(worker: Worker, msg: WorkerFetchRequestMessage): Promise<void> {\n const { requestId, url, method, headers, body, keepalive } = msg;\n try {\n // In practice this.handleSendEvents is always set here: the worker only emits\n // 'fetch-request' when useCustomTransport (= !!this.handleSendEvents) was true. The\n // built-in fetch is a defensive fallback for the impossible case so we never accidentally\n // drop a delegated send; it is not a supported \"run without a transport\" path.\n let res: Response;\n if (this.handleSendEvents) {\n res = await this.handleSendEvents({ url, method, headers, body, keepalive });\n } else {\n // Defensive only: the worker emits 'fetch-request' solely when useCustomTransport is set,\n // so this branch shouldn't be reachable. Warn so a regression that delegates without a\n // transport is diagnosable rather than silently routing to the built-in fetch.\n this.loggerProvider.warn(\n 'Delegated session replay fetch received without a custom transport configured; falling back to built-in fetch.',\n );\n res = await fetch(url, { method, headers, body, keepalive });\n }\n const status = res.status;\n let skipHeader: string | null = null;\n let responseBody = '';\n if (status >= 200 && status < 300) {\n skipHeader = res.headers?.get?.(EVENT_SKIPPED_HEADER) ?? null;\n }\n if (status === 413) {\n try {\n responseBody = await res.text();\n } catch {\n // best effort\n }\n }\n this.loggerProvider.debug(`Delegated session replay fetch (request ${requestId}) returned status ${status}.`);\n worker.postMessage({ type: 'fetch-response', requestId, status, skipHeader, body: responseBody });\n } catch (e) {\n this.loggerProvider.debug(`Delegated session replay fetch (request ${requestId}) failed:`, e);\n worker.postMessage({\n type: 'fetch-response',\n requestId,\n status: 0,\n skipHeader: null,\n body: String(e),\n error: true,\n });\n }\n }\n\n private async sendOnMainThread(\n apiKey: string,\n deviceId: string,\n context: SessionReplayDestinationContext,\n payload: { version: number; events: unknown[] },\n useRetry: boolean,\n ): Promise<void> {\n const url = getCurrentUrl();\n const version = VERSION;\n const sampleRate = context.sampleRate;\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: `${context.sessionId}`,\n type: `${context.type}`,\n });\n const sessionReplayLibrary = `${context.version?.type ?? 'standalone'}/${context.version?.version ?? version}`;\n\n try {\n const payloadJson = JSON.stringify(payload);\n // Only await gzip when (a) the customer hasn't opted out and (b) CompressionStream\n // is actually available; skipping the await entirely preserves the synchronous\n // fast-path for browsers/environments (e.g. Jest) that don't support it, keeping\n // retry-timing tests unaffected.\n const globalScope = getGlobalScope();\n const gzipped =\n this.enableTransportCompression && globalScope && 'CompressionStream' in globalScope\n ? await gzipJson(payloadJson, globalScope)\n : null;\n const payloadSize = gzipped ? gzipped.byteLength : new Blob([payloadJson]).size;\n // fetch() has no native timeout. A request stuck \"pending\" forever would block the\n // serial flush loop indefinitely (head-of-line blocking), so we abort it after\n // SEND_TIMEOUT_MS. The abort surfaces as an AbortError in the catch below, where it's\n // routed as a retryable network failure when useRetry is true.\n const controller = new AbortController();\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n Authorization: `Bearer ${apiKey}`,\n 'X-Client-Version': version,\n 'X-Client-Library': sessionReplayLibrary,\n 'X-Client-Url': url.substring(0, MAX_URL_LENGTH), // limit url length to 1000 characters to avoid ELB 400 error\n 'X-Client-Sample-Rate': `${sampleRate}`,\n 'X-Sampling-Hash-Alg': 'xxhash32',\n ...(gzipped ? { 'Content-Encoding': 'gzip' } : {}),\n };\n const body: string | Uint8Array = gzipped ?? payloadJson;\n // keepalive lets the request survive page navigation, preventing 499 (client-closed) errors.\n // Must stay under the browser's 64 KB keepalive budget; large payloads skip it.\n const keepalive = payloadSize <= MAX_KEEPALIVE_BYTES;\n const options: RequestInit = {\n headers,\n body,\n method: 'POST',\n keepalive,\n signal: controller.signal,\n };\n\n const serverUrl = `${getServerUrl(context.serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n // Final defensive guard: never POST a zero-event payload. Upper layers (events-manager\n // oversize filter, send()'s post-batcher check, store-layer filters) should already\n // have caught this — but SR-4284 fleet logs show ~416 empty-body 400s/24h slipping\n // through somehow, so a cheap belt-and-braces check immediately before fetch prevents\n // any future regression from re-introducing the same server rejection.\n if (payload.events.length === 0) {\n this.completeRequest({ context });\n return;\n }\n // sendTimeoutMs <= 0 disables the abort: the request can then hang indefinitely\n // (head-of-line blocking the serial flush). Explicit experiment opt-out only.\n const sendTimeout =\n this.sendTimeoutMs > 0\n ? setTimeout(() => {\n controller.abort();\n }, this.sendTimeoutMs)\n : undefined;\n let res: Response;\n try {\n // When a custom transport is configured, hand it the fully-formed request and let it own\n // the network call (e.g. to attach a JWT and route through a proxy). Otherwise use the\n // built-in fetch. Retry/response handling below is identical for both paths. The built-in\n // fetch cancels directly on controller.signal; the custom callback can't be cancelled, so\n // we race it against the abort — a hung/never-settling transport then rejects with an\n // AbortError (retryable, like the worker delegation path) instead of blocking the serial\n // flush loop forever. The callback's own promise keeps running; we just stop awaiting it.\n res = this.handleSendEvents\n ? await abortable(\n this.handleSendEvents({ url: serverUrl, method: 'POST', headers, body, keepalive }),\n controller.signal,\n )\n : await fetch(serverUrl, options);\n } finally {\n // Clear on success and on error alike so a settled request never leaves an armed\n // timer that would abort a later reused controller or fire a stray callback.\n if (sendTimeout) clearTimeout(sendTimeout);\n }\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE });\n return;\n }\n if (res.status >= 200 && res.status < 300) {\n const skipCode = res.headers?.get?.(EVENT_SKIPPED_HEADER) ?? null;\n this.applyServerDirective(context.sessionId, skipCode);\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n let responseBody = '';\n if (res.status === 413) {\n try {\n responseBody = await res.text();\n } catch {\n // best effort\n }\n }\n await this.handleReponse(res.status, context, responseBody);\n }\n } catch (e) {\n // A send timeout aborts the fetch, which rejects with an AbortError. Treat that as a\n // transient network failure and route it through the same retry budget/backoff as a\n // 5xx (so a single stalled request doesn't permanently drop the batch) when retries\n // are enabled. completeRequest fires onComplete exactly once via either branch\n // (handleOtherResponse only completes on retry exhaustion), so onComplete can't fire\n // twice. Non-abort errors keep the original complete-with-error behavior.\n // Browsers reject an aborted fetch with a DOMException named 'AbortError', which is NOT an\n // Error instance — an `instanceof Error` check would misroute every send-timeout abort to\n // the fatal completeRequest path, defeating the retry. Match on the name across any thrown\n // object (DOMException or Error) instead.\n const isAbort = !!e && typeof e === 'object' && (e as { name?: unknown }).name === 'AbortError';\n if (isAbort && useRetry) {\n await this.handleOtherResponse(context);\n } else {\n this.completeRequest({ context, err: e as string });\n }\n }\n }\n\n async handleReponse(status: number, context: SessionReplayDestinationContext, responseBody = '') {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n case Status.Failed:\n case Status.Timeout: // 408: server timed out waiting for request, data not received\n case Status.RateLimit: // 429: retry with existing backoff rather than silently dropping\n await this.handleOtherResponse(context);\n break;\n case Status.PayloadTooLarge:\n this.handlePayloadTooLargeResponse(context, WAF_PAYLOAD_TOO_LARGE_PATTERN.test(responseBody));\n break;\n default:\n // 499 (client closed connection / upstream dropped) is also retryable\n if (status === 499) {\n await this.handleOtherResponse(context);\n break;\n }\n this.completeRequest({ context, err: UNEXPECTED_NETWORK_ERROR_MESSAGE });\n }\n }\n\n handlePayloadTooLargeResponse(context: SessionReplayDestinationContext, isWaf: boolean): void {\n const source = isWaf ? 'WAF (compressed payload too large)' : 'server (event too large)';\n const totalSizeKB = Math.round(context.events.reduce((sum, e) => sum + e.length, 0) / KB_SIZE);\n\n if (!isWaf) {\n this.completeRequest({\n context,\n err: `Session replay event batch dropped: ${source} rejected payload (${context.events.length} events, ${totalSizeKB} KB) — not retrying non-WAF 413`,\n });\n return;\n }\n\n if (context.events.length === 1) {\n this.completeRequest({\n context,\n err: `Session replay event dropped: single event (${totalSizeKB} KB, 1 event) rejected by ${source} — cannot split further`,\n });\n return;\n }\n\n this.loggerProvider.warn(\n `Session replay event batch rejected by ${source} (${context.events.length} events, ${totalSizeKB} KB total) — splitting and retrying`,\n );\n\n // Clean up the original IDB record, then re-enqueue both halves as new in-memory batches.\n // For a merged-on-throttle context (mergeQueueAfterThrottle), this onComplete is the\n // fanned-out callback covering N source IDB records — they'll all be cleaned up here.\n // Halves get noop onCompletes, so a page-close between this cleanup and a half delivery\n // means up to N source sequences are lost. The merge soft cap (1.4MB chars) is well under\n // the 10MB compressed 413 ceiling, so a 413 on a merged context is exceedingly rare in\n // practice; the alternative — deferring source cleanup until both halves complete — would\n // significantly complicate the retry path for marginal benefit.\n void context.onComplete();\n const noop = (): Promise<void> => Promise.resolve();\n const mid = Math.floor(context.events.length / 2);\n this.sendEventsList({ ...context, events: context.events.slice(0, mid), onComplete: noop });\n this.sendEventsList({ ...context, events: context.events.slice(mid), onComplete: noop });\n }\n\n handleSuccessResponse(context: SessionReplayDestinationContext) {\n const sizeOfEventsList = Math.round(new Blob(context.events).size / KB_SIZE);\n this.completeRequest({\n context,\n success: `Session replay event batch tracked successfully for session id ${context.sessionId}, size of events: ${sizeOfEventsList} KB`,\n });\n }\n\n async handleOtherResponse(context: SessionReplayDestinationContext) {\n const delay = Math.random() * context.attempts * this.retryTimeout;\n context.attempts++;\n if (context.attempts > (context.flushMaxRetries || 0)) {\n this.completeRequest({ context, err: MAX_RETRIES_EXCEEDED_MESSAGE });\n return;\n }\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n await this.send(context, true);\n }\n\n completeRequest({\n context,\n err,\n success,\n }: {\n context: SessionReplayDestinationContext;\n err?: string;\n success?: string;\n }) {\n void context.onComplete();\n if (err) {\n this.loggerProvider.warn(err);\n } else if (success) {\n this.loggerProvider.log(success);\n }\n }\n\n /**\n * Applies the server's back-pressure signal carried on a 200 response.\n *\n * - `EVENT_SKIP_CODE_THROTTLED` (server-side rate limit): pause the flush schedule\n * for `THROTTLED_FLUSH_PAUSE_MS` so we keep batching events instead of retry-storming.\n * - `EVENT_SKIP_CODE_CAPTURE_DISABLED` / `EVENT_SKIP_CODE_INVALID_RANGE`: hard kill\n * switch for this session — drop the queued contexts and stop accepting new ones.\n * New sessions are unaffected.\n * - `null` (clean 200, no header): clear any throttle pause; subsequent flushes resume\n * on the normal cadence.\n */\n private applyServerDirective(sessionId: string | number, skipCode: string | null) {\n if (skipCode === null) {\n this.flushPauseUntilMs = 0;\n this.mergeLogFiredThisPause = false;\n return;\n }\n if (skipCode === EVENT_SKIP_CODE_THROTTLED) {\n const wasInPause = this.flushPauseUntilMs > Date.now();\n this.flushPauseUntilMs = Date.now() + THROTTLED_FLUSH_PAUSE_MS;\n // Log only on pause-state transitions — a throttled server may reply to many\n // batches per minute, and one log per batch would flood the console.\n if (!wasInPause) {\n this.loggerProvider.log(\n `Session replay throttled by server; pausing flush schedule for ${THROTTLED_FLUSH_PAUSE_MS / 1000}s`,\n );\n }\n return;\n }\n if (skipCode === EVENT_SKIP_CODE_CAPTURE_DISABLED || skipCode === EVENT_SKIP_CODE_INVALID_RANGE) {\n this.killSession(sessionId, skipCode);\n }\n // Unknown skip codes are ignored — the server may add new ones, and our default\n // behavior (treat as a normal 200) preserves throughput rather than penalizing the\n // session for a code we don't recognize.\n }\n\n private killSession(sessionId: string | number, skipCode: string) {\n if (this.killedSessions.has(sessionId)) return;\n this.killedSessions.add(sessionId);\n // Set preserves insertion order, so deleting the first key evicts the oldest entry.\n if (this.killedSessions.size > MAX_KILLED_SESSIONS) {\n for (const oldest of this.killedSessions) {\n this.killedSessions.delete(oldest);\n break;\n }\n }\n this.loggerProvider.log(\n `Session replay capture stopped for session ${sessionId} by server directive ${skipCode}; remaining events will be dropped`,\n );\n // Drain any queued contexts for this session so their IDB records get cleaned up\n // via onComplete, instead of sitting in the queue waiting for a flush we'll never make.\n const remaining: SessionReplayDestinationContext[] = [];\n for (const queued of this.queue) {\n if (queued.sessionId === sessionId) {\n this.completeRequest({ context: queued, err: SESSION_KILLED_MESSAGE });\n } else {\n remaining.push(queued);\n }\n }\n this.queue = remaining;\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.47.0-sr-trc-debug-log.4";
1
+ export declare const VERSION = "1.47.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,8BAA8B,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,WAAW,CAAC"}
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Autogenerated by `pnpm version-file`. DO NOT EDIT
5
- exports.VERSION = '1.47.0-sr-trc-debug-log.4';
5
+ exports.VERSION = '1.47.0';
6
6
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAA,oDAAoD;AACvC,QAAA,OAAO,GAAG,2BAA2B,CAAC","sourcesContent":["// Autogenerated by `pnpm version-file`. DO NOT EDIT\nexport const VERSION = '1.47.0-sr-trc-debug-log.4';\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAA,oDAAoD;AACvC,QAAA,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["// Autogenerated by `pnpm version-file`. DO NOT EDIT\nexport const VERSION = '1.47.0';\n"]}
@@ -3,4 +3,4 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.trackDestinationScript = exports.compressionScript = void 0;
5
5
  exports.compressionScript = "var WebWorker=function(e){\"use strict\";onmessage=function(e){var s=\"string\"==typeof e.data?JSON.parse(e.data):e.data,t=s.event,a=s.sessionId,n=t.type,r=t.timestamp,i=t.delay,o=t.data,d=null!=i?JSON.stringify({type:n,timestamp:r,delay:i,data:o}):JSON.stringify({type:n,timestamp:r,data:o});postMessage({compressedEvent:d,sessionId:a})};var s=onmessage;return e.compressionOnMessage=s,Object.defineProperty(e,\"__esModule\",{value:!0}),e}({});\n";
6
- exports.trackDestinationScript = "var WebWorker=function(e){\"use strict\";var t,r=function(){return r=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var s in t=arguments[r])Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);return e},r.apply(this,arguments)};function n(e,t,r,n){return new(r||(r=Promise))(function(s,o){function a(e){try{c(n.next(e))}catch(e){o(e)}}function i(e){try{c(n.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?s(e.value):(t=e.value,t instanceof r?t:new r(function(e){e(t)})).then(a,i)}c((n=n.apply(e,t||[])).next())})}function s(e,t){var r,n,s,o={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]},a=Object.create((\"function\"==typeof Iterator?Iterator:Object).prototype);return a.next=i(0),a.throw=i(1),a.return=i(2),\"function\"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function i(i){return function(c){return function(i){if(r)throw new TypeError(\"Generator is already executing.\");for(;a&&(a=0,i[0]&&(o=0)),o;)try{if(r=1,n&&(s=2&i[0]?n.return:i[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,i[1])).done)return s;switch(n=0,s&&(i=[2&i[0],s.value]),i[0]){case 0:case 1:s=i;break;case 4:return o.label++,{value:i[1],done:!1};case 5:o.label++,n=i[1],i=[0];continue;case 7:i=o.ops.pop(),o.trys.pop();continue;default:if(!(s=o.trys,(s=s.length>0&&s[s.length-1])||6!==i[0]&&2!==i[0])){o=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){o.label=i[1];break}if(6===i[0]&&o.label<s[1]){o.label=s[1],s=i;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(i);break}s[2]&&o.ops.pop(),o.trys.pop();continue}i=t.call(e,o)}catch(e){i=[6,e],n=0}finally{r=s=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}\"function\"==typeof SuppressedError&&SuppressedError,function(e){e.US=\"US\",e.EU=\"EU\",e.STAGING=\"STAGING\"}(t||(t={})),t.US;var o,a=/payload.*exceed/i;!function(e){e.GET_SR_PROPS=\"get-sr-props\",e.DEBUG_INFO=\"debug-info\",e.FETCH_REQUEST=\"fetch-request\",e.METADATA=\"metadata\",e.TARGETING_DECISION=\"targeting-decision\",e.REPLAY_GATE_DECISION=\"replay-gate-decision\"}(o||(o={}));var i=\"Network error occurred, event batch rejected\";function c(e,t){return n(this,void 0,void 0,function(){var r,o,a,i,c,u,l,d,p,f,h,v,y,b,g=this;return s(this,function(m){switch(m.label){case 0:return m.trys.push([0,4,,5]),r=t.CompressionStream,o=new r(\"gzip\"),a=o.writable.getWriter(),i=o.readable.getReader(),c=[],u=n(g,void 0,void 0,function(){var e,t,r;return s(this,function(n){switch(n.label){case 0:return[4,i.read()];case 1:if(e=n.sent(),t=e.done,r=e.value,t)return[3,3];c.push(r),n.label=2;case 2:return[3,0];case 3:return[2]}})}),[4,a.write((new TextEncoder).encode(e))];case 1:return m.sent(),[4,a.close()];case 2:return m.sent(),[4,u];case 3:m.sent(),l=c.reduce(function(e,t){return e+t.length},0),d=new Uint8Array(l),p=0;try{for(f=function(e){var t=\"function\"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&\"number\"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")}(c),h=f.next();!h.done;h=f.next())v=h.value,d.set(v,p),p+=v.length}catch(e){y={error:e}}finally{try{h&&!h.done&&(b=f.return)&&b.call(f)}finally{if(y)throw y.error}}return[2,d];case 4:return m.sent(),[2,null];case 5:return[2]}})})}function u(e,t){var o,u,l,d,p,f,h,v;return n(this,void 0,void 0,function(){var n,y,b,g,m,S,w,T,E,R,k,x,C,A,I;return s(this,function(s){switch(s.label){case 0:n=null!==(o=t.sendTimeoutMs)&&void 0!==o?o:1e4,s.label=1;case 1:return s.trys.push([1,14,,15]),!1!==t.enableTransportCompression&&\"CompressionStream\"in self?[4,c(e,self)]:[3,3];case 2:return b=s.sent(),[3,4];case 3:b=null,s.label=4;case 4:y=b,g=\"\".concat(null!==(l=null===(u=t.version)||void 0===u?void 0:u.type)&&void 0!==l?l:\"standalone\",\"/\").concat(null!==(p=null===(d=t.version)||void 0===d?void 0:d.version)&&void 0!==p?p:t.sdkVersion),m=new URLSearchParams({device_id:t.deviceId,session_id:\"\".concat(t.sessionId),type:t.eventType}),S=\"\".concat((O=t.serverZone,U=t.trackServerUrl,U||(\"STAGING\"===O?\"https://api-sr.stag2.amplitude.com/sessions/v2/track\":\"EU\"===O?\"https://api-sr.eu.amplitude.com/sessions/v2/track\":\"https://api-sr.amplitude.com/sessions/v2/track\")),\"?\").concat(m.toString()),w=r({\"Content-Type\":\"application/json\",Accept:\"*/*\",Authorization:\"Bearer \".concat(t.apiKey),\"X-Client-Version\":t.sdkVersion,\"X-Client-Library\":g,\"X-Client-Url\":t.currentUrl.substring(0,1e3),\"X-Client-Sample-Rate\":\"\".concat(t.sampleRate),\"X-Sampling-Hash-Alg\":\"xxhash32\"},y?{\"Content-Encoding\":\"gzip\"}:{}),T=y?y.byteLength:new Blob([e]).size,E=new AbortController,R=n>0?setTimeout(function(){E.abort()},n):void 0,k=void 0,s.label=5;case 5:return s.trys.push([5,,7,8]),[4,fetch(S,{method:\"POST\",headers:w,body:null!=y?y:e,keepalive:T<=65536,signal:E.signal})];case 6:return k=s.sent(),[3,8];case 7:return R&&clearTimeout(R),[7];case 8:if(null===k)return[2,{shouldRetry:!1,success:!1,message:\"Unexpected error occurred\"}];if(k.status>=200&&k.status<300)return x=Math.round(new Blob(t.events).size/1024),C=null!==(v=null===(h=null===(f=k.headers)||void 0===f?void 0:f.get)||void 0===h?void 0:h.call(f,\"X-Session-Replay-Event-Skipped\"))&&void 0!==v?v:null,[2,{shouldRetry:!1,success:!0,message:\"Session replay event batch tracked successfully for session id \".concat(t.sessionId,\", size of events: \").concat(x,\" KB\"),skipCode:C}];if(413!==k.status)return[3,13];A=\"\",s.label=9;case 9:return s.trys.push([9,11,,12]),[4,k.text()];case 10:return A=s.sent(),[3,12];case 11:return s.sent(),[3,12];case 12:return[2,{shouldRetry:!1,success:!1,message:i,payloadTooLarge:!0,isWaf:a.test(A)}];case 13:return k.status>=500||408===k.status||429===k.status||499===k.status?[2,{shouldRetry:!0,success:!1,message:\"HTTP \".concat(k.status)}]:[2,{shouldRetry:!1,success:!1,message:i}];case 14:return(I=s.sent())&&\"object\"==typeof I&&\"AbortError\"===I.name?[2,{shouldRetry:!0,success:!1,message:\"Session replay worker request timed out after \".concat(n,\"ms\")}]:[2,{shouldRetry:!1,success:!1,message:String(I)}];case 15:return[2]}var O,U})})}function l(e,t,r,o){var a;return n(this,void 0,void 0,function(){var n,i,c;return s(this,function(s){switch(s.label){case 0:n=1,s.label=1;case 1:return[4,u(t,r)];case 2:return(i=s.sent()).success?(postMessage({type:\"log\",id:e,message:i.message}),postMessage({type:\"complete\",id:e,skipCode:null!==(a=i.skipCode)&&void 0!==a?a:null}),[2]):i.payloadTooLarge&&o?(postMessage({type:\"payload_too_large\",id:e,isWaf:!0===i.isWaf}),[2]):o&&i.shouldRetry&&n<r.flushMaxRetries?[4,new Promise(function(e){return setTimeout(e,Math.random()*n*1e3)})]:[3,4];case 3:return s.sent(),n++,[3,5];case 4:return c=n>=r.flushMaxRetries?\"Session replay event batch rejected due to exceeded retry count\":i.message,postMessage({type:\"warn\",id:e,message:c}),postMessage({type:\"complete\",id:e}),[2];case 5:return[3,1];case 6:return[2]}})})}onmessage=function(e){return n(void 0,void 0,void 0,function(){var t,r,n,o,a,i,c;return s(this,function(s){switch(s.label){case 0:return t=e.data,r=t.type,n=t.id,o=t.payload,a=t.context,i=t.useRetry,\"send\"!==r?[3,2]:(c=JSON.stringify(o),[4,l(n,c,a,i)]);case 1:s.sent(),s.label=2;case 2:return[2]}})})};var d=onmessage;return e.trackDestinationOnMessage=d,Object.defineProperty(e,\"__esModule\",{value:!0}),e}({});\n";
6
+ exports.trackDestinationScript = "var WebWorker=function(e){\"use strict\";var t,r=function(){return r=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var s in t=arguments[r])Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);return e},r.apply(this,arguments)};function n(e,t,r,n){return new(r||(r=Promise))(function(s,o){function a(e){try{u(n.next(e))}catch(e){o(e)}}function i(e){try{u(n.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?s(e.value):(t=e.value,t instanceof r?t:new r(function(e){e(t)})).then(a,i)}u((n=n.apply(e,t||[])).next())})}function s(e,t){var r,n,s,o={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]},a=Object.create((\"function\"==typeof Iterator?Iterator:Object).prototype);return a.next=i(0),a.throw=i(1),a.return=i(2),\"function\"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function i(i){return function(u){return function(i){if(r)throw new TypeError(\"Generator is already executing.\");for(;a&&(a=0,i[0]&&(o=0)),o;)try{if(r=1,n&&(s=2&i[0]?n.return:i[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,i[1])).done)return s;switch(n=0,s&&(i=[2&i[0],s.value]),i[0]){case 0:case 1:s=i;break;case 4:return o.label++,{value:i[1],done:!1};case 5:o.label++,n=i[1],i=[0];continue;case 7:i=o.ops.pop(),o.trys.pop();continue;default:if(!(s=o.trys,(s=s.length>0&&s[s.length-1])||6!==i[0]&&2!==i[0])){o=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){o.label=i[1];break}if(6===i[0]&&o.label<s[1]){o.label=s[1],s=i;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(i);break}s[2]&&o.ops.pop(),o.trys.pop();continue}i=t.call(e,o)}catch(e){i=[6,e],n=0}finally{r=s=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,u])}}}\"function\"==typeof SuppressedError&&SuppressedError,function(e){e.US=\"US\",e.EU=\"EU\",e.STAGING=\"STAGING\"}(t||(t={})),t.US;var o,a=/payload.*exceed/i,i=\"X-Session-Replay-Event-Skipped\";!function(e){e.GET_SR_PROPS=\"get-sr-props\",e.DEBUG_INFO=\"debug-info\",e.FETCH_REQUEST=\"fetch-request\",e.METADATA=\"metadata\",e.TARGETING_DECISION=\"targeting-decision\",e.REPLAY_GATE_DECISION=\"replay-gate-decision\"}(o||(o={}));var u=\"Network error occurred, event batch rejected\";function c(e,t){return n(this,void 0,void 0,function(){var r,o,a,i,u,c,l,d,p,f,v,y,h,b,g=this;return s(this,function(m){switch(m.label){case 0:return m.trys.push([0,4,,5]),r=t.CompressionStream,o=new r(\"gzip\"),a=o.writable.getWriter(),i=o.readable.getReader(),u=[],c=n(g,void 0,void 0,function(){var e,t,r;return s(this,function(n){switch(n.label){case 0:return[4,i.read()];case 1:if(e=n.sent(),t=e.done,r=e.value,t)return[3,3];u.push(r),n.label=2;case 2:return[3,0];case 3:return[2]}})}),[4,a.write((new TextEncoder).encode(e))];case 1:return m.sent(),[4,a.close()];case 2:return m.sent(),[4,c];case 3:m.sent(),l=u.reduce(function(e,t){return e+t.length},0),d=new Uint8Array(l),p=0;try{for(f=function(e){var t=\"function\"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&\"number\"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")}(u),v=f.next();!v.done;v=f.next())y=v.value,d.set(y,p),p+=y.length}catch(e){h={error:e}}finally{try{v&&!v.done&&(b=f.return)&&b.call(f)}finally{if(h)throw h.error}}return[2,d];case 4:return m.sent(),[2,null];case 5:return[2]}})})}var l=0,d=new Map,p=function(e,t){return fetch(e,t)},f=function(e,t){var r=\"\".concat(++l);return new Promise(function(n,s){var o=t.signal,a=function(){d.delete(r);var e=new Error(\"Delegated session replay fetch aborted by send timeout\");e.name=\"AbortError\",s(e)};o.addEventListener(\"abort\",a,{once:!0}),d.set(r,function(e){o.removeEventListener(\"abort\",a),e.error?s(new Error(e.body)):n({status:e.status,headers:{get:function(t){return t===i?e.skipHeader:null}},text:function(){return Promise.resolve(e.body)}})}),postMessage({type:\"fetch-request\",requestId:r,url:e,method:\"POST\",headers:t.headers,body:t.body,keepalive:t.keepalive})})};function v(e,t,o){var l,d,p,f,v,y,h,b;return n(this,void 0,void 0,function(){var n,g,m,w,S,T,E,k,R,x,C,I,A,M,O;return s(this,function(s){switch(s.label){case 0:n=null!==(l=t.sendTimeoutMs)&&void 0!==l?l:1e4,s.label=1;case 1:return s.trys.push([1,14,,15]),!1!==t.enableTransportCompression&&\"CompressionStream\"in self?[4,c(e,self)]:[3,3];case 2:return m=s.sent(),[3,4];case 3:m=null,s.label=4;case 4:g=m,w=\"\".concat(null!==(p=null===(d=t.version)||void 0===d?void 0:d.type)&&void 0!==p?p:\"standalone\",\"/\").concat(null!==(v=null===(f=t.version)||void 0===f?void 0:f.version)&&void 0!==v?v:t.sdkVersion),S=new URLSearchParams({device_id:t.deviceId,session_id:\"\".concat(t.sessionId),type:t.eventType}),T=\"\".concat((U=t.serverZone,P=t.trackServerUrl,P||(\"STAGING\"===U?\"https://api-sr.stag2.amplitude.com/sessions/v2/track\":\"EU\"===U?\"https://api-sr.eu.amplitude.com/sessions/v2/track\":\"https://api-sr.amplitude.com/sessions/v2/track\")),\"?\").concat(S.toString()),E=r({\"Content-Type\":\"application/json\",Accept:\"*/*\",Authorization:\"Bearer \".concat(t.apiKey),\"X-Client-Version\":t.sdkVersion,\"X-Client-Library\":w,\"X-Client-Url\":t.currentUrl.substring(0,1e3),\"X-Client-Sample-Rate\":\"\".concat(t.sampleRate),\"X-Sampling-Hash-Alg\":\"xxhash32\"},g?{\"Content-Encoding\":\"gzip\"}:{}),k=g?g.byteLength:new Blob([e]).size,R=new AbortController,x=n>0?setTimeout(function(){R.abort()},n):void 0,C=void 0,s.label=5;case 5:return s.trys.push([5,,7,8]),[4,o(T,{method:\"POST\",headers:E,body:null!=g?g:e,keepalive:k<=65536,signal:R.signal})];case 6:return C=s.sent(),[3,8];case 7:return x&&clearTimeout(x),[7];case 8:if(null===C)return[2,{shouldRetry:!1,success:!1,message:\"Unexpected error occurred\"}];if(C.status>=200&&C.status<300)return I=Math.round(new Blob(t.events).size/1024),A=null!==(b=null===(h=null===(y=C.headers)||void 0===y?void 0:y.get)||void 0===h?void 0:h.call(y,i))&&void 0!==b?b:null,[2,{shouldRetry:!1,success:!0,message:\"Session replay event batch tracked successfully for session id \".concat(t.sessionId,\", size of events: \").concat(I,\" KB\"),skipCode:A}];if(413!==C.status)return[3,13];M=\"\",s.label=9;case 9:return s.trys.push([9,11,,12]),[4,C.text()];case 10:return M=s.sent(),[3,12];case 11:return s.sent(),[3,12];case 12:return[2,{shouldRetry:!1,success:!1,message:u,payloadTooLarge:!0,isWaf:a.test(M)}];case 13:return C.status>=500||408===C.status||429===C.status||499===C.status?[2,{shouldRetry:!0,success:!1,message:\"HTTP \".concat(C.status)}]:[2,{shouldRetry:!1,success:!1,message:u}];case 14:return(O=s.sent())&&\"object\"==typeof O&&\"AbortError\"===O.name?[2,{shouldRetry:!0,success:!1,message:\"Session replay worker request timed out after \".concat(n,\"ms\")}]:[2,{shouldRetry:!1,success:!1,message:String(O)}];case 15:return[2]}var U,P})})}function y(e,t,r,o,a){var i;return n(this,void 0,void 0,function(){var n,u,c;return s(this,function(s){switch(s.label){case 0:n=1,s.label=1;case 1:return[4,v(t,r,a)];case 2:return(u=s.sent()).success?(postMessage({type:\"log\",id:e,message:u.message}),postMessage({type:\"complete\",id:e,skipCode:null!==(i=u.skipCode)&&void 0!==i?i:null}),[2]):u.payloadTooLarge&&o?(postMessage({type:\"payload_too_large\",id:e,isWaf:!0===u.isWaf}),[2]):o&&u.shouldRetry&&n<r.flushMaxRetries?[4,new Promise(function(e){return setTimeout(e,Math.random()*n*1e3)})]:[3,4];case 3:return s.sent(),n++,[3,5];case 4:return c=n>=r.flushMaxRetries?\"Session replay event batch rejected due to exceeded retry count\":u.message,postMessage({type:\"warn\",id:e,message:c}),postMessage({type:\"complete\",id:e}),[2];case 5:return[3,1];case 6:return[2]}})})}onmessage=function(e){return n(void 0,void 0,void 0,function(){var t,r,n,o,a,i,u,c;return s(this,function(s){switch(s.label){case 0:return\"fetch-response\"===(t=e.data).type?((r=d.get(t.requestId))&&(d.delete(t.requestId),r(t)),[2]):\"send\"!==t.type?[3,2]:(n=t.id,o=t.payload,a=t.context,i=t.useRetry,u=t.useCustomTransport,c=JSON.stringify(o),[4,y(n,c,a,i,u?f:p)]);case 1:s.sent(),s.label=2;case 2:return[2]}})})};var h=onmessage;return e.trackDestinationOnMessage=h,Object.defineProperty(e,\"__esModule\",{value:!0}),e}({});\n";
@@ -22,6 +22,8 @@ export declare class BeaconTransport<T> {
22
22
  private readonly basePageUrl;
23
23
  private readonly context;
24
24
  private readonly apiKey;
25
+ private readonly handleSendEvents?;
26
+ private readonly loggerProvider?;
25
27
  constructor(context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>, config: SessionReplayJoinedConfig);
26
28
  send(deviceId: string, payload: T): void;
27
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"beacon-transport.d.ts","sourceRoot":"","sources":["../../src/beacon-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,uCAAuC,EAAE,MAAM,0BAA0B,CAAC;AAKnF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,eAAe,CAAC,CAAC;IAC5B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4D;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,OAAO,EAAE,IAAI,CAAC,uCAAuC,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,yBAAyB;IA8BjH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;CAelC"}
1
+ {"version":3,"file":"beacon-transport.d.ts","sourceRoot":"","sources":["../../src/beacon-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAkC,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,uCAAuC,EAAE,MAAM,0BAA0B,CAAC;AAKnF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,eAAe,CAAC,CAAC;IAC5B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4D;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAGhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAiC;IACnE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAU;gBAE9B,OAAO,EAAE,IAAI,CAAC,uCAAuC,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,yBAAyB;IAgCjH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;CAiDlC"}
@@ -45,9 +45,47 @@ var BeaconTransport = /** @class */ (function () {
45
45
  this.basePageUrl = getServerUrl(config.serverZone, config.trackServerUrl);
46
46
  this.apiKey = config.apiKey;
47
47
  this.context = context;
48
+ this.handleSendEvents = config.handleSendEvents;
49
+ this.loggerProvider = config.loggerProvider;
48
50
  }
49
51
  BeaconTransport.prototype.send = function (deviceId, payload) {
50
- var _a = this.context, sessionId = _a.sessionId, type = _a.type;
52
+ var _this = this;
53
+ var _a;
54
+ var _b = this.context, sessionId = _b.sessionId, type = _b.type;
55
+ // Custom-transport path: navigator.sendBeacon/XHR cannot attach custom headers, so an
56
+ // interaction beacon would otherwise leave unauthenticated and be rejected by an
57
+ // authenticating proxy. When handleSendEvents is set, route the beacon through it instead —
58
+ // a keepalive fetch (survives page unload) that carries the customer's auth. Mirrors the
59
+ // replay page-exit path: api_key goes in the Authorization header, not the URL.
60
+ if (this.handleSendEvents) {
61
+ var params = new URLSearchParams({
62
+ device_id: deviceId,
63
+ session_id: String(sessionId),
64
+ type: String(type),
65
+ });
66
+ var url = "".concat(this.basePageUrl, "?").concat(params.toString());
67
+ var headers = {
68
+ 'Content-Type': 'application/json',
69
+ Accept: '*/*',
70
+ Authorization: "Bearer ".concat(this.apiKey),
71
+ };
72
+ try {
73
+ void this.handleSendEvents({
74
+ url: url,
75
+ method: 'POST',
76
+ headers: headers,
77
+ body: JSON.stringify(payload),
78
+ keepalive: true,
79
+ }).catch(function (e) {
80
+ var _a;
81
+ (_a = _this.loggerProvider) === null || _a === void 0 ? void 0 : _a.warn('Custom transport failed to send session replay interaction beacon:', e);
82
+ });
83
+ }
84
+ catch (e) {
85
+ (_a = this.loggerProvider) === null || _a === void 0 ? void 0 : _a.warn('Custom transport threw while sending session replay interaction beacon:', e);
86
+ }
87
+ return;
88
+ }
51
89
  var urlParams = new URLSearchParams({
52
90
  device_id: deviceId,
53
91
  session_id: String(sessionId),
@@ -1 +1 @@
1
- {"version":3,"file":"beacon-transport.js","sourceRoot":"","sources":["../../src/beacon-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAIzC;;;;;;;;;;;;;;;GAeG;AACH;IAOE,yBAAY,OAAkE,EAAE,MAAiC;QAC/G,IAAM,WAAW,GAAG,cAAc,EAAE,CAAC;QACrC,IAAI,WAAW,IAAI,WAAW,CAAC,SAAS,IAAI,OAAO,WAAW,CAAC,SAAS,CAAC,UAAU,KAAK,UAAU,EAAE;YAClG,IAAI,CAAC,UAAU,GAAG,UAAC,OAAO,EAAE,OAAO;gBACjC,IAAI;oBACF,IAAI,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE;wBACtE,OAAO,IAAI,CAAC;qBACb;iBACF;gBAAC,OAAO,CAAC,EAAE;oBACV,4EAA4E;iBAC7E;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC;SACH;aAAM;YACL,IAAI,CAAC,UAAU,GAAG,cAAM,OAAA,KAAK,EAAL,CAAK,CAAC;SAC/B;QAED,IAAI,CAAC,OAAO,GAAG,UAAC,OAAO,EAAE,OAAO;YAC9B,IAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAChC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QAEF,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,8BAAI,GAAJ,UAAK,QAAgB,EAAE,OAAU;QACzB,IAAA,KAAsB,IAAI,CAAC,OAAO,EAAhC,SAAS,eAAA,EAAE,IAAI,UAAiB,CAAC;QACzC,IAAM,SAAS,GAAG,IAAI,eAAe,CAAC;YACpC,SAAS,EAAE,QAAQ;YACnB,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,OAAO,EAAE,IAAI,CAAC,MAAM;SACrB,CAAC,CAAC;QAEH,IAAM,OAAO,GAAG,UAAG,IAAI,CAAC,WAAW,cAAI,SAAS,CAAC,QAAQ,EAAE,CAAE,CAAC;QAE9D,kGAAkG;QAClG,+DAA+D;QAC/D,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IACH,sBAAC;AAAD,CAAC,AApDD,IAoDC","sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-core';\nimport { SessionReplayJoinedConfig } from './config/types';\nimport { SessionReplayDestinationSessionMetadata } from './typings/session-replay';\nimport { getServerUrl } from './helpers';\n\ntype BeaconSendFn<T> = (pageUrl: string, payload: T) => boolean;\n\n/**\n * For very small payloads it's preferable to use the [Beacon API](https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API).\n * While it doesn't provide 100% guarantees on sends, it greatly helps with overall reliability and page load performance. As\n * the Beacon API has a potential to fail due to size constraints we want to fall back to XHR if need be. This is mostly to\n * be used with 'pagehide' or 'beforeunload' events.\n *\n * Note there are only 3 CORS safelisted Content-Types you can send:\n *\n * - application/x-www-form-urlencoded\n * - multipart/form-data\n * - text/plain\n *\n * If we do not send one of these, some browsers like Chrome may not send this at all. Also we incur the overhead of a preflight\n * request. In our case we will add no additional content-type header. If you are trying to ping a server that requires this\n * header, you may want to use the regular fetch API or a different mechanism.\n */\nexport class BeaconTransport<T> {\n private sendBeacon: BeaconSendFn<T>;\n private sendXhr: BeaconSendFn<T>;\n private readonly basePageUrl: string;\n private readonly context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>;\n private readonly apiKey: string;\n\n constructor(context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>, config: SessionReplayJoinedConfig) {\n const globalScope = getGlobalScope();\n if (globalScope && globalScope.navigator && typeof globalScope.navigator.sendBeacon === 'function') {\n this.sendBeacon = (pageUrl, payload) => {\n try {\n if (globalScope.navigator.sendBeacon(pageUrl, JSON.stringify(payload))) {\n return true;\n }\n } catch (e) {\n // not logging error, since it would be hard to view and just adds overhead.\n }\n return false;\n };\n } else {\n this.sendBeacon = () => false;\n }\n\n this.sendXhr = (pageUrl, payload) => {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', pageUrl, true);\n xhr.setRequestHeader('Accept', '*/*');\n xhr.send(JSON.stringify(payload));\n return true;\n };\n\n this.basePageUrl = getServerUrl(config.serverZone, config.trackServerUrl);\n this.apiKey = config.apiKey;\n this.context = context;\n }\n\n send(deviceId: string, payload: T) {\n const { sessionId, type } = this.context;\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: String(type),\n api_key: this.apiKey,\n });\n\n const pageUrl = `${this.basePageUrl}?${urlParams.toString()}`;\n\n // ideally send using the beacon API, but there is a chance it may fail, possibly due to a payload\n // size limit. in this case, try best effort to send using xhr.\n this.sendBeacon(pageUrl, payload) || this.sendXhr(pageUrl, payload);\n }\n}\n"]}
1
+ {"version":3,"file":"beacon-transport.js","sourceRoot":"","sources":["../../src/beacon-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { getGlobalScope, ILogger } from '@amplitude/analytics-core';\nimport { SessionReplayJoinedConfig, SessionReplaySendEventsHandler } from './config/types';\nimport { SessionReplayDestinationSessionMetadata } from './typings/session-replay';\nimport { getServerUrl } from './helpers';\n\ntype BeaconSendFn<T> = (pageUrl: string, payload: T) => boolean;\n\n/**\n * For very small payloads it's preferable to use the [Beacon API](https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API).\n * While it doesn't provide 100% guarantees on sends, it greatly helps with overall reliability and page load performance. As\n * the Beacon API has a potential to fail due to size constraints we want to fall back to XHR if need be. This is mostly to\n * be used with 'pagehide' or 'beforeunload' events.\n *\n * Note there are only 3 CORS safelisted Content-Types you can send:\n *\n * - application/x-www-form-urlencoded\n * - multipart/form-data\n * - text/plain\n *\n * If we do not send one of these, some browsers like Chrome may not send this at all. Also we incur the overhead of a preflight\n * request. In our case we will add no additional content-type header. If you are trying to ping a server that requires this\n * header, you may want to use the regular fetch API or a different mechanism.\n */\nexport class BeaconTransport<T> {\n private sendBeacon: BeaconSendFn<T>;\n private sendXhr: BeaconSendFn<T>;\n private readonly basePageUrl: string;\n private readonly context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>;\n private readonly apiKey: string;\n // Optional custom transport. When set, interaction beacons go through it (a keepalive fetch\n // that can carry custom auth) instead of navigator.sendBeacon/XHR, which cannot set headers.\n private readonly handleSendEvents?: SessionReplaySendEventsHandler;\n private readonly loggerProvider?: ILogger;\n\n constructor(context: Omit<SessionReplayDestinationSessionMetadata, 'deviceId'>, config: SessionReplayJoinedConfig) {\n const globalScope = getGlobalScope();\n if (globalScope && globalScope.navigator && typeof globalScope.navigator.sendBeacon === 'function') {\n this.sendBeacon = (pageUrl, payload) => {\n try {\n if (globalScope.navigator.sendBeacon(pageUrl, JSON.stringify(payload))) {\n return true;\n }\n } catch (e) {\n // not logging error, since it would be hard to view and just adds overhead.\n }\n return false;\n };\n } else {\n this.sendBeacon = () => false;\n }\n\n this.sendXhr = (pageUrl, payload) => {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', pageUrl, true);\n xhr.setRequestHeader('Accept', '*/*');\n xhr.send(JSON.stringify(payload));\n return true;\n };\n\n this.basePageUrl = getServerUrl(config.serverZone, config.trackServerUrl);\n this.apiKey = config.apiKey;\n this.context = context;\n this.handleSendEvents = config.handleSendEvents;\n this.loggerProvider = config.loggerProvider;\n }\n\n send(deviceId: string, payload: T) {\n const { sessionId, type } = this.context;\n\n // Custom-transport path: navigator.sendBeacon/XHR cannot attach custom headers, so an\n // interaction beacon would otherwise leave unauthenticated and be rejected by an\n // authenticating proxy. When handleSendEvents is set, route the beacon through it instead —\n // a keepalive fetch (survives page unload) that carries the customer's auth. Mirrors the\n // replay page-exit path: api_key goes in the Authorization header, not the URL.\n if (this.handleSendEvents) {\n const params = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: String(type),\n });\n const url = `${this.basePageUrl}?${params.toString()}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n Authorization: `Bearer ${this.apiKey}`,\n };\n try {\n void this.handleSendEvents({\n url,\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n keepalive: true,\n }).catch((e) => {\n this.loggerProvider?.warn('Custom transport failed to send session replay interaction beacon:', e);\n });\n } catch (e) {\n this.loggerProvider?.warn('Custom transport threw while sending session replay interaction beacon:', e);\n }\n return;\n }\n\n const urlParams = new URLSearchParams({\n device_id: deviceId,\n session_id: String(sessionId),\n type: String(type),\n api_key: this.apiKey,\n });\n\n const pageUrl = `${this.basePageUrl}?${urlParams.toString()}`;\n\n // ideally send using the beacon API, but there is a chance it may fail, possibly due to a payload\n // size limit. in this case, try best effort to send using xhr.\n this.sendBeacon(pageUrl, payload) || this.sendXhr(pageUrl, payload);\n }\n}\n"]}
@@ -5,12 +5,7 @@ export declare const removeInvalidSelectorsFromPrivacyConfig: (privacyConfig: Pr
5
5
  export declare class SessionReplayJoinedConfigGenerator {
6
6
  private readonly localConfig;
7
7
  private readonly remoteConfigClient;
8
- private readonly sessionId?;
9
- private readonly deviceId?;
10
- constructor(remoteConfigClient: IRemoteConfigClient, localConfig: ISessionReplayLocalConfig, identity?: {
11
- sessionId?: string | number;
12
- deviceId?: string;
13
- });
8
+ constructor(remoteConfigClient: IRemoteConfigClient, localConfig: ISessionReplayLocalConfig);
14
9
  generateJoinedConfig(): Promise<SessionReplayConfigs>;
15
10
  /**
16
11
  * Defensive bounds for the remote-supplied min_session_duration_ms. A misconfigured
@@ -1 +1 @@
1
- {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAA4C,MAAM,2BAA2B,CAAC;AAGnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,aAAa,EACb,oBAAoB,EAGrB,MAAM,SAAS,CAAC;AAajB,eAAO,MAAM,uCAAuC,kBAAmB,aAAa,kBAAkB,OAAO,kBA0B5G,CAAC;AACF,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;IAEzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;gBAGjC,kBAAkB,EAAE,mBAAmB,EACvC,WAAW,EAAE,yBAAyB,EACtC,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAQzD,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAwO3D;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;CAmBrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAc3G,CAAC"}
1
+ {"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAA4C,MAAM,2BAA2B,CAAC;AAEnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,aAAa,EACb,oBAAoB,EAGrB,MAAM,SAAS,CAAC;AAajB,eAAO,MAAM,uCAAuC,kBAAmB,aAAa,kBAAkB,OAAO,kBA0B5G,CAAC;AACF,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;gBAE7C,kBAAkB,EAAE,mBAAmB,EAAE,WAAW,EAAE,yBAAyB;IAKrF,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC;IA+L3D;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;CAmBrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAc3G,CAAC"}