@amplitude/session-replay-browser 1.42.1 → 1.42.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/cjs/config/joined-config.d.ts.map +1 -1
  2. package/lib/cjs/config/joined-config.js +19 -4
  3. package/lib/cjs/config/joined-config.js.map +1 -1
  4. package/lib/cjs/constants.d.ts +5 -0
  5. package/lib/cjs/constants.d.ts.map +1 -1
  6. package/lib/cjs/constants.js +10 -1
  7. package/lib/cjs/constants.js.map +1 -1
  8. package/lib/cjs/messages.d.ts +1 -0
  9. package/lib/cjs/messages.d.ts.map +1 -1
  10. package/lib/cjs/messages.js +2 -1
  11. package/lib/cjs/messages.js.map +1 -1
  12. package/lib/cjs/track-destination.d.ts +15 -0
  13. package/lib/cjs/track-destination.d.ts.map +1 -1
  14. package/lib/cjs/track-destination.js +133 -20
  15. package/lib/cjs/track-destination.js.map +1 -1
  16. package/lib/cjs/version.d.ts +1 -1
  17. package/lib/cjs/version.js +1 -1
  18. package/lib/cjs/version.js.map +1 -1
  19. package/lib/cjs/worker/index.js +1 -1
  20. package/lib/esm/config/joined-config.d.ts.map +1 -1
  21. package/lib/esm/config/joined-config.js +19 -4
  22. package/lib/esm/config/joined-config.js.map +1 -1
  23. package/lib/esm/constants.d.ts +5 -0
  24. package/lib/esm/constants.d.ts.map +1 -1
  25. package/lib/esm/constants.js +9 -0
  26. package/lib/esm/constants.js.map +1 -1
  27. package/lib/esm/messages.d.ts +1 -0
  28. package/lib/esm/messages.d.ts.map +1 -1
  29. package/lib/esm/messages.js +1 -0
  30. package/lib/esm/messages.js.map +1 -1
  31. package/lib/esm/track-destination.d.ts +15 -0
  32. package/lib/esm/track-destination.d.ts.map +1 -1
  33. package/lib/esm/track-destination.js +135 -22
  34. package/lib/esm/track-destination.js.map +1 -1
  35. package/lib/esm/version.d.ts +1 -1
  36. package/lib/esm/version.js +1 -1
  37. package/lib/esm/version.js.map +1 -1
  38. package/lib/esm/worker/index.js +1 -1
  39. package/lib/scripts/index-min.js +1 -1
  40. package/lib/scripts/index-min.js.gz +0 -0
  41. package/lib/scripts/index-min.js.map +1 -1
  42. package/lib/scripts/session-replay-browser-min.js +1 -1
  43. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  44. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  45. package/lib/scripts/worker-min.js +1 -1
  46. package/lib/scripts/worker-min.js.gz +0 -0
  47. package/package.json +1 -1
@@ -1,10 +1,13 @@
1
1
  import { __assign, __awaiter, __generator, __read, __values } from "tslib";
2
2
  import { BaseTransport, getGlobalScope, Status } from '@amplitude/analytics-core';
3
3
  import { getCurrentUrl, getServerUrl } from './helpers';
4
- import { MAX_RETRIES_EXCEEDED_MESSAGE, MISSING_API_KEY_MESSAGE, MISSING_DEVICE_ID_MESSAGE, UNEXPECTED_ERROR_MESSAGE, UNEXPECTED_NETWORK_ERROR_MESSAGE, } from './messages';
4
+ import { MAX_RETRIES_EXCEEDED_MESSAGE, MISSING_API_KEY_MESSAGE, MISSING_DEVICE_ID_MESSAGE, SESSION_KILLED_MESSAGE, UNEXPECTED_ERROR_MESSAGE, UNEXPECTED_NETWORK_ERROR_MESSAGE, } from './messages';
5
5
  import { VERSION } from './version';
6
- import { MAX_URL_LENGTH, KB_SIZE, MAX_KEEPALIVE_BYTES, WAF_PAYLOAD_TOO_LARGE_PATTERN } from './constants';
6
+ import { MAX_URL_LENGTH, KB_SIZE, MAX_KEEPALIVE_BYTES, WAF_PAYLOAD_TOO_LARGE_PATTERN, EVENT_SKIPPED_HEADER, EVENT_SKIP_CODE_THROTTLED, EVENT_SKIP_CODE_INVALID_RANGE, EVENT_SKIP_CODE_CAPTURE_DISABLED, THROTTLED_FLUSH_PAUSE_MS, } from './constants';
7
7
  import { gzipJson } from './utils/gzip';
