@sentry/replay 7.52.1 → 7.53.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.
package/esm/index.js CHANGED
@@ -3285,6 +3285,23 @@ var NodeType;
3285
3285
  NodeType[NodeType["Comment"] = 5] = "Comment";
3286
3286
  })(NodeType || (NodeType = {}));
3287
3287
 
3288
+ /* eslint-disable @typescript-eslint/naming-convention */
3289
+
3290
+ var EventType; (function (EventType) {
3291
+ const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
3292
+ const Load = 1; EventType[EventType["Load"] = Load] = "Load";
3293
+ const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
3294
+ const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
3295
+ const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
3296
+ const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
3297
+ const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
3298
+ })(EventType || (EventType = {}));
3299
+
3300
+ /**
3301
+ * This is a partial copy of rrweb's eventWithTime type which only contains the properties
3302
+ * we specifcally need in the SDK.
3303
+ */
3304
+
3288
3305
  /**
3289
3306
  * Converts a timestamp to ms, if it was in s, or keeps it as ms.
3290
3307
  */
@@ -3327,7 +3344,18 @@ async function addEvent(
3327
3344
  replay.eventBuffer.clear();
3328
3345
  }
3329
3346
 
3330
- return await replay.eventBuffer.addEvent(event);
3347
+ const replayOptions = replay.getOptions();
3348
+
3349
+ const eventAfterPossibleCallback =
3350
+ typeof replayOptions.beforeAddRecordingEvent === 'function' && event.type === EventType.Custom
3351
+ ? replayOptions.beforeAddRecordingEvent(event)
3352
+ : event;
3353
+
3354
+ if (!eventAfterPossibleCallback) {
3355
+ return;
3356
+ }
3357
+
3358
+ return await replay.eventBuffer.addEvent(eventAfterPossibleCallback);
3331
3359
  } catch (error) {
3332
3360
  (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
3333
3361
  await replay.stop('addEvent');
@@ -6303,23 +6331,6 @@ function debounce(func, wait, options) {
6303
6331
  return debounced;
6304
6332
  }
6305
6333
 
6306
- /* eslint-disable @typescript-eslint/naming-convention */
6307
-
6308
- var EventType; (function (EventType) {
6309
- const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
6310
- const Load = 1; EventType[EventType["Load"] = Load] = "Load";
6311
- const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
6312
- const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
6313
- const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
6314
- const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
6315
- const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
6316
- })(EventType || (EventType = {}));
6317
-
6318
- /**
6319
- * This is a partial copy of rrweb's eventWithTime type which only contains the properties
6320
- * we specifcally need in the SDK.
6321
- */
6322
-
6323
6334
  /**
6324
6335
  * Handler for recording events.
6325
6336
  *
@@ -6393,6 +6404,30 @@ function getHandleRecordingEmit(replay) {
6393
6404
  }
6394
6405
  }
6395
6406
 
6407
+ const options = replay.getOptions();
6408
+
6409
+ // TODO: We want this as an experiment so that we can test
6410
+ // internally and create metrics before making this the default
6411
+ if (options._experiments.delayFlushOnCheckout) {
6412
+ // If the full snapshot is due to an initial load, we will not have
6413
+ // a previous session ID. In this case, we want to buffer events
6414
+ // for a set amount of time before flushing. This can help avoid
6415
+ // capturing replays of users that immediately close the window.
6416
+ setTimeout(() => replay.conditionalFlush(), options._experiments.delayFlushOnCheckout);
6417
+
6418
+ // Cancel any previously debounced flushes to ensure there are no [near]
6419
+ // simultaneous flushes happening. The latter request should be
6420
+ // insignificant in this case, so wait for additional user interaction to
6421
+ // trigger a new flush.
6422
+ //
6423
+ // This can happen because there's no guarantee that a recording event
6424
+ // happens first. e.g. a mouse click can happen and trigger a debounced
6425
+ // flush before the checkout.
6426
+ replay.cancelFlush();
6427
+
6428
+ return true;
6429
+ }
6430
+
6396
6431
  // Flush immediately so that we do not miss the first segment, otherwise
6397
6432
  // it can prevent loading on the UI. This will cause an increase in short
6398
6433
  // replays (e.g. opening and closing a tab quickly), but these can be
@@ -7158,7 +7193,17 @@ class ReplayContainer {
7158
7193
  }
7159
7194
 
7160
7195
  /**
7161
- *
7196
+ * Only flush if `this.recordingMode === 'session'`
7197
+ */
7198
+ conditionalFlush() {
7199
+ if (this.recordingMode === 'buffer') {
7200
+ return Promise.resolve();
7201
+ }
7202
+
7203
+ return this.flushImmediate();
7204
+ }
7205
+
7206
+ /**
7162
7207
  * Always flush via `_debouncedFlush` so that we do not have flushes triggered
7163
7208
  * from calling both `flush` and `_debouncedFlush`. Otherwise, there could be
7164
7209
  * cases of mulitple flushes happening closely together.
@@ -7169,6 +7214,13 @@ class ReplayContainer {
7169
7214
  return this._debouncedFlush.flush() ;
7170
7215
  }
7171
7216
 
7217
+ /**
7218
+ * Cancels queued up flushes.
7219
+ */
7220
+ cancelFlush() {
7221
+ this._debouncedFlush.cancel();
7222
+ }
7223
+
7172
7224
  /** Get the current sesion (=replay) ID */
7173
7225
  getSessionId() {
7174
7226
  return this.session && this.session.id;
@@ -7418,7 +7470,7 @@ class ReplayContainer {
7418
7470
  // Send replay when the page/tab becomes hidden. There is no reason to send
7419
7471
  // replay if it becomes visible, since no actions we care about were done
7420
7472
  // while it was hidden
7421
- this._conditionalFlush();
7473
+ void this.conditionalFlush();
7422
7474
  }
7423
7475
 
7424
7476
  /**
@@ -7502,17 +7554,6 @@ class ReplayContainer {
7502
7554
  return Promise.all(createPerformanceSpans(this, createPerformanceEntries(entries)));
7503
7555
  }
7504
7556
 
7505
- /**
7506
- * Only flush if `this.recordingMode === 'session'`
7507
- */
7508
- _conditionalFlush() {
7509
- if (this.recordingMode === 'buffer') {
7510
- return;
7511
- }
7512
-
7513
- void this.flushImmediate();
7514
- }
7515
-
7516
7557
  /**
7517
7558
  * Clear _context
7518
7559
  */
@@ -7874,6 +7915,8 @@ class Replay {
7874
7915
  ignore = [],
7875
7916
  maskFn,
7876
7917
 
7918
+ beforeAddRecordingEvent,
7919
+
7877
7920
  // eslint-disable-next-line deprecation/deprecation
7878
7921
  blockClass,
7879
7922
  // eslint-disable-next-line deprecation/deprecation
@@ -7931,6 +7974,7 @@ class Replay {
7931
7974
  networkCaptureBodies,
7932
7975
  networkRequestHeaders: _getMergedNetworkHeaders(networkRequestHeaders),
7933
7976
  networkResponseHeaders: _getMergedNetworkHeaders(networkResponseHeaders),
7977
+ beforeAddRecordingEvent,
7934
7978
 
7935
7979
  _experiments,
7936
7980
  };