@multiplayer-app/session-recorder-browser 2.0.18 → 2.0.24

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/README.md CHANGED
@@ -98,8 +98,8 @@ SessionRecorder.init({
98
98
 
99
99
  showWidget: true, // show in‑app recording widget (default: true)
100
100
  recordCanvas: true, // record canvas elements (default: false)
101
- inlineImages: true, // inline images as base64 so they survive asset removal (default: true)
102
- inlineStylesheet: true, // inline stylesheets so they survive asset removal (default: true)
101
+ inlineImages: true, // opt-in: inline images as base64 (requires CORS on cross-origin asset hosts; default: false)
102
+ inlineStylesheet: true, // opt-in: inline stylesheets (cross-origin hosts may need CORS; default: false)
103
103
  // Add domains to not capture OTLP data in the session recording
104
104
  ignoreUrls: [
105
105
  /https:\/\/domain\.to\.ignore\/.*/, // can be regex or string
@@ -119,7 +119,7 @@ SessionRecorder.init({
119
119
  // crash buffer: keep a rolling window of rrweb + traces when no recording is active.
120
120
  // when user starts a session or saves (e.g. on error), the buffer is flushed into the session.
121
121
  buffering: {
122
- enabled: false, // enable/disable buffering (default: false)
122
+ enabled: true, // enable/disable buffering (default: true)
123
123
  windowMinutes: 0.5, // rolling window size in minutes (default: 0.5)
124
124
  snapshotIntervalMs: 20000 // full snapshot interval while buffering in ms (default: 20000)
125
125
  },
@@ -222,6 +222,15 @@ SessionRecorder.init({
222
222
  })
223
223
  ```
224
224
 
225
+ ### Important: Inlining images and stylesheets (CORS)
226
+
227
+ By default, **`inlineImages`** and **`inlineStylesheet`** are **`false`**. That avoids failed cross-origin requests and DevTools noise when assets are served from another host (for example S3 or a CDN) that does not send CORS headers such as **`Access-Control-Allow-Origin`** for your app.
228
+
229
+ If you enable either option:
230
+
231
+ - The browser must be allowed to **read** those resources from script (image pixels for base64 inlining, or stylesheet text for inlining). Configure CORS on the asset host for your frontend origin, or serve assets same-origin via a proxy.
232
+ - With defaults left off, recordings still store normal **`src`** and stylesheet links; replay loads them like a normal page when URLs remain valid.
233
+
225
234
  ### Manual session recording
226
235
 
227
236
  Below is an example showing how to create a session recording in `MANUAL` mode. Manual session recordings stream and save all the data between calling `start` and `stop`.
@@ -388,6 +397,8 @@ For React Native applications (iOS and Android), use the dedicated React Native
388
397
 
389
398
  For more details on how the Multiplayer Session Recorder integrates with your backend architecture and system auto-documentation, check out our [official documentation](https://www.multiplayer.app/docs/features/system-auto-documentation/).
390
399
 
400
+ **Inlining and CORS:** See [Inlining images and stylesheets (CORS)](#important-inlining-images-and-stylesheets-cors) above for defaults and when you must configure CORS on asset hosts.
401
+
391
402
  ## License
392
403
 
393
404
  This library is distributed under the [MIT License](./LICENSE).
@@ -25163,7 +25163,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
25163
25163
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
25164
25164
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
25165
25165
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
25166
- const PACKAGE_VERSION_EXPORT = "2.0.18" || 0;
25166
+ const PACKAGE_VERSION_EXPORT = "2.0.24" || 0;
25167
25167
  // Regex patterns for OpenTelemetry ignore URLs
25168
25168
  const OTEL_IGNORE_URLS = [
25169
25169
  // Traces endpoint
@@ -25249,8 +25249,11 @@ const BASE_CONFIG = {
25249
25249
  apiBaseUrl: _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_BASE_API_URL,
25250
25250
  exporterEndpoint: _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
25251
25251
  recordCanvas: false,
25252
- inlineImages: true,
25253
- inlineStylesheet: true,
25252
+ // Off by default: inlining reads pixels via canvas and requires CORS on cross-origin hosts (e.g. S3).
25253
+ // Set true when asset URLs send Access-Control-Allow-Origin for your app origin.
25254
+ inlineImages: false,
25255
+ // Off by default: inlining fetches stylesheet text; cross-origin <link> assets need CORS when enabled.
25256
+ inlineStylesheet: false,
25254
25257
  recordNavigation: true,
25255
25258
  schemifyDocSpanPayload: true,
25256
25259
  ignoreUrls: [],
@@ -25263,7 +25266,7 @@ const BASE_CONFIG = {
25263
25266
  widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
25264
25267
  useWebsocket: true,
25265
25268
  buffering: {
25266
- enabled: false,
25269
+ enabled: true,
25267
25270
  windowMinutes: 0.5,
25268
25271
  snapshotIntervalMs: 20000,
25269
25272
  },
@@ -26904,6 +26907,7 @@ __webpack_require__.r(__webpack_exports__);
26904
26907
 
26905
26908
  class RecorderBrowserSDK {
26906
26909
  constructor() {
26910
+ this.generation = 0;
26907
26911
  this.intervals = {
26908
26912
  restart: null,
26909
26913
  bufferSnapshot: null,
@@ -26939,12 +26943,15 @@ class RecorderBrowserSDK {
26939
26943
  throw new Error('Configuration not initialized. Call init() before start().');
26940
26944
  }
26941
26945
  this.startedAt = new Date().toISOString();
26946
+ const gen = ++this.generation;
26942
26947
  this.stopFn = (0,rrweb__WEBPACK_IMPORTED_MODULE_6__.record)({
26943
26948
  ...this._buildRecordOptions(),
26944
26949
  emit: async (event) => {
26950
+ if (gen !== this.generation)
26951
+ return;
26945
26952
  const ts = event.timestamp;
26946
26953
  if (!sessionId) {
26947
- await this._handleBufferOnlyEvent(event, ts);
26954
+ await this._handleBufferOnlyEvent(event, ts, gen);
26948
26955
  return;
26949
26956
  }
26950
26957
  this._handleLiveSessionEvent(event, ts, sessionId, sessionType);
@@ -26960,6 +26967,7 @@ class RecorderBrowserSDK {
26960
26967
  var _a;
26961
26968
  try {
26962
26969
  (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26970
+ this.stopFn = undefined;
26963
26971
  this.start(sessionId, sessionType);
26964
26972
  }
26965
26973
  catch (_e) {
@@ -26973,6 +26981,7 @@ class RecorderBrowserSDK {
26973
26981
  var _a, _b, _c;
26974
26982
  (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26975
26983
  this.stopFn = undefined;
26984
+ this.generation++;
26976
26985
  if (!((_b = this.config) === null || _b === void 0 ? void 0 : _b.useWebsocket)) {
26977
26986
  (_c = this.socketService) === null || _c === void 0 ? void 0 : _c.close();
26978
26987
  }
@@ -27012,13 +27021,15 @@ class RecorderBrowserSDK {
27012
27021
  * @param event - Event.
27013
27022
  * @param ts - Timestamp.
27014
27023
  */
27015
- async _handleBufferOnlyEvent(event, ts) {
27024
+ async _handleBufferOnlyEvent(event, ts, gen) {
27016
27025
  if (!this.crashBuffer)
27017
27026
  return;
27018
27027
  try {
27019
27028
  this._applyConsoleMasking(event);
27020
27029
  const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
27021
27030
  this.stoppedAt = new Date(ts).toISOString();
27031
+ if (gen !== this.generation)
27032
+ return;
27022
27033
  await this.crashBuffer.appendEvent({
27023
27034
  ts,
27024
27035
  isFullSnapshot: event.type === _rrweb_types__WEBPACK_IMPORTED_MODULE_1__.EventType.FullSnapshot,
@@ -27292,10 +27303,11 @@ __webpack_require__.r(__webpack_exports__);
27292
27303
 
27293
27304
 
27294
27305
  class CrashBufferService {
27295
- constructor(db, tabId, windowMs) {
27306
+ constructor(db, tabId, windowMs, ready = Promise.resolve()) {
27296
27307
  this.db = db;
27297
27308
  this.tabId = tabId;
27298
27309
  this.windowMs = windowMs;
27310
+ this.ready = ready;
27299
27311
  this.lastPruneAt = 0;
27300
27312
  this.pruneInFlight = null;
27301
27313
  this.isActive = true;
@@ -27318,6 +27330,7 @@ class CrashBufferService {
27318
27330
  if (!this.isActive)
27319
27331
  return;
27320
27332
  const isFullSnapshot = Boolean(payload.isFullSnapshot);
27333
+ await this.ready;
27321
27334
  await this._safe(async () => {
27322
27335
  await this.db.appendEvent({
27323
27336
  tabId: this.tabId,
@@ -27338,6 +27351,7 @@ class CrashBufferService {
27338
27351
  if (!this.isActive)
27339
27352
  return;
27340
27353
  let errorEvent = null;
27354
+ await this.ready;
27341
27355
  await this._safe(async () => {
27342
27356
  const records = payload.map((p) => {
27343
27357
  var _a, _b;
@@ -27386,6 +27400,7 @@ class CrashBufferService {
27386
27400
  }
27387
27401
  async snapshot(_windowMs, now = Date.now()) {
27388
27402
  var _a, _b;
27403
+ await this.ready;
27389
27404
  const stoppedAt = now;
27390
27405
  const startedAt = Math.max(0, stoppedAt - this.windowMs);
27391
27406
  // Always include a full snapshot "anchor" if one exists at/before the window start.
@@ -28026,6 +28041,8 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
28026
28041
  this.sessionId = null;
28027
28042
  this.usePostMessage = false;
28028
28043
  this.isInitialized = false;
28044
+ this.lastUserPayload = null;
28045
+ this.lastSubscribeSession = null;
28029
28046
  this.options = {
28030
28047
  apiKey: '',
28031
28048
  socketUrl: '',
@@ -28088,6 +28105,15 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
28088
28105
  this.isConnecting = false;
28089
28106
  this.isConnected = true;
28090
28107
  this.usePostMessage = false;
28108
+ // Re-establish identity and session on every (re)connect: socket.io's auto-reconnect
28109
+ // fires 'ready' again after a drop, but the server has no memory of the previous
28110
+ // setUser/subscribe calls — the client must replay them.
28111
+ if (this.lastUserPayload && this.socket) {
28112
+ this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, this.lastUserPayload);
28113
+ }
28114
+ if (this.lastSubscribeSession) {
28115
+ this._emitSubscribe(this.lastSubscribeSession);
28116
+ }
28091
28117
  this.flushQueue();
28092
28118
  });
28093
28119
  this.socket.on('disconnect', (err) => {
@@ -28154,16 +28180,33 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
28154
28180
  this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_ADD_EVENT, event);
28155
28181
  }
28156
28182
  subscribeToSession(session) {
28183
+ // Remember the session so reconnects replay subscribe + started.
28184
+ this.lastSubscribeSession = session;
28185
+ this._emitSubscribe(session);
28186
+ }
28187
+ _emitSubscribe(session) {
28157
28188
  this.sessionId = session.shortId || session._id;
28158
- const payload = {
28189
+ const subscribePayload = {
28159
28190
  projectId: session.project,
28160
28191
  workspaceId: session.workspace,
28161
28192
  debugSessionId: this.sessionId,
28162
28193
  sessionType: session.creationType,
28163
28194
  };
28164
- this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SUBSCRIBE_EVENT, payload);
28165
- // use long id instead of short id
28166
- this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STARTED_EVENT, { debugSessionId: session._id });
28195
+ const startedPayload = { debugSessionId: session._id };
28196
+ // Send directly (not via the queue). The queue would cause a duplicate emit on
28197
+ // the next 'ready' alongside the replay, since 'ready' also replays lastSubscribeSession.
28198
+ if (this.usePostMessage) {
28199
+ this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SUBSCRIBE_EVENT, subscribePayload);
28200
+ this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STARTED_EVENT, startedPayload);
28201
+ }
28202
+ else if (this.socket && this.isConnected) {
28203
+ this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SUBSCRIBE_EVENT, subscribePayload);
28204
+ this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STARTED_EVENT, startedPayload);
28205
+ }
28206
+ else {
28207
+ // Not connected: 'ready' will replay via lastSubscribeSession once the socket is up.
28208
+ this._initConnection();
28209
+ }
28167
28210
  }
28168
28211
  unsubscribeFromSession(stopSession) {
28169
28212
  if (this.sessionId) {
@@ -28172,9 +28215,23 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
28172
28215
  this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STOPPED_EVENT, {});
28173
28216
  }
28174
28217
  }
28218
+ this.lastSubscribeSession = null;
28175
28219
  }
28176
28220
  setUser(data) {
28177
- this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, data);
28221
+ // Remember the last identity so 'ready' (initial connect + every reconnect) can replay it.
28222
+ // Send directly here rather than queuing: the queue would cause a duplicate emit on the
28223
+ // next 'ready' alongside the replay.
28224
+ this.lastUserPayload = data;
28225
+ if (this.usePostMessage) {
28226
+ this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, data);
28227
+ }
28228
+ else if (this.socket && this.isConnected) {
28229
+ this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, data);
28230
+ }
28231
+ else {
28232
+ // Not connected yet: 'ready' will replay lastUserPayload once the socket is up.
28233
+ this._initConnection();
28234
+ }
28178
28235
  }
28179
28236
  close() {
28180
28237
  return new Promise((resolve) => {
@@ -28417,13 +28474,11 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28417
28474
  this._start();
28418
28475
  }
28419
28476
  else {
28420
- // Buffer-only recording when there is no active debug session.
28421
28477
  this._startBufferOnlyRecording();
28422
28478
  }
28423
28479
  this._registerWidgetEvents();
28424
28480
  this._registerSocketServiceListeners();
28425
28481
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_9__["default"].sendMessage('state-change', this.sessionState);
28426
- // Emit init observable event
28427
28482
  this.emit('init', [this]);
28428
28483
  }
28429
28484
  _setupCrashBuffer() {
@@ -28431,7 +28486,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28431
28486
  if ((_a = this._configs.buffering) === null || _a === void 0 ? void 0 : _a.enabled) {
28432
28487
  const windowMinutes = this._configs.buffering.windowMinutes || 0.5;
28433
28488
  const windowMs = Math.max(10000, windowMinutes * 60 * 1000);
28434
- this._crashBuffer = new _services_crashBuffer_service__WEBPACK_IMPORTED_MODULE_13__.CrashBufferService(this._bufferDb, this._tabId, windowMs);
28489
+ const ready = this._bufferDb.clearTab(this._tabId).catch(() => undefined);
28490
+ this._crashBuffer = new _services_crashBuffer_service__WEBPACK_IMPORTED_MODULE_13__.CrashBufferService(this._bufferDb, this._tabId, windowMs, ready);
28435
28491
  this._recorder.setCrashBuffer(this._crashBuffer);
28436
28492
  this._tracer.setCrashBuffer(this._crashBuffer);
28437
28493
  this._crashBuffer.on('error-span-appended', (payload) => {
@@ -28483,10 +28539,14 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28483
28539
  }
28484
28540
  _startBufferOnlyRecording() {
28485
28541
  var _a, _b;
28486
- if (this.sessionId ||
28487
- !this._crashBuffer ||
28488
- !((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled) ||
28489
- this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
28542
+ // NOTE: `this.sessionId` is intentionally NOT checked. `_stop()` runs
28543
+ // before `_clearSession()` (the stopSession API call sits between them),
28544
+ // so the clear().then() chain fires while sessionId is still set.
28545
+ // Bailing on sessionId here meant rrweb never restarted after manual
28546
+ // stop, leaving the buffer with no FullSnapshot and silently breaking
28547
+ // exception-triggered flushBuffer. `_recorder.restart(null, ...)` passes
28548
+ // null explicitly, so it's safe regardless of `this.sessionId`.
28549
+ if (!this._crashBuffer || !((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled) || this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
28490
28550
  return;
28491
28551
  }
28492
28552
  void this._recorder.restart(null, _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL);
@@ -28556,9 +28616,10 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28556
28616
  async stop(comment) {
28557
28617
  try {
28558
28618
  this._checkOperation('stop');
28619
+ const sid = this.sessionId;
28559
28620
  this._stop();
28560
28621
  if (this.continuousRecording) {
28561
- await this._apiService.stopContinuousDebugSession(this.sessionId);
28622
+ await this._apiService.stopContinuousDebugSession(sid);
28562
28623
  this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
28563
28624
  }
28564
28625
  else {
@@ -28566,10 +28627,9 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28566
28627
  sessionAttributes: { comment },
28567
28628
  stoppedAt: this._recorder.stoppedAt,
28568
28629
  };
28569
- const response = await this._apiService.stopSession(this.sessionId, request);
28630
+ const response = await this._apiService.stopSession(sid, request);
28570
28631
  _eventBus__WEBPACK_IMPORTED_MODULE_7__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_RESPONSE, response);
28571
28632
  }
28572
- this._clearSession();
28573
28633
  }
28574
28634
  catch (error) {
28575
28635
  this.error = error.message;
@@ -28605,15 +28665,15 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28605
28665
  async cancel() {
28606
28666
  try {
28607
28667
  this._checkOperation('cancel');
28668
+ const sid = this.sessionId;
28608
28669
  this._stop();
28609
28670
  if (this.continuousRecording) {
28610
- await this._apiService.stopContinuousDebugSession(this.sessionId);
28671
+ await this._apiService.stopContinuousDebugSession(sid);
28611
28672
  this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
28612
28673
  }
28613
28674
  else {
28614
- await this._apiService.cancelSession(this.sessionId);
28675
+ await this._apiService.cancelSession(sid);
28615
28676
  }
28616
- this._clearSession();
28617
28677
  }
28618
28678
  catch (error) {
28619
28679
  this.error = error.message;
@@ -28665,12 +28725,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28665
28725
  }
28666
28726
  }
28667
28727
  async _flushBuffer(sessionId) {
28668
- var _a, _b;
28669
- if (!sessionId ||
28670
- !this._crashBuffer ||
28671
- this._isFlushingBuffer ||
28672
- !((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled) ||
28673
- this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
28728
+ if (!sessionId || !this._crashBuffer || this._isFlushingBuffer) {
28674
28729
  return null;
28675
28730
  }
28676
28731
  this._isFlushingBuffer = true;
@@ -28860,6 +28915,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28860
28915
  });
28861
28916
  this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_SAVE_BUFFER_EVENT, (payload) => {
28862
28917
  var _a;
28918
+ if (this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped)
28919
+ return;
28863
28920
  this._flushBuffer((_a = payload === null || payload === void 0 ? void 0 : payload.debugSession) === null || _a === void 0 ? void 0 : _a._id);
28864
28921
  });
28865
28922
  }
@@ -28930,7 +28987,18 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
28930
28987
  this._tracer.stop();
28931
28988
  this._recorder.stop();
28932
28989
  this._navigationRecorder.stop();
28933
- this._startBufferOnlyRecording();
28990
+ // Clear session identity synchronously. The buffer-restart chain and the
28991
+ // error-span-appended listener both gate on `this.sessionId === null`;
28992
+ // deferring this to `_clearSession()` (after the network stopSession
28993
+ // call) left them seeing a stale id and silently no-oping. Callers that
28994
+ // need the id for the stop/cancel API must capture it before _stop().
28995
+ this.session = null;
28996
+ this.sessionId = null;
28997
+ // rrweb assigns new node IDs on each record() call, so the next buffer
28998
+ // segment must not carry events from the previous generation. Await the
28999
+ // clear so its IDB tx can't race past the fresh FullSnapshot.
29000
+ const cleared = this._crashBuffer ? this._crashBuffer.clear() : Promise.resolve();
29001
+ void cleared.catch(() => undefined).then(() => this._startBufferOnlyRecording());
28934
29002
  }
28935
29003
  /**
28936
29004
  * Pause the session tracing and recording
@@ -57765,6 +57833,7 @@ __webpack_require__.r(__webpack_exports__);
57765
57833
  /* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX),
57766
57834
  /* harmony export */ MULTIPLAYER_TRACE_SESSION_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_SESSION_PREFIX),
57767
57835
  /* harmony export */ NavigationRecorder: () => (/* reexport safe */ _navigation__WEBPACK_IMPORTED_MODULE_6__.NavigationRecorder),
57836
+ /* harmony export */ SessionRecorder: () => (/* binding */ SessionRecorderInstance),
57768
57837
  /* harmony export */ SessionRecorderBrowserTraceExporter: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderBrowserTraceExporter),
57769
57838
  /* harmony export */ SessionRecorderIdGenerator: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderIdGenerator),
57770
57839
  /* harmony export */ SessionRecorderSdk: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderSdk),
@@ -57812,6 +57881,7 @@ else {
57812
57881
  SessionRecorderInstance = new _session_recorder__WEBPACK_IMPORTED_MODULE_3__.SessionRecorder();
57813
57882
  }
57814
57883
 
57884
+
57815
57885
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SessionRecorderInstance);
57816
57886
 
57817
57887
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyB,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAIlH,eAAO,MAAM,sBAAsB,EAAE,aASpC,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,yBAuBxC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,sBAAsB,CAuCxD,CAAA"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyB,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAIlH,eAAO,MAAM,sBAAsB,EAAE,aASpC,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,yBAuBxC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,sBAAsB,CA0CxD,CAAA"}
@@ -46,8 +46,11 @@ export const BASE_CONFIG = {
46
46
  apiBaseUrl: MULTIPLAYER_BASE_API_URL,
47
47
  exporterEndpoint: MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
48
48
  recordCanvas: false,
49
- inlineImages: true,
50
- inlineStylesheet: true,
49
+ // Off by default: inlining reads pixels via canvas and requires CORS on cross-origin hosts (e.g. S3).
50
+ // Set true when asset URLs send Access-Control-Allow-Origin for your app origin.
51
+ inlineImages: false,
52
+ // Off by default: inlining fetches stylesheet text; cross-origin <link> assets need CORS when enabled.
53
+ inlineStylesheet: false,
51
54
  recordNavigation: true,
52
55
  schemifyDocSpanPayload: true,
53
56
  ignoreUrls: [],
@@ -60,7 +63,7 @@ export const BASE_CONFIG = {
60
63
  widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
61
64
  useWebsocket: true,
62
65
  buffering: {
63
- enabled: false,
66
+ enabled: true,
64
67
  windowMinutes: 0.5,
65
68
  snapshotIntervalMs: 20000,
66
69
  },
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,iDAAiD,GAClD,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAyC,qBAAqB,EAA6B,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,0BAA0B,EAAE,uCAAuC,EAAE,MAAM,aAAa,CAAA;AACjG,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,CAAA;AAEtE,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,IAAI;IAC7B,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC;IAC/B,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,eAAe;IACnC,eAAe,EAAE,gBAAgB;IACjC,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,EAAE;CACrB,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAA8B;IACnE,0BAA0B,EAAE,uBAAuB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,gCAAgC,EAAE,kEAAkE;IACpG,mCAAmC,EAAE,kEAAkE;IACvG,wBAAwB,EAAE,sBAAsB;IAChD,wBAAwB,EAAE,iBAAiB;IAC3C,UAAU,EAAE,iBAAiB;IAC7B,gBAAgB,EAAE,0FAA0F;IAC5G,kBAAkB,EAAE,kBAAkB;IACtC,cAAc,EAAE,kBAAkB;IAClC,gBAAgB,EAAE,kBAAkB;IACpC,sBAAsB,EAAE,mCAAmC;IAC3D,4BAA4B,EAC1B,mOAAmO;IACrO,0BAA0B,EAAE,gBAAgB;IAC5C,iBAAiB,EAAE,gBAAgB;IACnC,oBAAoB,EAClB,iJAAiJ;IACnJ,wBAAwB,EAAE,+CAA+C;IACzE,8BAA8B,EAAE,kBAAkB;IAClD,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,QAAQ;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,MAAM,EAAE,EAAE;IAEV,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;IAEf,UAAU,EAAE,IAAI;IAChB,uBAAuB,EAAE,IAAI;IAC7B,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;IAExD,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,wBAAwB;IACpC,gBAAgB,EAAE,iDAAiD;IAEnE,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,IAAI;IAClB,gBAAgB,EAAE,IAAI;IACtB,gBAAgB,EAAE,IAAI;IACtB,sBAAsB,EAAE,IAAI;IAE5B,UAAU,EAAE,EAAE;IACd,4BAA4B,EAAE,EAAE;IAEhC,gBAAgB,EAAE,0BAA0B;IAC5C,2BAA2B,EAAE,uCAAuC;IAEpE,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,OAAO,EAAE,sBAAsB;IAC/B,mBAAmB,EAAE,0BAA0B;IAE/C,YAAY,EAAE,IAAI;IAElB,SAAS,EAAE;QACT,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,GAAG;QAClB,kBAAkB,EAAE,KAAK;KAC1B;CACF,CAAA"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,iDAAiD,GAClD,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAyC,qBAAqB,EAA6B,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,0BAA0B,EAAE,uCAAuC,EAAE,MAAM,aAAa,CAAA;AACjG,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,CAAA;AAEtE,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,IAAI;IAC7B,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC;IAC/B,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,eAAe;IACnC,eAAe,EAAE,gBAAgB;IACjC,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,EAAE;CACrB,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAA8B;IACnE,0BAA0B,EAAE,uBAAuB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,gCAAgC,EAAE,kEAAkE;IACpG,mCAAmC,EAAE,kEAAkE;IACvG,wBAAwB,EAAE,sBAAsB;IAChD,wBAAwB,EAAE,iBAAiB;IAC3C,UAAU,EAAE,iBAAiB;IAC7B,gBAAgB,EAAE,0FAA0F;IAC5G,kBAAkB,EAAE,kBAAkB;IACtC,cAAc,EAAE,kBAAkB;IAClC,gBAAgB,EAAE,kBAAkB;IACpC,sBAAsB,EAAE,mCAAmC;IAC3D,4BAA4B,EAC1B,mOAAmO;IACrO,0BAA0B,EAAE,gBAAgB;IAC5C,iBAAiB,EAAE,gBAAgB;IACnC,oBAAoB,EAClB,iJAAiJ;IACnJ,wBAAwB,EAAE,+CAA+C;IACzE,8BAA8B,EAAE,kBAAkB;IAClD,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,QAAQ;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,MAAM,EAAE,EAAE;IAEV,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;IAEf,UAAU,EAAE,IAAI;IAChB,uBAAuB,EAAE,IAAI;IAC7B,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;IAExD,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,wBAAwB;IACpC,gBAAgB,EAAE,iDAAiD;IAEnE,YAAY,EAAE,KAAK;IACnB,sGAAsG;IACtG,iFAAiF;IACjF,YAAY,EAAE,KAAK;IACnB,uGAAuG;IACvG,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,IAAI;IACtB,sBAAsB,EAAE,IAAI;IAE5B,UAAU,EAAE,EAAE;IACd,4BAA4B,EAAE,EAAE;IAEhC,gBAAgB,EAAE,0BAA0B;IAC5C,2BAA2B,EAAE,uCAAuC;IAEpE,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,OAAO,EAAE,sBAAsB;IAC/B,mBAAmB,EAAE,0BAA0B;IAE/C,YAAY,EAAE,IAAI;IAElB,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,GAAG;QAClB,kBAAkB,EAAE,KAAK;KAC1B;CACF,CAAA"}