8
+ // Bounded so a long-lived SDK instance can't accumulate kill records indefinitely;
9
+ // sessions are time-bounded in practice, this cap is just a defensive ceiling.
10
+ var MAX_KILLED_SESSIONS = 256;
8
11
  var SessionReplayTrackDestination = /** @class */ (function () {
9
12
  function SessionReplayTrackDestination(_a) {
10
13
  var trackServerUrl = _a.trackServerUrl, loggerProvider = _a.loggerProvider, payloadBatcher = _a.payloadBatcher, workerScript = _a.workerScript;
@@ -15,6 +18,11 @@ var SessionReplayTrackDestination = /** @class */ (function () {
15
18
  this.queue = [];
16
19
  this.sendIdCounter = 0;
17
20
  this.pendingWorkerRequests = new Map();
21
+ // Server back-pressure state, fed by the X-Session-Replay-Event-Skipped header on 200s.
22
+ // The server uses this header (instead of 4xx) to signal a deliberate no-retry drop so SDKs
23
+ // don't retry-storm. We honor it here by slowing or stopping our flush schedule.
24
+ this.flushPauseUntilMs = 0;
25
+ this.killedSessions = new Set();
18
26
  this.loggerProvider = loggerProvider;
19
27
  this.payloadBatcher = payloadBatcher ? payloadBatcher : function (payload) { return payload; };
20
28
  this.trackServerUrl = trackServerUrl;
@@ -67,6 +75,9 @@ var SessionReplayTrackDestination = /** @class */ (function () {
67
75
  else if (msg.type === 'complete') {
68
76
  var pending_3 = _this.pendingWorkerRequests.get(msg.id);
69
77
  if (pending_3) {
78
+ if (msg.skipCode !== undefined) {
79
+ _this.applyServerDirective(pending_3.context.sessionId, msg.skipCode);
80
+ }
70
81
  _this.completeRequest({ context: pending_3.context });
71
82
  pending_3.resolve();
72
83
  _this.pendingWorkerRequests.delete(msg.id);
@@ -146,6 +157,15 @@ var SessionReplayTrackDestination = /** @class */ (function () {
146
157
  list[_i] = arguments[_i];
147
158
  }
148
159
  var tryable = list.filter(function (context) {
160
+ if (_this.killedSessions.has(context.sessionId)) {
161
+ // Server has signaled capture_disabled or session_in_invalid_range for this session;
162
+ // drop the batch (and clean up its IDB record via onComplete) instead of POSTing.
163
+ _this.completeRequest({
164
+ context: context,
165
+ err: SESSION_KILLED_MESSAGE,
166
+ });
167
+ return false;
168
+ }
149
169
  if (context.attempts < (context.flushMaxRetries || 0)) {
150
170
  context.attempts += 1;
151
171
  return true;
@@ -165,13 +185,17 @@ var SessionReplayTrackDestination = /** @class */ (function () {
165
185
  var _this = this;
166
186
  if (this.scheduled)
167
187
  return;
188
+ // If the server signaled throttling on a recent 200, defer the next flush until the
189
+ // pause window ends. This lets us keep batching events without retry-storming the server.
190
+ var pauseRemaining = this.flushPauseUntilMs - Date.now();
191
+ var effectiveTimeout = pauseRemaining > timeout ? pauseRemaining : timeout;
168
192
  this.scheduled = setTimeout(function () {
169
193
  void _this.flush(true).then(function () {
170
194
  if (_this.queue.length > 0) {
171
195
  _this.schedule(timeout);
172
196
  }
173
197
  });
174
- }, timeout);
198
+ }, effectiveTimeout);
175
199
  };
176
200
  SessionReplayTrackDestination.prototype.flush = function (useRetry) {
177
201
  if (useRetry === void 0) { useRetry = false; }
@@ -223,6 +247,12 @@ var SessionReplayTrackDestination = /** @class */ (function () {
223
247
  return __awaiter(this, void 0, void 0, function () {
224
248
  var apiKey, deviceId, payload, worker;
225
249
  return __generator(this, function (_a) {
250
+ // A kill directive can arrive between flush() snapshotting the queue and us reaching
251
+ // each context. Re-check before hitting the network so we don't waste POSTs on a
252
+ // session the server has already told us to stop sending for.
253
+ if (this.killedSessions.has(context.sessionId)) {
254
+ return [2 /*return*/, this.completeRequest({ context: context, err: SESSION_KILLED_MESSAGE })];
255
+ }
226
256
  apiKey = context.apiKey;
227
257
  if (!apiKey) {
228
258
  return [2 /*return*/, this.completeRequest({ context: context, err: MISSING_API_KEY_MESSAGE })];
@@ -281,11 +311,11 @@ var SessionReplayTrackDestination = /** @class */ (function () {
281
311
  });
282
312
  };
283
313
  SessionReplayTrackDestination.prototype.sendOnMainThread = function (apiKey, deviceId, context, payload, useRetry) {
284
- var _a, _b, _c, _d;
314
+ var _a, _b, _c, _d, _e, _f, _g;
285
315
  return __awaiter(this, void 0, void 0, function () {
286
- var url, version, sampleRate, urlParams, sessionReplayLibrary, payloadJson, globalScope, gzipped, _e, payloadSize, options, serverUrl, res, responseBody, responseBody, _f, e_3;
287
- return __generator(this, function (_g) {
288
- switch (_g.label) {
316
+ var url, version, sampleRate, urlParams, sessionReplayLibrary, payloadJson, globalScope, gzipped, _h, payloadSize, options, serverUrl, res, skipCode, responseBody, responseBody, _j, e_3;
317
+ return __generator(this, function (_k) {
318
+ switch (_k.label) {
289
319
  case 0:
290
320
  url = getCurrentUrl();
291
321
  version = VERSION;
@@ -296,21 +326,21 @@ var SessionReplayTrackDestination = /** @class */ (function () {
296
326
  type: "".concat(context.type),
297
327
  });
298
328
  sessionReplayLibrary = "".concat((_b = (_a = context.version) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'standalone', "/").concat((_d = (_c = context.version) === null || _c === void 0 ? void 0 : _c.version) !== null && _d !== void 0 ? _d : version);
299
- _g.label = 1;
329
+ _k.label = 1;
300
330
  case 1:
301
- _g.trys.push([1, 13, , 14]);
331
+ _k.trys.push([1, 13, , 14]);
302
332
  payloadJson = JSON.stringify(payload);
303
333
  globalScope = getGlobalScope();
304
334
  if (!(globalScope && 'CompressionStream' in globalScope)) return [3 /*break*/, 3];
305
335
  return [4 /*yield*/, gzipJson(payloadJson, globalScope)];
306
336
  case 2:
307
- _e = _g.sent();
337
+ _h = _k.sent();
308
338
  return [3 /*break*/, 4];
309
339
  case 3:
310
- _e = null;
311
- _g.label = 4;
340
+ _h = null;
341
+ _k.label = 4;
312
342
  case 4:
313
- gzipped = _e;
343
+ gzipped = _h;
314
344
  payloadSize = gzipped ? gzipped.byteLength : new Blob([payloadJson]).size;
315
345
  options = {
316
346
  headers: __assign({ 'Content-Type': 'application/json', Accept: '*/*', Authorization: "Bearer ".concat(apiKey), 'X-Client-Version': version, 'X-Client-Library': sessionReplayLibrary, 'X-Client-Url': url.substring(0, MAX_URL_LENGTH), 'X-Client-Sample-Rate': "".concat(sampleRate), 'X-Sampling-Hash-Alg': 'xxhash32' }, (gzipped ? { 'Content-Encoding': 'gzip' } : {})),
@@ -323,17 +353,21 @@ var SessionReplayTrackDestination = /** @class */ (function () {
323
353
  serverUrl = "".concat(getServerUrl(context.serverZone, this.trackServerUrl), "?").concat(urlParams.toString());
324
354
  return [4 /*yield*/, fetch(serverUrl, options)];
325
355
  case 5:
326
- res = _g.sent();
356
+ res = _k.sent();
327
357
  if (res === null) {
328
358
  this.completeRequest({ context: context, err: UNEXPECTED_ERROR_MESSAGE });
329
359
  return [2 /*return*/];
330
360
  }
361
+ if (res.status >= 200 && res.status < 300) {
362
+ skipCode = (_g = (_f = (_e = res.headers) === null || _e === void 0 ? void 0 : _e.get) === null || _f === void 0 ? void 0 : _f.call(_e, EVENT_SKIPPED_HEADER)) !== null && _g !== void 0 ? _g : null;
363
+ this.applyServerDirective(context.sessionId, skipCode);
364
+ }
331
365
  if (!!useRetry) return [3 /*break*/, 6];
332
366
  responseBody = '';
333
367
  try {
334
368
  responseBody = JSON.stringify(res.body, null, 2);
335
369
  }
336
- catch (_h) {
370
+ catch (_l) {
337
371
  // to avoid crash, but don't care about the error, add comment to avoid empty block lint error
338
372
  }
339
373
  this.completeRequest({ context: context, success: "".concat(res.status, ": ").concat(responseBody) });
@@ -341,23 +375,23 @@ var SessionReplayTrackDestination = /** @class */ (function () {
341
375
  case 6:
342
376
  responseBody = '';
343
377
  if (!(res.status === 413)) return [3 /*break*/, 10];
344
- _g.label = 7;
378
+ _k.label = 7;
345
379
  case 7:
346
- _g.trys.push([7, 9, , 10]);
380
+ _k.trys.push([7, 9, , 10]);
347
381
  return [4 /*yield*/, res.text()];
348
382
  case 8:
349
- responseBody = _g.sent();
383
+ responseBody = _k.sent();
350
384
  return [3 /*break*/, 10];
351
385
  case 9:
352
- _f = _g.sent();
386
+ _j = _k.sent();
353
387
  return [3 /*break*/, 10];
354
388
  case 10: return [4 /*yield*/, this.handleReponse(res.status, context, responseBody)];
355
389
  case 11:
356
- _g.sent();
357
- _g.label = 12;
390
+ _k.sent();
391
+ _k.label = 12;
358
392
  case 12: return [3 /*break*/, 14];
359
393
  case 13:
360
- e_3 = _g.sent();
394
+ e_3 = _k.sent();
361
395
  this.completeRequest({ context: context, err: e_3 });
362
396
  return [3 /*break*/, 14];
363
397
  case 14: return [2 /*return*/];
@@ -472,6 +506,85 @@ var SessionReplayTrackDestination = /** @class */ (function () {
472
506
  this.loggerProvider.log(success);
473
507
  }
474
508
  };
509
+ /**
510
+ * Applies the server's back-pressure signal carried on a 200 response.
511
+ *
512
+ * - `EVENT_SKIP_CODE_THROTTLED` (server-side rate limit): pause the flush schedule
513
+ * for `THROTTLED_FLUSH_PAUSE_MS` so we keep batching events instead of retry-storming.
514
+ * - `EVENT_SKIP_CODE_CAPTURE_DISABLED` / `EVENT_SKIP_CODE_INVALID_RANGE`: hard kill
515
+ * switch for this session — drop the queued contexts and stop accepting new ones.
516
+ * New sessions are unaffected.
517
+ * - `null` (clean 200, no header): clear any throttle pause; subsequent flushes resume
518
+ * on the normal cadence.
519
+ */
520
+ SessionReplayTrackDestination.prototype.applyServerDirective = function (sessionId, skipCode) {
521
+ if (skipCode === null) {
522
+ this.flushPauseUntilMs = 0;
523
+ return;
524
+ }
525
+ if (skipCode === EVENT_SKIP_CODE_THROTTLED) {
526
+ var wasInPause = this.flushPauseUntilMs > Date.now();
527
+ this.flushPauseUntilMs = Date.now() + THROTTLED_FLUSH_PAUSE_MS;
528
+ // Log only on pause-state transitions — a throttled server may reply to many
529
+ // batches per minute, and one log per batch would flood the console.
530
+ if (!wasInPause) {
531
+ this.loggerProvider.log("Session replay throttled by server; pausing flush schedule for ".concat(THROTTLED_FLUSH_PAUSE_MS / 1000, "s"));
532
+ }
533
+ return;
534
+ }
535
+ if (skipCode === EVENT_SKIP_CODE_CAPTURE_DISABLED || skipCode === EVENT_SKIP_CODE_INVALID_RANGE) {
536
+ this.killSession(sessionId, skipCode);
537
+ }
538
+ // Unknown skip codes are ignored — the server may add new ones, and our default
539
+ // behavior (treat as a normal 200) preserves throughput rather than penalizing the
540
+ // session for a code we don't recognize.
541
+ };
542
+ SessionReplayTrackDestination.prototype.killSession = function (sessionId, skipCode) {
543
+ var e_4, _a, e_5, _b;
544
+ if (this.killedSessions.has(sessionId))
545
+ return;
546
+ this.killedSessions.add(sessionId);
547
+ // Set preserves insertion order, so deleting the first key evicts the oldest entry.
548
+ if (this.killedSessions.size > MAX_KILLED_SESSIONS) {
549
+ try {
550
+ for (var _c = __values(this.killedSessions), _d = _c.next(); !_d.done; _d = _c.next()) {
551
+ var oldest = _d.value;
552
+ this.killedSessions.delete(oldest);
553
+ break;
554
+ }
555
+ }
556
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
557
+ finally {
558
+ try {
559
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
560
+ }
561
+ finally { if (e_4) throw e_4.error; }
562
+ }
563
+ }
564
+ this.loggerProvider.log("Session replay capture stopped for session ".concat(sessionId, " by server directive ").concat(skipCode, "; remaining events will be dropped"));
565
+ // Drain any queued contexts for this session so their IDB records get cleaned up
566
+ // via onComplete, instead of sitting in the queue waiting for a flush we'll never make.
567
+ var remaining = [];
568
+ try {
569
+ for (var _e = __values(this.queue), _f = _e.next(); !_f.done; _f = _e.next()) {
570
+ var queued = _f.value;
571
+ if (queued.sessionId === sessionId) {
572
+ this.completeRequest({ context: queued, err: SESSION_KILLED_MESSAGE });
573
+ }
574
+ else {
575
+ remaining.push(queued);
576
+ }
577
+ }
578
+ }
579
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
580
+ finally {
581
+ try {
582
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
583
+ }
584
+ finally { if (e_5) throw e_5.error; }
585
+ }
586
+ this.queue = remaining;
587
+ };
475
588
  return SessionReplayTrackDestination;
476
589
  }());
477
590
  export { SessionReplayTrackDestination };
@@ -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 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 { MAX_URL_LENGTH, KB_SIZE, MAX_KEEPALIVE_BYTES, WAF_PAYLOAD_TOO_LARGE_PATTERN } from './constants';\nimport { gzipJson } from './utils/gzip';\n\ninterface WorkerCompleteMessage {\n type: 'complete';\n id: string;\n err?: string;\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\nexport class SessionReplayTrackDestination implements AmplitudeSessionReplayTrackDestination {\n loggerProvider: ILogger;\n storageKey = '';\n trackServerUrl?: string;\n retryTimeout = 1000;\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<string, { context: SessionReplayDestinationContext; resolve: () => void }>();\n\n constructor({\n trackServerUrl,\n loggerProvider,\n payloadBatcher,\n workerScript,\n }: {\n trackServerUrl?: string;\n loggerProvider: ILogger;\n payloadBatcher?: PayloadBatcher;\n workerScript?: string;\n }) {\n this.loggerProvider = loggerProvider;\n this.payloadBatcher = payloadBatcher ? payloadBatcher : (payload) => payload;\n this.trackServerUrl = trackServerUrl;\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 loggerProvider.warn(`Session replay event send failed due to worker crash: ${e.message}`);\n pending.resolve();\n }\n this.pendingWorkerRequests.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 this.handlePayloadTooLargeResponse(pending.context, msg.isWaf);\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n }\n } else if (msg.type === 'complete') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\n this.completeRequest({ context: pending.context });\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\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 * 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 (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 this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, timeout);\n }\n\n async flush(useRetry = false) {\n const list = this.queue;\n this.queue = [];\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n for (const context of list) {\n await this.send(context, useRetry);\n }\n }\n\n async send(context: SessionReplayDestinationContext, useRetry = true) {\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 this.pendingWorkerRequests.set(id, { context, resolve });\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 },\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 CompressionStream is actually available; skipping the\n // await entirely preserves the synchronous fast-path for browsers/environments\n // (e.g. Jest) that don't support it, keeping retry-timing tests unaffected.\n const globalScope = getGlobalScope();\n const gzipped =\n globalScope && 'CompressionStream' in globalScope ? await gzipJson(payloadJson, globalScope) : null;\n const payloadSize = gzipped ? gzipped.byteLength : new Blob([payloadJson]).size;\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 };\n\n const serverUrl = `${getServerUrl(context.serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n const res = await fetch(serverUrl, options);\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE });\n return;\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 this.completeRequest({ context, err: e as string });\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 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"]}
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} 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\nexport class SessionReplayTrackDestination implements AmplitudeSessionReplayTrackDestination {\n loggerProvider: ILogger;\n storageKey = '';\n trackServerUrl?: string;\n retryTimeout = 1000;\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<string, { context: SessionReplayDestinationContext; resolve: () => void }>();\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 private killedSessions = new Set<string | number>();\n\n constructor({\n trackServerUrl,\n loggerProvider,\n payloadBatcher,\n workerScript,\n }: {\n trackServerUrl?: string;\n loggerProvider: ILogger;\n payloadBatcher?: PayloadBatcher;\n workerScript?: string;\n }) {\n this.loggerProvider = loggerProvider;\n this.payloadBatcher = payloadBatcher ? payloadBatcher : (payload) => payload;\n this.trackServerUrl = trackServerUrl;\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 loggerProvider.warn(`Session replay event send failed due to worker crash: ${e.message}`);\n pending.resolve();\n }\n this.pendingWorkerRequests.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 this.handlePayloadTooLargeResponse(pending.context, msg.isWaf);\n pending.resolve();\n this.pendingWorkerRequests.delete(msg.id);\n }\n } else if (msg.type === 'complete') {\n const pending = this.pendingWorkerRequests.get(msg.id);\n if (pending) {\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 }\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 * 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 effectiveTimeout = pauseRemaining > timeout ? pauseRemaining : timeout;\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 const list = this.queue;\n this.queue = [];\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n for (const context of list) {\n await this.send(context, useRetry);\n }\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 this.pendingWorkerRequests.set(id, { context, resolve });\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 },\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 CompressionStream is actually available; skipping the\n // await entirely preserves the synchronous fast-path for browsers/environments\n // (e.g. Jest) that don't support it, keeping retry-timing tests unaffected.\n const globalScope = getGlobalScope();\n const gzipped =\n globalScope && 'CompressionStream' in globalScope ? await gzipJson(payloadJson, globalScope) : null;\n const payloadSize = gzipped ? gzipped.byteLength : new Blob([payloadJson]).size;\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 };\n\n const serverUrl = `${getServerUrl(context.serverZone, this.trackServerUrl)}?${urlParams.toString()}`;\n const res = await fetch(serverUrl, options);\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 this.completeRequest({ context, err: e as string });\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 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 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.42.1";
1
+ export declare const VERSION = "1.42.3";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Autogenerated by `pnpm version-file`. DO NOT EDIT
2
- export var VERSION = '1.42.1';
2
+ export var VERSION = '1.42.3';
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,MAAM,CAAC,IAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["// Autogenerated by `pnpm version-file`. DO NOT EDIT\nexport const VERSION = '1.42.1';\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,MAAM,CAAC,IAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["// Autogenerated by `pnpm version-file`. DO NOT EDIT\nexport const VERSION = '1.42.3';\n"]}
@@ -1,4 +1,4 @@
1
1
  var 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";
2
- var 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,a){function o(e){try{c(n.next(e))}catch(e){a(e)}}function i(e){try{c(n.throw(e))}catch(e){a(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(o,i)}c((n=n.apply(e,t||[])).next())})}function s(e,t){var r,n,s,a={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]},o=Object.create((\"function\"==typeof Iterator?Iterator:Object).prototype);return o.next=i(0),o.throw=i(1),o.return=i(2),\"function\"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(i){return function(c){return function(i){if(r)throw new TypeError(\"Generator is already executing.\");for(;o&&(o=0,i[0]&&(a=0)),a;)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 a.label++,{value:i[1],done:!1};case 5:a.label++,n=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(s=a.trys,(s=s.length>0&&s[s.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){a.label=i[1];break}if(6===i[0]&&a.label<s[1]){a.label=s[1],s=i;break}if(s&&a.label<s[2]){a.label=s[2],a.ops.push(i);break}s[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}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 a,o=/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\"}(a||(a={}));var i=\"Network error occurred, event batch rejected\";function c(e,t){return n(this,void 0,void 0,function(){var r,a,o,i,c,u,l,d,p,f,h,y,v,b,g=this;return s(this,function(m){switch(m.label){case 0:return m.trys.push([0,4,,5]),r=t.CompressionStream,a=new r(\"gzip\"),o=a.writable.getWriter(),i=a.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,o.write((new TextEncoder).encode(e))];case 1:return m.sent(),[4,o.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())y=h.value,d.set(y,p),p+=y.length}catch(e){v={error:e}}finally{try{h&&!h.done&&(b=f.return)&&b.call(f)}finally{if(v)throw v.error}}return[2,d];case 4:return m.sent(),[2,null];case 5:return[2]}})})}function u(e,t){var a,u,l,d;return n(this,void 0,void 0,function(){var n,p,f,h,y,v,b,g,m,w,S;return s(this,function(s){switch(s.label){case 0:return s.trys.push([0,10,,11]),\"CompressionStream\"in self?[4,c(e,self)]:[3,2];case 1:return p=s.sent(),[3,3];case 2:p=null,s.label=3;case 3:return n=p,f=\"\".concat(null!==(u=null===(a=t.version)||void 0===a?void 0:a.type)&&void 0!==u?u:\"standalone\",\"/\").concat(null!==(d=null===(l=t.version)||void 0===l?void 0:l.version)&&void 0!==d?d:t.sdkVersion),h=new URLSearchParams({device_id:t.deviceId,session_id:\"\".concat(t.sessionId),type:t.eventType}),y=\"\".concat((T=t.serverZone,x=t.trackServerUrl,x||(\"STAGING\"===T?\"https://api-sr.stag2.amplitude.com/sessions/v2/track\":\"EU\"===T?\"https://api-sr.eu.amplitude.com/sessions/v2/track\":\"https://api-sr.amplitude.com/sessions/v2/track\")),\"?\").concat(h.toString()),v=r({\"Content-Type\":\"application/json\",Accept:\"*/*\",Authorization:\"Bearer \".concat(t.apiKey),\"X-Client-Version\":t.sdkVersion,\"X-Client-Library\":f,\"X-Client-Url\":t.currentUrl.substring(0,1e3),\"X-Client-Sample-Rate\":\"\".concat(t.sampleRate),\"X-Sampling-Hash-Alg\":\"xxhash32\"},n?{\"Content-Encoding\":\"gzip\"}:{}),b=n?n.byteLength:new Blob([e]).size,[4,fetch(y,{method:\"POST\",headers:v,body:null!=n?n:e,keepalive:b<=65536})];case 4:if(null===(g=s.sent()))return[2,{shouldRetry:!1,success:!1,message:\"Unexpected error occurred\"}];if(g.status>=200&&g.status<300)return m=Math.round(new Blob(t.events).size/1024),[2,{shouldRetry:!1,success:!0,message:\"Session replay event batch tracked successfully for session id \".concat(t.sessionId,\", size of events: \").concat(m,\" KB\")}];if(413!==g.status)return[3,9];w=\"\",s.label=5;case 5:return s.trys.push([5,7,,8]),[4,g.text()];case 6:return w=s.sent(),[3,8];case 7:return s.sent(),[3,8];case 8:return[2,{shouldRetry:!1,success:!1,message:i,payloadTooLarge:!0,isWaf:o.test(w)}];case 9:return g.status>=500||408===g.status||429===g.status||499===g.status?[2,{shouldRetry:!0,success:!1,message:\"HTTP \".concat(g.status)}]:[2,{shouldRetry:!1,success:!1,message:i}];case 10:return S=s.sent(),[2,{shouldRetry:!1,success:!1,message:String(S)}];case 11:return[2]}var T,x})})}function l(e,t,r,a){return n(this,void 0,void 0,function(){var n,o,i;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(o=s.sent()).success?(postMessage({type:\"log\",id:e,message:o.message}),postMessage({type:\"complete\",id:e}),[2]):o.payloadTooLarge&&a?(postMessage({type:\"payload_too_large\",id:e,isWaf:!0===o.isWaf}),[2]):a&&o.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 i=n>=r.flushMaxRetries?\"Session replay event batch rejected due to exceeded retry count\":o.message,postMessage({type:\"warn\",id:e,message:i}),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,a,o,i,c;return s(this,function(s){switch(s.label){case 0:return t=e.data,r=t.type,n=t.id,a=t.payload,o=t.context,i=t.useRetry,\"send\"!==r?[3,2]:(c=JSON.stringify(a),[4,l(n,c,o,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";
2
+ var 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,a){function o(e){try{c(n.next(e))}catch(e){a(e)}}function i(e){try{c(n.throw(e))}catch(e){a(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(o,i)}c((n=n.apply(e,t||[])).next())})}function s(e,t){var r,n,s,a={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]},o=Object.create((\"function\"==typeof Iterator?Iterator:Object).prototype);return o.next=i(0),o.throw=i(1),o.return=i(2),\"function\"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(i){return function(c){return function(i){if(r)throw new TypeError(\"Generator is already executing.\");for(;o&&(o=0,i[0]&&(a=0)),a;)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 a.label++,{value:i[1],done:!1};case 5:a.label++,n=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(s=a.trys,(s=s.length>0&&s[s.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){a.label=i[1];break}if(6===i[0]&&a.label<s[1]){a.label=s[1],s=i;break}if(s&&a.label<s[2]){a.label=s[2],a.ops.push(i);break}s[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(e,a)}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 a,o=/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\"}(a||(a={}));var i=\"Network error occurred, event batch rejected\";function c(e,t){return n(this,void 0,void 0,function(){var r,a,o,i,c,u,l,d,p,f,h,v,y,g,b=this;return s(this,function(m){switch(m.label){case 0:return m.trys.push([0,4,,5]),r=t.CompressionStream,a=new r(\"gzip\"),o=a.writable.getWriter(),i=a.readable.getReader(),c=[],u=n(b,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,o.write((new TextEncoder).encode(e))];case 1:return m.sent(),[4,o.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&&(g=f.return)&&g.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 a,u,l,d,p,f,h;return n(this,void 0,void 0,function(){var n,v,y,g,b,m,S,w,T,k,R,x;return s(this,function(s){switch(s.label){case 0:return s.trys.push([0,10,,11]),\"CompressionStream\"in self?[4,c(e,self)]:[3,2];case 1:return v=s.sent(),[3,3];case 2:v=null,s.label=3;case 3:return n=v,y=\"\".concat(null!==(u=null===(a=t.version)||void 0===a?void 0:a.type)&&void 0!==u?u:\"standalone\",\"/\").concat(null!==(d=null===(l=t.version)||void 0===l?void 0:l.version)&&void 0!==d?d:t.sdkVersion),g=new URLSearchParams({device_id:t.deviceId,session_id:\"\".concat(t.sessionId),type:t.eventType}),b=\"\".concat((E=t.serverZone,U=t.trackServerUrl,U||(\"STAGING\"===E?\"https://api-sr.stag2.amplitude.com/sessions/v2/track\":\"EU\"===E?\"https://api-sr.eu.amplitude.com/sessions/v2/track\":\"https://api-sr.amplitude.com/sessions/v2/track\")),\"?\").concat(g.toString()),m=r({\"Content-Type\":\"application/json\",Accept:\"*/*\",Authorization:\"Bearer \".concat(t.apiKey),\"X-Client-Version\":t.sdkVersion,\"X-Client-Library\":y,\"X-Client-Url\":t.currentUrl.substring(0,1e3),\"X-Client-Sample-Rate\":\"\".concat(t.sampleRate),\"X-Sampling-Hash-Alg\":\"xxhash32\"},n?{\"Content-Encoding\":\"gzip\"}:{}),S=n?n.byteLength:new Blob([e]).size,[4,fetch(b,{method:\"POST\",headers:m,body:null!=n?n:e,keepalive:S<=65536})];case 4:if(null===(w=s.sent()))return[2,{shouldRetry:!1,success:!1,message:\"Unexpected error occurred\"}];if(w.status>=200&&w.status<300)return T=Math.round(new Blob(t.events).size/1024),k=null!==(h=null===(f=null===(p=w.headers)||void 0===p?void 0:p.get)||void 0===f?void 0:f.call(p,\"X-Session-Replay-Event-Skipped\"))&&void 0!==h?h:null,[2,{shouldRetry:!1,success:!0,message:\"Session replay event batch tracked successfully for session id \".concat(t.sessionId,\", size of events: \").concat(T,\" KB\"),skipCode:k}];if(413!==w.status)return[3,9];R=\"\",s.label=5;case 5:return s.trys.push([5,7,,8]),[4,w.text()];case 6:return R=s.sent(),[3,8];case 7:return s.sent(),[3,8];case 8:return[2,{shouldRetry:!1,success:!1,message:i,payloadTooLarge:!0,isWaf:o.test(R)}];case 9:return w.status>=500||408===w.status||429===w.status||499===w.status?[2,{shouldRetry:!0,success:!1,message:\"HTTP \".concat(w.status)}]:[2,{shouldRetry:!1,success:!1,message:i}];case 10:return x=s.sent(),[2,{shouldRetry:!1,success:!1,message:String(x)}];case 11:return[2]}var E,U})})}function l(e,t,r,a){var o;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!==(o=i.skipCode)&&void 0!==o?o:null}),[2]):i.payloadTooLarge&&a?(postMessage({type:\"payload_too_large\",id:e,isWaf:!0===i.isWaf}),[2]):a&&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,a,o,i,c;return s(this,function(s){switch(s.label){case 0:return t=e.data,r=t.type,n=t.id,a=t.payload,o=t.context,i=t.useRetry,\"send\"!==r?[3,2]:(c=JSON.stringify(a),[4,l(n,c,o,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";
3
3
 
4
4
  export { compressionScript, trackDestinationScript };