@multiplayer-app/session-recorder-browser 1.3.16 → 1.3.17-session-buffering.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/browser/index.js +1224 -174
  2. package/dist/config/constants.d.ts +1 -0
  3. package/dist/config/constants.d.ts.map +1 -1
  4. package/dist/config/constants.js +2 -0
  5. package/dist/config/constants.js.map +1 -1
  6. package/dist/config/defaults.d.ts.map +1 -1
  7. package/dist/config/defaults.js +5 -0
  8. package/dist/config/defaults.js.map +1 -1
  9. package/dist/config/session-recorder.d.ts.map +1 -1
  10. package/dist/config/session-recorder.js +6 -1
  11. package/dist/config/session-recorder.js.map +1 -1
  12. package/dist/exporters/index.js +1 -1
  13. package/dist/exporters/index.js.LICENSE.txt +2 -0
  14. package/dist/exporters/index.js.map +1 -1
  15. package/dist/index.js +1216 -175
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.umd.js +1214 -174
  18. package/dist/index.umd.js.map +1 -1
  19. package/dist/otel/index.d.ts +7 -1
  20. package/dist/otel/index.d.ts.map +1 -1
  21. package/dist/otel/index.js +63 -3
  22. package/dist/otel/index.js.map +1 -1
  23. package/dist/patch/fetch.js +2 -2
  24. package/dist/patch/fetch.js.map +1 -1
  25. package/dist/rrweb/index.d.ts +50 -17
  26. package/dist/rrweb/index.d.ts.map +1 -1
  27. package/dist/rrweb/index.js +158 -84
  28. package/dist/rrweb/index.js.map +1 -1
  29. package/dist/services/crashBuffer.service.d.ts +60 -0
  30. package/dist/services/crashBuffer.service.d.ts.map +1 -0
  31. package/dist/services/crashBuffer.service.js +161 -0
  32. package/dist/services/crashBuffer.service.js.map +1 -0
  33. package/dist/services/indexedDb.service.d.ts +72 -0
  34. package/dist/services/indexedDb.service.d.ts.map +1 -0
  35. package/dist/services/indexedDb.service.js +335 -0
  36. package/dist/services/indexedDb.service.js.map +1 -0
  37. package/dist/services/socket.service.d.ts +3 -2
  38. package/dist/services/socket.service.d.ts.map +1 -1
  39. package/dist/services/socket.service.js +8 -1
  40. package/dist/services/socket.service.js.map +1 -1
  41. package/dist/session-recorder.d.ts +12 -1
  42. package/dist/session-recorder.d.ts.map +1 -1
  43. package/dist/session-recorder.js +155 -7
  44. package/dist/session-recorder.js.map +1 -1
  45. package/dist/types/session-recorder.d.ts +20 -0
  46. package/dist/types/session-recorder.d.ts.map +1 -1
  47. package/dist/types/session-recorder.js.map +1 -1
  48. package/dist/utils/index.d.ts +1 -0
  49. package/dist/utils/index.d.ts.map +1 -1
  50. package/dist/utils/index.js +1 -0
  51. package/dist/utils/index.js.map +1 -1
  52. package/dist/utils/storage.d.ts +4 -1
  53. package/dist/utils/storage.d.ts.map +1 -1
  54. package/dist/utils/storage.js +35 -13
  55. package/dist/utils/storage.js.map +1 -1
  56. package/dist/utils/tabId.d.ts +2 -0
  57. package/dist/utils/tabId.d.ts.map +1 -0
  58. package/dist/utils/tabId.js +22 -0
  59. package/dist/utils/tabId.js.map +1 -0
  60. package/package.json +2 -2
  61. package/dist/rrweb/indexedDbService.d.ts +0 -9
  62. package/dist/rrweb/indexedDbService.d.ts.map +0 -1
  63. package/dist/rrweb/indexedDbService.js +0 -54
  64. package/dist/rrweb/indexedDbService.js.map +0 -1
package/dist/index.umd.js CHANGED
@@ -24295,6 +24295,7 @@ module.exports = {
24295
24295
  /* harmony export */ SESSION_ID_PROP_NAME: () => (/* binding */ SESSION_ID_PROP_NAME),
24296
24296
  /* harmony export */ SESSION_PROP_NAME: () => (/* binding */ SESSION_PROP_NAME),
24297
24297
  /* harmony export */ SESSION_RESPONSE: () => (/* binding */ SESSION_RESPONSE),
24298
+ /* harmony export */ SESSION_SAVE_BUFFER_EVENT: () => (/* binding */ SESSION_SAVE_BUFFER_EVENT),
24298
24299
  /* harmony export */ SESSION_STARTED_EVENT: () => (/* binding */ SESSION_STARTED_EVENT),
24299
24300
  /* harmony export */ SESSION_STATE_PROP_NAME: () => (/* binding */ SESSION_STATE_PROP_NAME),
24300
24301
  /* harmony export */ SESSION_STOPPED_EVENT: () => (/* binding */ SESSION_STOPPED_EVENT),
@@ -24316,6 +24317,8 @@ const SESSION_SUBSCRIBE_EVENT = 'debug-session:subscribe';
24316
24317
  const SESSION_UNSUBSCRIBE_EVENT = 'debug-session:unsubscribe';
24317
24318
  const SESSION_AUTO_CREATED = 'debug-session:auto-created';
24318
24319
  const SESSION_ADD_EVENT = 'debug-session:rrweb:add-event';
24320
+ // Backend-triggered flush of client-side crash buffer
24321
+ const SESSION_SAVE_BUFFER_EVENT = 'debug-session:save-buffer';
24319
24322
  const SOCKET_SET_USER_EVENT = 'socket:set-user';
24320
24323
  const DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE = 100000;
24321
24324
  const SESSION_RESPONSE = 'multiplayer-debug-session-response';
@@ -24323,7 +24326,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
24323
24326
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
24324
24327
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
24325
24328
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
24326
- const PACKAGE_VERSION_EXPORT = "1.3.16" || 0;
24329
+ const PACKAGE_VERSION_EXPORT = "1.3.17-session-buffering.0" || 0;
24327
24330
  // Regex patterns for OpenTelemetry ignore URLs
24328
24331
  const OTEL_IGNORE_URLS = [
24329
24332
  // Traces endpoint
@@ -24419,6 +24422,11 @@ const BASE_CONFIG = {
24419
24422
  masking: DEFAULT_MASKING_CONFIG,
24420
24423
  widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
24421
24424
  useWebsocket: true,
24425
+ buffering: {
24426
+ enabled: true,
24427
+ windowMinutes: 1,
24428
+ snapshotIntervalMs: 30000,
24429
+ },
24422
24430
  };
24423
24431
 
24424
24432
 
@@ -24444,6 +24452,7 @@ const BASE_CONFIG = {
24444
24452
  /* harmony export */ SESSION_ID_PROP_NAME: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_ID_PROP_NAME),
24445
24453
  /* harmony export */ SESSION_PROP_NAME: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_PROP_NAME),
24446
24454
  /* harmony export */ SESSION_RESPONSE: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_RESPONSE),
24455
+ /* harmony export */ SESSION_SAVE_BUFFER_EVENT: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_SAVE_BUFFER_EVENT),
24447
24456
  /* harmony export */ SESSION_STARTED_EVENT: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_STARTED_EVENT),
24448
24457
  /* harmony export */ SESSION_STATE_PROP_NAME: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_STATE_PROP_NAME),
24449
24458
  /* harmony export */ SESSION_STOPPED_EVENT: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_0__.SESSION_STOPPED_EVENT),
@@ -24560,7 +24569,7 @@ const getWidgetTextOverridesConfig = (config, defaultConfig) => {
24560
24569
  };
24561
24570
  };
24562
24571
  const getSessionRecorderConfig = (c) => {
24563
- var _a;
24572
+ var _a, _b, _c, _d, _e, _f, _g;
24564
24573
  if (!c) {
24565
24574
  return _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG;
24566
24575
  }
@@ -24587,6 +24596,11 @@ const getSessionRecorderConfig = (c) => {
24587
24596
  masking: (0,_masking__WEBPACK_IMPORTED_MODULE_2__.getMaskingConfig)(c.masking),
24588
24597
  widgetTextOverrides: getWidgetTextOverridesConfig(c.widgetTextOverrides, _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG.widgetTextOverrides),
24589
24598
  useWebsocket: (0,_validators__WEBPACK_IMPORTED_MODULE_3__.isValidBoolean)(c.useWebsocket, (_a = _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG.useWebsocket) !== null && _a !== void 0 ? _a : false),
24599
+ buffering: {
24600
+ enabled: (_c = (_b = c.buffering) === null || _b === void 0 ? void 0 : _b.enabled) !== null && _c !== void 0 ? _c : _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG.buffering.enabled,
24601
+ windowMinutes: (_e = (_d = c.buffering) === null || _d === void 0 ? void 0 : _d.windowMinutes) !== null && _e !== void 0 ? _e : _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG.buffering.windowMinutes,
24602
+ snapshotIntervalMs: (_g = (_f = c.buffering) === null || _f === void 0 ? void 0 : _f.snapshotIntervalMs) !== null && _g !== void 0 ? _g : _defaults__WEBPACK_IMPORTED_MODULE_1__.BASE_CONFIG.buffering.snapshotIntervalMs,
24603
+ },
24590
24604
  };
24591
24605
  };
24592
24606
 
@@ -25236,14 +25250,19 @@ const getElementTextContent = (element) => {
25236
25250
  class TracerBrowserSDK {
25237
25251
  constructor() {
25238
25252
  this.sessionId = '';
25253
+ this.clientId = '';
25239
25254
  this.globalErrorListenersRegistered = false;
25240
25255
  }
25241
- setSessionId(sessionId, sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.PLAIN) {
25256
+ setSessionId(sessionId, sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL) {
25242
25257
  this.sessionId = sessionId;
25243
- this.idGenerator.setSessionId(sessionId, sessionType);
25258
+ if (!this.idGenerator) {
25259
+ throw new Error('Id generator not initialized');
25260
+ }
25261
+ this.idGenerator.setSessionId(sessionId, sessionType, this.clientId);
25244
25262
  }
25245
25263
  init(options) {
25246
25264
  this.config = options;
25265
+ this.clientId = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderSdk.getIdGenerator(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH)();
25247
25266
  const { application, version, environment } = this.config;
25248
25267
  this.idGenerator = new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderIdGenerator();
25249
25268
  this.exporter = new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderBrowserTraceExporter({
@@ -25261,6 +25280,7 @@ class TracerBrowserSDK {
25261
25280
  sampler: new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderTraceIdRatioBasedSampler(this.config.sampleTraceRatio),
25262
25281
  spanProcessors: [
25263
25282
  this._getSpanSessionIdProcessor(),
25283
+ this._getCrashBufferSpanProcessor(),
25264
25284
  new _opentelemetry_sdk_trace_base__WEBPACK_IMPORTED_MODULE_7__.BatchSpanProcessor(this.exporter),
25265
25285
  ],
25266
25286
  });
@@ -25377,6 +25397,60 @@ class TracerBrowserSDK {
25377
25397
  });
25378
25398
  this._registerGlobalErrorListeners();
25379
25399
  }
25400
+ setCrashBuffer(crashBuffer) {
25401
+ this.crashBuffer = crashBuffer;
25402
+ }
25403
+ _getCrashBufferSpanProcessor() {
25404
+ return {
25405
+ onStart: () => { },
25406
+ onEnd: (span) => {
25407
+ // Only buffer spans when we don't have an active debug session.
25408
+ if (this.sessionId)
25409
+ return;
25410
+ if (!this.crashBuffer)
25411
+ return;
25412
+ try {
25413
+ const now = Date.now();
25414
+ this.crashBuffer.appendOtelSpan({
25415
+ ts: now,
25416
+ span: this._serializeSpan(span),
25417
+ });
25418
+ }
25419
+ catch (_e) {
25420
+ // ignore
25421
+ }
25422
+ },
25423
+ shutdown: () => Promise.resolve(),
25424
+ forceFlush: () => Promise.resolve(),
25425
+ };
25426
+ }
25427
+ _serializeSpan(span) {
25428
+ var _a, _b;
25429
+ const spanContext = ((_a = span === null || span === void 0 ? void 0 : span.spanContext) === null || _a === void 0 ? void 0 : _a.call(span))
25430
+ ? span.spanContext()
25431
+ : span === null || span === void 0 ? void 0 : span._spanContext;
25432
+ return {
25433
+ _spanContext: spanContext,
25434
+ name: span === null || span === void 0 ? void 0 : span.name,
25435
+ kind: span === null || span === void 0 ? void 0 : span.kind,
25436
+ links: span === null || span === void 0 ? void 0 : span.links,
25437
+ ended: span === null || span === void 0 ? void 0 : span.ended,
25438
+ events: span === null || span === void 0 ? void 0 : span.events,
25439
+ status: span === null || span === void 0 ? void 0 : span.status,
25440
+ endTime: span === null || span === void 0 ? void 0 : span.endTime,
25441
+ startTime: span === null || span === void 0 ? void 0 : span.startTime,
25442
+ duration: span === null || span === void 0 ? void 0 : span.duration,
25443
+ attributes: span === null || span === void 0 ? void 0 : span.attributes,
25444
+ parentSpanId: (_b = span === null || span === void 0 ? void 0 : span.parentSpanContext) === null || _b === void 0 ? void 0 : _b.spanId,
25445
+ droppedAttributesCount: span === null || span === void 0 ? void 0 : span.droppedAttributesCount,
25446
+ droppedEventsCount: span === null || span === void 0 ? void 0 : span.droppedEventsCount,
25447
+ droppedLinksCount: span === null || span === void 0 ? void 0 : span.droppedLinksCount,
25448
+ resource: (span === null || span === void 0 ? void 0 : span.resource) ? {
25449
+ attributes: span.resource.attributes,
25450
+ asyncAttributesPending: span.resource.asyncAttributesPending,
25451
+ } : undefined,
25452
+ };
25453
+ }
25380
25454
  start(sessionId, sessionType) {
25381
25455
  if (!this.tracerProvider) {
25382
25456
  throw new Error('Configuration not initialized. Call init() before start().');
@@ -25522,7 +25596,7 @@ const setShouldRecordHttpData = (shouldRecordBody, shouldRecordHeaders) => {
25522
25596
 
25523
25597
 
25524
25598
 
25525
- function _tryReadFetchBody({ body, url }) {
25599
+ function _tryReadFetchBody({ body, url, }) {
25526
25600
  if ((0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(body)) {
25527
25601
  return null;
25528
25602
  }
@@ -25695,7 +25769,7 @@ if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
25695
25769
  if (!(0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(candidateBody)) {
25696
25770
  const requestBody = _tryReadFetchBody({
25697
25771
  body: candidateBody,
25698
- url: urlStr
25772
+ url: urlStr,
25699
25773
  });
25700
25774
  if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) && new Blob([requestBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
25701
25775
  networkRequest.requestBody = requestBody;
@@ -25893,11 +25967,13 @@ if (typeof XMLHttpRequest !== 'undefined') {
25893
25967
  /* harmony export */ RecorderBrowserSDK: () => (/* binding */ RecorderBrowserSDK)
25894
25968
  /* harmony export */ });
25895
25969
  /* harmony import */ var _rrweb_packer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @rrweb/packer */ "../../node_modules/@rrweb/packer/dist/packer.js");
25896
- /* harmony import */ var rrweb__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rrweb */ "../../node_modules/rrweb/dist/rrweb.js");
25897
- /* harmony import */ var _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @multiplayer-app/session-recorder-common */ "../session-recorder-common/dist/esm/index-browser.js");
25898
- /* harmony import */ var _rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @rrweb/rrweb-plugin-console-record */ "../../node_modules/@rrweb/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.js");
25899
- /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ "./src/utils/index.ts");
25900
- /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../config */ "./src/config/index.ts");
25970
+ /* harmony import */ var _rrweb_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @rrweb/types */ "../../node_modules/@rrweb/types/dist/types.js");
25971
+ /* harmony import */ var rrweb__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rrweb */ "../../node_modules/rrweb/dist/rrweb.js");
25972
+ /* harmony import */ var _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @multiplayer-app/session-recorder-common */ "../session-recorder-common/dist/esm/index-browser.js");
25973
+ /* harmony import */ var _rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @rrweb/rrweb-plugin-console-record */ "../../node_modules/@rrweb/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.js");
25974
+ /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils */ "./src/utils/index.ts");
25975
+ /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../config */ "./src/config/index.ts");
25976
+
25901
25977
 
25902
25978
 
25903
25979
 
@@ -25905,129 +25981,202 @@ if (typeof XMLHttpRequest !== 'undefined') {
25905
25981
 
25906
25982
 
25907
25983
  class RecorderBrowserSDK {
25908
- get startedAt() {
25909
- return this._startedAt;
25910
- }
25911
- set startedAt(v) {
25912
- this._startedAt = v;
25913
- }
25914
- get stoppedAt() {
25915
- return this._stoppedAt;
25916
- }
25917
- set stoppedAt(v) {
25918
- this._stoppedAt = v;
25919
- }
25920
25984
  constructor() {
25921
- this.restartInterval = null;
25922
- this._startedAt = '';
25923
- this._stoppedAt = '';
25985
+ this.intervals = {
25986
+ restart: null,
25987
+ bufferSnapshot: null,
25988
+ };
25989
+ this.startedAt = '';
25990
+ this.stoppedAt = '';
25991
+ }
25992
+ /**
25993
+ * Full snapshot.
25994
+ */
25995
+ takeFullSnapshot() {
25996
+ rrweb__WEBPACK_IMPORTED_MODULE_6__.record.takeFullSnapshot();
25924
25997
  }
25925
25998
  /**
25926
- * Initializes the recorder SDK with configuration settings.
25927
- * @param config - Configuration settings for the session debugger.
25928
- * @param socketService - Optional socket service instance for sending events.
25999
+ * Initializes the recorder SDK.
26000
+ * @param config - Configuration settings.
26001
+ * @param socketService - Optional socket service.
25929
26002
  */
25930
26003
  init(config, socketService) {
25931
26004
  this.config = config;
25932
26005
  this.socketService = socketService;
25933
26006
  }
25934
26007
  /**
25935
- * Starts recording events for a given session ID.
25936
- * @param sessionId - The ID of the session to record events for.
26008
+ * Starts recording.
26009
+ * @param sessionId - Session ID or null for buffer-only mode.
26010
+ * @param sessionType - Session type.
25937
26011
  */
25938
26012
  start(sessionId, sessionType) {
25939
- var _a;
25940
26013
  if (!this.config) {
25941
26014
  throw new Error('Configuration not initialized. Call init() before start().');
25942
26015
  }
25943
- const restartInterval = sessionType === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.CONTINUOUS ? _config__WEBPACK_IMPORTED_MODULE_4__.CONTINUOUS_DEBUGGING_TIMEOUT : 0;
25944
26016
  this.startedAt = new Date().toISOString();
25945
- // Build masking configuration
25946
- const maskingConfig = this.config.masking || {};
26017
+ this.stopFn = (0,rrweb__WEBPACK_IMPORTED_MODULE_6__.record)({
26018
+ ...this._buildRecordOptions(),
26019
+ emit: async (event) => {
26020
+ const ts = event.timestamp;
26021
+ if (!sessionId) {
26022
+ await this._handleBufferOnlyEvent(event, ts);
26023
+ return;
26024
+ }
26025
+ this._handleLiveSessionEvent(event, ts, sessionId, sessionType);
26026
+ },
26027
+ });
26028
+ this.takeFullSnapshot();
26029
+ this._setupPeriodicSnapshots(sessionId, sessionType);
26030
+ }
26031
+ /**
26032
+ * Restarts recording. Never throws - library mode constraint.
26033
+ */
26034
+ async restart(sessionId, sessionType) {
26035
+ var _a;
26036
+ try {
26037
+ (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26038
+ this.start(sessionId, sessionType);
26039
+ }
26040
+ catch (_e) {
26041
+ // Silent failure
26042
+ }
26043
+ }
26044
+ /**
26045
+ * Stops recording and cleans up resources.
26046
+ */
26047
+ stop() {
26048
+ var _a, _b, _c;
26049
+ (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26050
+ if (!((_b = this.config) === null || _b === void 0 ? void 0 : _b.useWebsocket)) {
26051
+ (_c = this.socketService) === null || _c === void 0 ? void 0 : _c.close();
26052
+ }
26053
+ this._clearAllIntervals();
26054
+ }
26055
+ _clearAllIntervals() {
26056
+ if (this.intervals.restart) {
26057
+ clearInterval(this.intervals.restart);
26058
+ this.intervals.restart = null;
26059
+ }
26060
+ if (this.intervals.bufferSnapshot) {
26061
+ clearInterval(this.intervals.bufferSnapshot);
26062
+ this.intervals.bufferSnapshot = null;
26063
+ }
26064
+ }
26065
+ /**
26066
+ * Sets the crash buffer.
26067
+ * @param crashBuffer - Crash buffer service.
26068
+ */
26069
+ setCrashBuffer(crashBuffer) {
26070
+ this.crashBuffer = crashBuffer;
26071
+ }
26072
+ /**
26073
+ * Mutates event in-place for performance.
26074
+ */
26075
+ _applyConsoleMasking(event) {
26076
+ var _a, _b;
26077
+ const maskFn = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.masking) === null || _b === void 0 ? void 0 : _b.maskConsoleEvent;
26078
+ if (typeof maskFn === 'function' && (0,_utils__WEBPACK_IMPORTED_MODULE_4__.isConsoleEvent)(event)) {
26079
+ const pluginEvt = event;
26080
+ const maskedPayload = maskFn(pluginEvt.data.payload);
26081
+ pluginEvt.data = { ...pluginEvt.data, payload: maskedPayload };
26082
+ }
26083
+ }
26084
+ /**
26085
+ * Handles buffer-only event.
26086
+ * @param event - Event.
26087
+ * @param ts - Timestamp.
26088
+ */
26089
+ async _handleBufferOnlyEvent(event, ts) {
26090
+ if (!this.crashBuffer)
26091
+ return;
26092
+ try {
26093
+ this._applyConsoleMasking(event);
26094
+ const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
26095
+ this.stoppedAt = new Date(ts).toISOString();
26096
+ await this.crashBuffer.appendRrwebEvent({
26097
+ ts,
26098
+ isFullSnapshot: event.type === _rrweb_types__WEBPACK_IMPORTED_MODULE_1__.EventType.FullSnapshot,
26099
+ event: {
26100
+ event: packedEvent,
26101
+ eventType: event.type,
26102
+ timestamp: ts,
26103
+ },
26104
+ });
26105
+ }
26106
+ catch (error) {
26107
+ // Silent failure - library constraint
26108
+ }
26109
+ }
26110
+ /**
26111
+ * Handles live session event.
26112
+ * @param event - Event.
26113
+ * @param ts - Timestamp.
26114
+ * @param sessionId - Session ID.
26115
+ * @param sessionType - Session type.
26116
+ */
26117
+ _handleLiveSessionEvent(event, ts, sessionId, sessionType) {
26118
+ if (!this.socketService)
26119
+ return;
26120
+ this._applyConsoleMasking(event);
26121
+ const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
26122
+ this.stoppedAt = new Date(ts).toISOString();
26123
+ this.socketService.send({
26124
+ event: packedEvent,
26125
+ eventType: event.type,
26126
+ timestamp: ts,
26127
+ debugSessionId: sessionId,
26128
+ debugSessionType: sessionType,
26129
+ });
26130
+ }
26131
+ /**
26132
+ * Builds record options.
26133
+ */
26134
+ _buildRecordOptions() {
26135
+ var _a, _b, _c;
26136
+ const maskingConfig = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.masking) || {};
25947
26137
  const options = {
25948
- maskAllInputs: (_a = maskingConfig.maskAllInputs) !== null && _a !== void 0 ? _a : true,
26138
+ maskAllInputs: (_b = maskingConfig.maskAllInputs) !== null && _b !== void 0 ? _b : true,
25949
26139
  sampling: { canvas: 5 },
25950
- recordCanvas: this.config.recordCanvas,
26140
+ recordCanvas: (_c = this.config) === null || _c === void 0 ? void 0 : _c.recordCanvas,
25951
26141
  dataURLOptions: { type: 'image/webp', quality: 0.1 },
25952
- plugins: [
25953
- (0,_rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_2__.getRecordConsolePlugin)({ level: ['log', 'error'] }),
25954
- ],
26142
+ plugins: [(0,_rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_3__.getRecordConsolePlugin)({ level: ['log', 'error'] })],
25955
26143
  };
25956
- // Add mask input options if provided
25957
26144
  if (maskingConfig.maskInputOptions) {
25958
26145
  options.maskInputOptions = maskingConfig.maskInputOptions;
25959
26146
  }
25960
- // Add mask text class if provided
25961
26147
  if (maskingConfig.maskTextClass) {
25962
26148
  options.maskTextClass = maskingConfig.maskTextClass;
25963
26149
  }
25964
- // Add mask text selector if provided
25965
26150
  if (maskingConfig.maskTextSelector) {
25966
26151
  options.maskTextSelector = maskingConfig.maskTextSelector;
25967
26152
  }
25968
- // Add custom masking functions if provided
25969
26153
  if (typeof maskingConfig.maskInput === 'function') {
25970
26154
  options.maskInputFn = maskingConfig.maskInput;
25971
26155
  }
25972
26156
  if (typeof maskingConfig.maskText === 'function') {
25973
26157
  options.maskTextFn = maskingConfig.maskText;
25974
26158
  }
25975
- this.stopFn = (0,rrweb__WEBPACK_IMPORTED_MODULE_5__.record)({
25976
- ...options,
25977
- emit: async (event) => {
25978
- if (this.socketService) {
25979
- if (typeof maskingConfig.maskConsoleEvent === 'function' && (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isConsoleEvent)(event)) {
25980
- const { data } = event;
25981
- const maskedPayload = maskingConfig.maskConsoleEvent(data.payload);
25982
- event.data = { ...data, payload: maskedPayload };
25983
- }
25984
- const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
25985
- this.stoppedAt = new Date(event.timestamp).toISOString();
25986
- this.socketService.send({
25987
- event: packedEvent,
25988
- eventType: event.type,
25989
- timestamp: event.timestamp,
25990
- debugSessionId: sessionId,
25991
- debugSessionType: sessionType,
25992
- });
25993
- }
25994
- },
25995
- });
25996
- // It will sent full snapshot again but it will fix missing first snapshot issue
25997
- rrweb__WEBPACK_IMPORTED_MODULE_5__.record.takeFullSnapshot();
25998
- if (restartInterval > 0) {
25999
- this.restartInterval = setInterval(() => {
26000
- rrweb__WEBPACK_IMPORTED_MODULE_5__.record.takeFullSnapshot();
26001
- }, restartInterval);
26002
- }
26159
+ return options;
26003
26160
  }
26004
26161
  /**
26005
- * Restarts the recording of events.
26162
+ * Sets up periodic snapshots.
26163
+ * @param sessionId - Session ID.
26164
+ * @param sessionType - Session type.
26006
26165
  */
26007
- async restart(sessionId, sessionType) {
26008
- var _a;
26009
- (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26010
- this.start(sessionId, sessionType);
26011
- }
26012
- /**
26013
- * Clears the restart timeout.
26014
- */
26015
- clearRestartInterval() {
26016
- if (this.restartInterval) {
26017
- clearInterval(this.restartInterval);
26018
- this.restartInterval = null;
26166
+ _setupPeriodicSnapshots(sessionId, sessionType) {
26167
+ var _a, _b;
26168
+ this._clearAllIntervals();
26169
+ if (sessionType === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__.SessionType.CONTINUOUS) {
26170
+ this.intervals.restart = setInterval(() => {
26171
+ this.takeFullSnapshot();
26172
+ }, _config__WEBPACK_IMPORTED_MODULE_5__.CONTINUOUS_DEBUGGING_TIMEOUT);
26019
26173
  }
26020
- }
26021
- /**
26022
- * Stops the recording of events.
26023
- */
26024
- stop() {
26025
- var _a, _b, _c;
26026
- (_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
26027
- if (!((_b = this.config) === null || _b === void 0 ? void 0 : _b.useWebsocket)) {
26028
- (_c = this.socketService) === null || _c === void 0 ? void 0 : _c.close();
26174
+ if (!sessionId && ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled)) {
26175
+ const interval = this.config.buffering.snapshotIntervalMs || 30000;
26176
+ this.intervals.bufferSnapshot = setInterval(() => {
26177
+ this.takeFullSnapshot();
26178
+ }, interval);
26029
26179
  }
26030
- this.clearRestartInterval();
26031
26180
  }
26032
26181
  }
26033
26182
 
@@ -26179,6 +26328,528 @@ class ApiService {
26179
26328
  }
26180
26329
 
26181
26330
 
26331
+ /***/ }),
26332
+
26333
+ /***/ "./src/services/crashBuffer.service.ts":
26334
+ /*!*********************************************!*\
26335
+ !*** ./src/services/crashBuffer.service.ts ***!
26336
+ \*********************************************/
26337
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26338
+
26339
+ "use strict";
26340
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26341
+ /* harmony export */ CrashBufferService: () => (/* binding */ CrashBufferService)
26342
+ /* harmony export */ });
26343
+ class CrashBufferService {
26344
+ constructor(db, tabId, windowMs) {
26345
+ this.db = db;
26346
+ this.tabId = tabId;
26347
+ this.windowMs = windowMs;
26348
+ this.lastPruneAt = 0;
26349
+ this.pruneInFlight = null;
26350
+ this.isActive = true;
26351
+ this.frozenAtTs = null;
26352
+ this.lastSeenEventTs = 0;
26353
+ this.requiresFullSnapshot = true;
26354
+ this.lastTouchAt = 0;
26355
+ }
26356
+ async _safe(fn, fallback) {
26357
+ try {
26358
+ return await fn();
26359
+ }
26360
+ catch (_e) {
26361
+ return fallback;
26362
+ }
26363
+ }
26364
+ async setAttrs(attrs) {
26365
+ await this._safe(async () => {
26366
+ await this.db.setAttrs({
26367
+ tabId: this.tabId,
26368
+ ...attrs,
26369
+ });
26370
+ }, undefined);
26371
+ }
26372
+ async appendRrwebEvent(payload) {
26373
+ this.lastSeenEventTs = Math.max(this.lastSeenEventTs, payload.ts || 0);
26374
+ if (!this.isActive)
26375
+ return;
26376
+ const isFullSnapshot = Boolean(payload.isFullSnapshot);
26377
+ if (this.requiresFullSnapshot && !isFullSnapshot) {
26378
+ // Buffer must always start with a full snapshot; drop incrementals until we see one.
26379
+ return;
26380
+ }
26381
+ await this._safe(async () => {
26382
+ await this.db.appendRrwebEvent({
26383
+ tabId: this.tabId,
26384
+ ts: payload.ts,
26385
+ isFullSnapshot: payload.isFullSnapshot,
26386
+ event: payload.event,
26387
+ });
26388
+ }, undefined);
26389
+ if (isFullSnapshot && this.requiresFullSnapshot) {
26390
+ // Ensure this snapshot becomes the first replayable event.
26391
+ // We keep the snapshot itself and prune everything older.
26392
+ await this._safe(() => this.db.pruneOlderThan(this.tabId, Math.max(0, payload.ts - 1)), undefined);
26393
+ this.requiresFullSnapshot = false;
26394
+ }
26395
+ else if (isFullSnapshot) {
26396
+ this.requiresFullSnapshot = false;
26397
+ }
26398
+ this.pruneSoon();
26399
+ }
26400
+ async appendOtelSpan(payload) {
26401
+ this.lastSeenEventTs = Math.max(this.lastSeenEventTs, payload.ts || 0);
26402
+ if (!this.isActive)
26403
+ return;
26404
+ await this._safe(async () => {
26405
+ await this.db.appendOtelSpan({
26406
+ tabId: this.tabId,
26407
+ ts: payload.ts,
26408
+ span: payload.span,
26409
+ });
26410
+ }, undefined);
26411
+ this.pruneSoon();
26412
+ }
26413
+ async snapshot(now = Date.now()) {
26414
+ const toTs = now;
26415
+ const fromTs = Math.max(0, toTs - this.windowMs);
26416
+ // Always include a full snapshot "anchor" if one exists at/before the window start.
26417
+ const rrwebFromTs = await this._safe(async () => {
26418
+ const anchor = await this.db.getLastRrwebFullSnapshotBefore(this.tabId, fromTs);
26419
+ return typeof (anchor === null || anchor === void 0 ? void 0 : anchor.ts) === 'number' ? anchor.ts : fromTs;
26420
+ }, fromTs);
26421
+ const [rrweb, spans, attrs] = await Promise.all([
26422
+ this._safe(() => this.db.getRrwebEventsWindow(this.tabId, rrwebFromTs, toTs), []),
26423
+ this._safe(() => this.db.getOtelSpansWindow(this.tabId, fromTs, toTs), []),
26424
+ this._safe(() => this.db.getAttrs(this.tabId), null),
26425
+ ]);
26426
+ const rrwebSorted = rrweb
26427
+ .sort((a, b) => a.ts - b.ts)
26428
+ .map((r) => ({ ts: r.ts, isFullSnapshot: r.isFullSnapshot, event: r.event }));
26429
+ // Hard guarantee: snapshot payload starts with a FullSnapshot (or is empty).
26430
+ const firstFullSnapshotIdx = rrwebSorted.findIndex((e) => Boolean(e.isFullSnapshot));
26431
+ const rrwebEvents = firstFullSnapshotIdx >= 0 ? rrwebSorted.slice(firstFullSnapshotIdx) : [];
26432
+ // Align spans with the rrweb replay start: spans must start from the FullSnapshot timestamp.
26433
+ const replayStartTs = rrwebEvents.length > 0 ? rrwebEvents[0].ts : fromTs;
26434
+ const otelSpans = spans
26435
+ .filter((s) => typeof (s === null || s === void 0 ? void 0 : s.ts) === 'number' && s.ts >= replayStartTs)
26436
+ .sort((a, b) => a.ts - b.ts)
26437
+ .map((r) => ({ ts: r.ts, span: r.span }));
26438
+ return {
26439
+ rrwebEvents,
26440
+ otelSpans,
26441
+ attrs: attrs ? {
26442
+ sessionAttributes: attrs.sessionAttributes,
26443
+ resourceAttributes: attrs.resourceAttributes,
26444
+ userAttributes: attrs.userAttributes,
26445
+ } : null,
26446
+ windowMs: this.windowMs,
26447
+ fromTs: replayStartTs,
26448
+ toTs,
26449
+ };
26450
+ }
26451
+ async clear() {
26452
+ await this._safe(() => this.db.clearTab(this.tabId), undefined);
26453
+ this.requiresFullSnapshot = true;
26454
+ }
26455
+ needsFullSnapshot() {
26456
+ return this.requiresFullSnapshot;
26457
+ }
26458
+ /**
26459
+ * Mark the tab as active/inactive.
26460
+ *
26461
+ * - When inactive, we freeze the buffer and keep the last active `windowMs` indefinitely.
26462
+ * - When re-activated, we resume buffering but require a new FullSnapshot to start a replayable segment.
26463
+ */
26464
+ setActive(active) {
26465
+ if (this.isActive === active)
26466
+ return;
26467
+ this.isActive = active;
26468
+ if (!active) {
26469
+ const freezeAt = this.lastSeenEventTs || Date.now();
26470
+ this.frozenAtTs = freezeAt;
26471
+ // Keep the last active window, but preserve rrweb replayability via snapshot anchor.
26472
+ const cutoff = Math.max(0, freezeAt - this.windowMs);
26473
+ void this._safe(() => this.db.pruneOlderThanWithRrwebSnapshotAnchor(this.tabId, cutoff), undefined);
26474
+ return;
26475
+ }
26476
+ const wasFrozen = this.frozenAtTs !== null;
26477
+ this.frozenAtTs = null;
26478
+ // New active segment must start with a full snapshot (don’t stitch segments together).
26479
+ if (wasFrozen)
26480
+ this.requiresFullSnapshot = true;
26481
+ this.pruneSoon();
26482
+ }
26483
+ pruneSoon() {
26484
+ if (!this.isActive)
26485
+ return;
26486
+ const now = Date.now();
26487
+ // Throttle pruning to avoid hammering IDB on high event rates
26488
+ if (now - this.lastPruneAt < 2000)
26489
+ return;
26490
+ if (this.pruneInFlight)
26491
+ return;
26492
+ this.lastPruneAt = now;
26493
+ const cutoff = Math.max(0, now - this.windowMs);
26494
+ // Heartbeat so the stale-tab sweeper never deletes active tabs.
26495
+ if (now - this.lastTouchAt > 30000) {
26496
+ this.lastTouchAt = now;
26497
+ void this._safe(() => this.db.touchTab(this.tabId, now), undefined);
26498
+ }
26499
+ this.pruneInFlight = this._safe(() => this.db.pruneOlderThanWithRrwebSnapshotAnchor(this.tabId, cutoff), undefined)
26500
+ .finally(() => { this.pruneInFlight = null; });
26501
+ }
26502
+ }
26503
+
26504
+
26505
+ /***/ }),
26506
+
26507
+ /***/ "./src/services/indexedDb.service.ts":
26508
+ /*!*******************************************!*\
26509
+ !*** ./src/services/indexedDb.service.ts ***!
26510
+ \*******************************************/
26511
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26512
+
26513
+ "use strict";
26514
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26515
+ /* harmony export */ IndexedDBService: () => (/* binding */ IndexedDBService)
26516
+ /* harmony export */ });
26517
+ const dbName = 'mpEventsDB';
26518
+ const dbVersion = 2;
26519
+ const legacyStoreName = 'mpEventsStore';
26520
+ const rrwebEventsStore = 'rrwebEvents';
26521
+ const otelSpansStore = 'otelSpans';
26522
+ const attrsStore = 'crashBufferAttrs';
26523
+ class IndexedDBService {
26524
+ constructor() {
26525
+ this.dbPromise = this.openDB();
26526
+ }
26527
+ openDB() {
26528
+ return new Promise((resolve, reject) => {
26529
+ const request = indexedDB.open(dbName, dbVersion);
26530
+ request.onupgradeneeded = () => {
26531
+ const db = request.result;
26532
+ // Keep the legacy store if it exists to avoid breaking older versions.
26533
+ if (!db.objectStoreNames.contains(legacyStoreName)) {
26534
+ db.createObjectStore(legacyStoreName, { keyPath: 'id', autoIncrement: true });
26535
+ }
26536
+ if (!db.objectStoreNames.contains(rrwebEventsStore)) {
26537
+ const store = db.createObjectStore(rrwebEventsStore, { keyPath: 'id', autoIncrement: true });
26538
+ store.createIndex('tabId_ts', ['tabId', 'ts'], { unique: false });
26539
+ }
26540
+ if (!db.objectStoreNames.contains(otelSpansStore)) {
26541
+ const store = db.createObjectStore(otelSpansStore, { keyPath: 'id', autoIncrement: true });
26542
+ store.createIndex('tabId_ts', ['tabId', 'ts'], { unique: false });
26543
+ }
26544
+ if (!db.objectStoreNames.contains(attrsStore)) {
26545
+ db.createObjectStore(attrsStore, { keyPath: 'tabId' });
26546
+ }
26547
+ };
26548
+ request.onsuccess = () => resolve(request.result);
26549
+ request.onerror = () => reject(request.error);
26550
+ });
26551
+ }
26552
+ /**
26553
+ * @deprecated Prefer `appendRrwebEvent(tabId, ...)` and `getRrwebEventsWindow(...)`.
26554
+ * This writes into the legacy store with no pruning semantics.
26555
+ */
26556
+ async saveEvent(event) {
26557
+ const db = await this.dbPromise;
26558
+ return new Promise((resolve, reject) => {
26559
+ const tx = db.transaction(legacyStoreName, 'readwrite');
26560
+ const store = tx.objectStore(legacyStoreName);
26561
+ store.add({ event });
26562
+ tx.oncomplete = () => resolve();
26563
+ tx.onerror = () => reject(tx.error);
26564
+ });
26565
+ }
26566
+ /**
26567
+ * @deprecated Prefer `getRrwebEventsWindow(...)`.
26568
+ */
26569
+ async getAllEvents() {
26570
+ const db = await this.dbPromise;
26571
+ return new Promise((resolve, reject) => {
26572
+ const tx = db.transaction(legacyStoreName, 'readonly');
26573
+ const store = tx.objectStore(legacyStoreName);
26574
+ const request = store.getAll();
26575
+ request.onsuccess = () => {
26576
+ const events = request.result.map((record) => record.event);
26577
+ resolve(events);
26578
+ };
26579
+ request.onerror = () => reject(request.error);
26580
+ });
26581
+ }
26582
+ /**
26583
+ * @deprecated Prefer `clearTab(tabId)`.
26584
+ */
26585
+ async clearEvents() {
26586
+ const db = await this.dbPromise;
26587
+ return new Promise((resolve, reject) => {
26588
+ const tx = db.transaction(legacyStoreName, 'readwrite');
26589
+ const store = tx.objectStore(legacyStoreName);
26590
+ store.clear();
26591
+ tx.oncomplete = () => resolve();
26592
+ tx.onerror = () => reject(tx.error);
26593
+ });
26594
+ }
26595
+ async setAttrs(attrs) {
26596
+ var _a;
26597
+ const db = await this.dbPromise;
26598
+ const payload = {
26599
+ ...attrs,
26600
+ updatedAt: (_a = attrs.updatedAt) !== null && _a !== void 0 ? _a : Date.now(),
26601
+ };
26602
+ return new Promise((resolve, reject) => {
26603
+ const tx = db.transaction(attrsStore, 'readwrite');
26604
+ tx.objectStore(attrsStore).put(payload);
26605
+ tx.oncomplete = () => resolve();
26606
+ tx.onerror = () => reject(tx.error);
26607
+ });
26608
+ }
26609
+ async getAttrs(tabId) {
26610
+ const db = await this.dbPromise;
26611
+ return new Promise((resolve, reject) => {
26612
+ const tx = db.transaction(attrsStore, 'readonly');
26613
+ const request = tx.objectStore(attrsStore).get(tabId);
26614
+ request.onsuccess = () => resolve(request.result || null);
26615
+ request.onerror = () => reject(request.error);
26616
+ });
26617
+ }
26618
+ async getAllAttrs() {
26619
+ const db = await this.dbPromise;
26620
+ return new Promise((resolve, reject) => {
26621
+ const tx = db.transaction(attrsStore, 'readonly');
26622
+ const request = tx.objectStore(attrsStore).getAll();
26623
+ request.onsuccess = () => resolve(request.result || []);
26624
+ request.onerror = () => reject(request.error);
26625
+ });
26626
+ }
26627
+ /**
26628
+ * Updates `updatedAt` for the tab without clobbering existing attributes.
26629
+ */
26630
+ async touchTab(tabId, updatedAt = Date.now()) {
26631
+ const db = await this.dbPromise;
26632
+ return new Promise((resolve, reject) => {
26633
+ const tx = db.transaction(attrsStore, 'readwrite');
26634
+ const store = tx.objectStore(attrsStore);
26635
+ const getReq = store.get(tabId);
26636
+ getReq.onsuccess = () => {
26637
+ const existing = (getReq.result || null);
26638
+ const next = existing
26639
+ ? { ...existing, updatedAt }
26640
+ : { tabId, updatedAt };
26641
+ store.put(next);
26642
+ };
26643
+ getReq.onerror = () => reject(getReq.error);
26644
+ tx.oncomplete = () => resolve();
26645
+ tx.onerror = () => reject(tx.error);
26646
+ });
26647
+ }
26648
+ /**
26649
+ * Best-effort garbage collection for orphaned tabs.
26650
+ * Deletes all data for tabs whose `attrs.updatedAt` is older than `maxAgeMs`.
26651
+ */
26652
+ async sweepStaleTabs(maxAgeMs, now = Date.now()) {
26653
+ const attrs = await this.getAllAttrs().catch(() => []);
26654
+ if (!attrs.length)
26655
+ return 0;
26656
+ const stale = attrs
26657
+ .filter((a) => typeof (a === null || a === void 0 ? void 0 : a.updatedAt) === 'number' && now - a.updatedAt > maxAgeMs)
26658
+ .map((a) => a.tabId);
26659
+ let cleared = 0;
26660
+ for (const tabId of stale) {
26661
+ try {
26662
+ await this.clearTab(tabId);
26663
+ cleared += 1;
26664
+ }
26665
+ catch (_e) {
26666
+ // best effort
26667
+ }
26668
+ }
26669
+ return cleared;
26670
+ }
26671
+ async appendRrwebEvent(record) {
26672
+ const db = await this.dbPromise;
26673
+ return new Promise((resolve, reject) => {
26674
+ const tx = db.transaction(rrwebEventsStore, 'readwrite');
26675
+ tx.objectStore(rrwebEventsStore).add(record);
26676
+ tx.oncomplete = () => resolve();
26677
+ tx.onerror = () => reject(tx.error);
26678
+ });
26679
+ }
26680
+ async appendOtelSpan(record) {
26681
+ const db = await this.dbPromise;
26682
+ return new Promise((resolve, reject) => {
26683
+ const tx = db.transaction(otelSpansStore, 'readwrite');
26684
+ tx.objectStore(otelSpansStore).add(record);
26685
+ tx.oncomplete = () => resolve();
26686
+ tx.onerror = () => reject(tx.error);
26687
+ });
26688
+ }
26689
+ async getRrwebEventsWindow(tabId, fromTs, toTs) {
26690
+ const db = await this.dbPromise;
26691
+ const range = IDBKeyRange.bound([tabId, fromTs], [tabId, toTs]);
26692
+ return new Promise((resolve, reject) => {
26693
+ const tx = db.transaction(rrwebEventsStore, 'readonly');
26694
+ const idx = tx.objectStore(rrwebEventsStore).index('tabId_ts');
26695
+ const req = idx.getAll(range);
26696
+ req.onsuccess = () => resolve(req.result || []);
26697
+ req.onerror = () => reject(req.error);
26698
+ });
26699
+ }
26700
+ /**
26701
+ * Returns the last (highest-ts) FullSnapshot record at/before `cutoffTs`.
26702
+ * Used to keep a replayable anchor when pruning.
26703
+ */
26704
+ async getLastRrwebFullSnapshotBefore(tabId, cutoffTs) {
26705
+ const db = await this.dbPromise;
26706
+ const range = IDBKeyRange.bound([tabId, 0], [tabId, cutoffTs]);
26707
+ return new Promise((resolve, reject) => {
26708
+ const tx = db.transaction(rrwebEventsStore, 'readonly');
26709
+ const idx = tx.objectStore(rrwebEventsStore).index('tabId_ts');
26710
+ const req = idx.openCursor(range, 'prev');
26711
+ req.onsuccess = () => {
26712
+ const cursor = req.result;
26713
+ if (!cursor) {
26714
+ resolve(null);
26715
+ return;
26716
+ }
26717
+ const value = cursor.value;
26718
+ if (value === null || value === void 0 ? void 0 : value.isFullSnapshot) {
26719
+ resolve(value);
26720
+ return;
26721
+ }
26722
+ cursor.continue();
26723
+ };
26724
+ req.onerror = () => reject(req.error);
26725
+ });
26726
+ }
26727
+ async getOtelSpansWindow(tabId, fromTs, toTs) {
26728
+ const db = await this.dbPromise;
26729
+ const range = IDBKeyRange.bound([tabId, fromTs], [tabId, toTs]);
26730
+ return new Promise((resolve, reject) => {
26731
+ const tx = db.transaction(otelSpansStore, 'readonly');
26732
+ const idx = tx.objectStore(otelSpansStore).index('tabId_ts');
26733
+ const req = idx.getAll(range);
26734
+ req.onsuccess = () => resolve(req.result || []);
26735
+ req.onerror = () => reject(req.error);
26736
+ });
26737
+ }
26738
+ async pruneOlderThan(tabId, cutoffTs) {
26739
+ const db = await this.dbPromise;
26740
+ const rrwebRange = IDBKeyRange.bound([tabId, 0], [tabId, cutoffTs]);
26741
+ const spansRange = IDBKeyRange.bound([tabId, 0], [tabId, cutoffTs]);
26742
+ const pruneStore = (store, range) => new Promise((resolve, reject) => {
26743
+ const idx = store.index('tabId_ts');
26744
+ const req = idx.openCursor(range);
26745
+ req.onsuccess = () => {
26746
+ const cursor = req.result;
26747
+ if (!cursor) {
26748
+ resolve();
26749
+ return;
26750
+ }
26751
+ cursor.delete();
26752
+ cursor.continue();
26753
+ };
26754
+ req.onerror = () => reject(req.error);
26755
+ });
26756
+ return new Promise((resolve, reject) => {
26757
+ const tx = db.transaction([rrwebEventsStore, otelSpansStore], 'readwrite');
26758
+ const rrwebStore = tx.objectStore(rrwebEventsStore);
26759
+ const spanStore = tx.objectStore(otelSpansStore);
26760
+ Promise.all([
26761
+ pruneStore(rrwebStore, rrwebRange),
26762
+ pruneStore(spanStore, spansRange),
26763
+ ]).then(() => {
26764
+ // noop; completion is signaled by tx.oncomplete
26765
+ }).catch((e) => {
26766
+ reject(e);
26767
+ });
26768
+ tx.oncomplete = () => resolve();
26769
+ tx.onerror = () => reject(tx.error);
26770
+ });
26771
+ }
26772
+ /**
26773
+ * Prune older data while keeping rrweb replayability:
26774
+ * - rrweb: keep the last FullSnapshot at/before cutoff as an "anchor"
26775
+ * - spans: prune strictly by cutoff
26776
+ */
26777
+ async pruneOlderThanWithRrwebSnapshotAnchor(tabId, cutoffTs) {
26778
+ const db = await this.dbPromise;
26779
+ const anchor = await this.getLastRrwebFullSnapshotBefore(tabId, cutoffTs);
26780
+ // rrweb: delete everything strictly older than the anchor snapshot (keep the anchor itself)
26781
+ // spans: delete everything older than cutoffTs
26782
+ const rrwebCutoffTs = typeof (anchor === null || anchor === void 0 ? void 0 : anchor.ts) === 'number' ? Math.max(0, anchor.ts - 1) : cutoffTs;
26783
+ const rrwebRange = IDBKeyRange.bound([tabId, 0], [tabId, rrwebCutoffTs]);
26784
+ const spansRange = IDBKeyRange.bound([tabId, 0], [tabId, cutoffTs]);
26785
+ const pruneStore = (store, range) => new Promise((resolve, reject) => {
26786
+ const idx = store.index('tabId_ts');
26787
+ const req = idx.openCursor(range);
26788
+ req.onsuccess = () => {
26789
+ const cursor = req.result;
26790
+ if (!cursor) {
26791
+ resolve();
26792
+ return;
26793
+ }
26794
+ cursor.delete();
26795
+ cursor.continue();
26796
+ };
26797
+ req.onerror = () => reject(req.error);
26798
+ });
26799
+ return new Promise((resolve, reject) => {
26800
+ const tx = db.transaction([rrwebEventsStore, otelSpansStore], 'readwrite');
26801
+ const rrwebStore = tx.objectStore(rrwebEventsStore);
26802
+ const spanStore = tx.objectStore(otelSpansStore);
26803
+ Promise.all([
26804
+ pruneStore(rrwebStore, rrwebRange),
26805
+ pruneStore(spanStore, spansRange),
26806
+ ]).then(() => {
26807
+ // noop
26808
+ }).catch((e) => reject(e));
26809
+ tx.oncomplete = () => resolve();
26810
+ tx.onerror = () => reject(tx.error);
26811
+ });
26812
+ }
26813
+ async clearTab(tabId) {
26814
+ const db = await this.dbPromise;
26815
+ const allRange = IDBKeyRange.bound([tabId, 0], [tabId, Number.MAX_SAFE_INTEGER]);
26816
+ const clearByTab = (store) => new Promise((resolve, reject) => {
26817
+ const idx = store.index('tabId_ts');
26818
+ const req = idx.openCursor(allRange);
26819
+ req.onsuccess = () => {
26820
+ const cursor = req.result;
26821
+ if (!cursor) {
26822
+ resolve();
26823
+ return;
26824
+ }
26825
+ cursor.delete();
26826
+ cursor.continue();
26827
+ };
26828
+ req.onerror = () => reject(req.error);
26829
+ });
26830
+ return new Promise((resolve, reject) => {
26831
+ const tx = db.transaction([rrwebEventsStore, otelSpansStore, attrsStore], 'readwrite');
26832
+ const rrwebStore = tx.objectStore(rrwebEventsStore);
26833
+ const spanStore = tx.objectStore(otelSpansStore);
26834
+ const attr = tx.objectStore(attrsStore);
26835
+ Promise.all([
26836
+ clearByTab(rrwebStore),
26837
+ clearByTab(spanStore),
26838
+ new Promise((res, rej) => {
26839
+ const r = attr.delete(tabId);
26840
+ r.onsuccess = () => res();
26841
+ r.onerror = () => rej(r.error);
26842
+ }),
26843
+ ]).then(() => {
26844
+ // noop
26845
+ }).catch((e) => reject(e));
26846
+ tx.oncomplete = () => resolve();
26847
+ tx.onerror = () => reject(tx.error);
26848
+ });
26849
+ }
26850
+ }
26851
+
26852
+
26182
26853
  /***/ }),
26183
26854
 
26184
26855
  /***/ "./src/services/messaging.service.ts":
@@ -26299,15 +26970,17 @@ const messagingService = new MessagingService();
26299
26970
  /* harmony export */ SocketService: () => (/* binding */ SocketService)
26300
26971
  /* harmony export */ });
26301
26972
  /* harmony import */ var socket_io_client__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! socket.io-client */ "../../node_modules/socket.io-client/build/esm/index.js");
26302
- /* harmony import */ var lib0_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! lib0/observable */ "../../node_modules/lib0/observable.js");
26973
+ /* harmony import */ var lib0_observable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! lib0/observable */ "../../node_modules/lib0/observable.js");
26303
26974
  /* harmony import */ var _services_messaging_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../services/messaging.service */ "./src/services/messaging.service.ts");
26304
26975
  /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config */ "./src/config/index.ts");
26976
+ /* harmony import */ var _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @multiplayer-app/session-recorder-common */ "../session-recorder-common/dist/esm/index-browser.js");
26977
+
26305
26978
 
26306
26979
 
26307
26980
 
26308
26981
 
26309
26982
  const MAX_RECONNECTION_ATTEMPTS = 2;
26310
- class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_3__.Observable {
26983
+ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observable {
26311
26984
  constructor() {
26312
26985
  super();
26313
26986
  this.socket = null;
@@ -26374,6 +27047,9 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_3__.Observa
26374
27047
  path: '/v0/radar/ws',
26375
27048
  auth: {
26376
27049
  'x-api-key': this.options.apiKey,
27050
+ ...this.options.clientId
27051
+ ? { [_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_3__.ATTR_MULTIPLAYER_SESSION_CLIENT_ID]: this.options.clientId }
27052
+ : {},
26377
27053
  },
26378
27054
  reconnectionAttempts: 2,
26379
27055
  transports: ['websocket'],
@@ -26405,6 +27081,9 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_3__.Observa
26405
27081
  this.socket.on(_config__WEBPACK_IMPORTED_MODULE_2__.REMOTE_SESSION_RECORDING_STOP, (data) => {
26406
27082
  this.emit(_config__WEBPACK_IMPORTED_MODULE_2__.REMOTE_SESSION_RECORDING_STOP, [data]);
26407
27083
  });
27084
+ this.socket.on(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SAVE_BUFFER_EVENT, (data) => {
27085
+ this.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SAVE_BUFFER_EVENT, [data]);
27086
+ });
26408
27087
  }
26409
27088
  checkReconnectionAttempts() {
26410
27089
  if (this.attempts >= MAX_RECONNECTION_ATTEMPTS) {
@@ -26505,21 +27184,23 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_3__.Observa
26505
27184
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26506
27185
  /* harmony export */ SessionRecorder: () => (/* binding */ SessionRecorder)
26507
27186
  /* harmony export */ });
26508
- /* harmony import */ var lib0_observable__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! lib0/observable */ "../../node_modules/lib0/observable.js");
27187
+ /* harmony import */ var lib0_observable__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! lib0/observable */ "../../node_modules/lib0/observable.js");
26509
27188
  /* harmony import */ var _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @multiplayer-app/session-recorder-common */ "../session-recorder-common/dist/esm/index-browser.js");
26510
27189
  /* harmony import */ var _otel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./otel */ "./src/otel/index.ts");
26511
27190
  /* harmony import */ var _rrweb__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./rrweb */ "./src/rrweb/index.ts");
26512
27191
  /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils */ "./src/utils/index.ts");
26513
27192
  /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./types */ "./src/types/index.ts");
26514
- /* harmony import */ var _services_socket_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./services/socket.service */ "./src/services/socket.service.ts");
26515
- /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./config */ "./src/config/index.ts");
26516
- /* harmony import */ var _patch__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./patch */ "./src/patch/index.ts");
26517
- /* harmony import */ var _eventBus__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./eventBus */ "./src/eventBus.ts");
26518
- /* harmony import */ var _sessionWidget__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./sessionWidget */ "./src/sessionWidget/index.ts");
26519
- /* harmony import */ var _services_messaging_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./services/messaging.service */ "./src/services/messaging.service.ts");
26520
- /* harmony import */ var _services_api_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./services/api.service */ "./src/services/api.service.ts");
26521
- /* harmony import */ var _sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./sessionWidget/buttonStateConfigs */ "./src/sessionWidget/buttonStateConfigs.ts");
26522
- /* harmony import */ var _navigation__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./navigation */ "./src/navigation/index.ts");
27193
+ /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./config */ "./src/config/index.ts");
27194
+ /* harmony import */ var _patch__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./patch */ "./src/patch/index.ts");
27195
+ /* harmony import */ var _eventBus__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./eventBus */ "./src/eventBus.ts");
27196
+ /* harmony import */ var _sessionWidget__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./sessionWidget */ "./src/sessionWidget/index.ts");
27197
+ /* harmony import */ var _services_messaging_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./services/messaging.service */ "./src/services/messaging.service.ts");
27198
+ /* harmony import */ var _services_api_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./services/api.service */ "./src/services/api.service.ts");
27199
+ /* harmony import */ var _services_socket_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./services/socket.service */ "./src/services/socket.service.ts");
27200
+ /* harmony import */ var _services_indexedDb_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./services/indexedDb.service */ "./src/services/indexedDb.service.ts");
27201
+ /* harmony import */ var _services_crashBuffer_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./services/crashBuffer.service */ "./src/services/crashBuffer.service.ts");
27202
+ /* harmony import */ var _sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./sessionWidget/buttonStateConfigs */ "./src/sessionWidget/buttonStateConfigs.ts");
27203
+ /* harmony import */ var _navigation__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./navigation */ "./src/navigation/index.ts");
26523
27204
 
26524
27205
 
26525
27206
 
@@ -26535,7 +27216,9 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_3__.Observa
26535
27216
 
26536
27217
 
26537
27218
 
26538
- class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Observable {
27219
+
27220
+
27221
+ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Observable {
26539
27222
  get navigation() {
26540
27223
  return this._navigationRecorder.api;
26541
27224
  }
@@ -26547,7 +27230,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26547
27230
  }
26548
27231
  set sessionId(sessionId) {
26549
27232
  this._sessionId = sessionId;
26550
- (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_ID_PROP_NAME, sessionId);
27233
+ (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_ID_PROP_NAME, sessionId);
26551
27234
  }
26552
27235
  get sessionType() {
26553
27236
  return this._sessionType;
@@ -26556,8 +27239,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26556
27239
  this._sessionType = sessionType;
26557
27240
  const continuousRecording = sessionType === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS;
26558
27241
  this._sessionWidget.updateContinuousRecordingState(continuousRecording);
26559
- _services_messaging_service__WEBPACK_IMPORTED_MODULE_10__["default"].sendMessage('continuous-debugging', continuousRecording);
26560
- (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_TYPE_PROP_NAME, sessionType);
27242
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_9__["default"].sendMessage('continuous-debugging', continuousRecording);
27243
+ (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_TYPE_PROP_NAME, sessionType);
26561
27244
  }
26562
27245
  get continuousRecording() {
26563
27246
  return this.sessionType === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS;
@@ -26568,8 +27251,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26568
27251
  set sessionState(state) {
26569
27252
  this._sessionState = state;
26570
27253
  this._sessionWidget.updateState(this._sessionState, this.continuousRecording);
26571
- _services_messaging_service__WEBPACK_IMPORTED_MODULE_10__["default"].sendMessage('state-change', this._sessionState);
26572
- (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_STATE_PROP_NAME, state);
27254
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_9__["default"].sendMessage('state-change', this._sessionState);
27255
+ (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_STATE_PROP_NAME, state);
26573
27256
  // Emit observable event to support React wrapper
26574
27257
  this.emit('state-change', [this._sessionState || _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped, this.sessionType]);
26575
27258
  }
@@ -26578,19 +27261,23 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26578
27261
  }
26579
27262
  set session(session) {
26580
27263
  this._session = session;
26581
- (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_PROP_NAME, this._session);
27264
+ (0,_utils__WEBPACK_IMPORTED_MODULE_3__.setStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_PROP_NAME, this._session);
26582
27265
  }
26583
27266
  get sessionAttributes() {
26584
27267
  return this._sessionAttributes || {};
26585
27268
  }
26586
27269
  set sessionAttributes(attributes) {
27270
+ var _a;
26587
27271
  this._sessionAttributes = attributes;
27272
+ (_a = this._crashBuffer) === null || _a === void 0 ? void 0 : _a.setAttrs({ sessionAttributes: this.sessionAttributes });
26588
27273
  }
26589
27274
  get userAttributes() {
26590
27275
  return this._userAttributes;
26591
27276
  }
26592
27277
  set userAttributes(userAttributes) {
27278
+ var _a;
26593
27279
  this._userAttributes = userAttributes;
27280
+ (_a = this._crashBuffer) === null || _a === void 0 ? void 0 : _a.setAttrs({ userAttributes: this._userAttributes });
26594
27281
  }
26595
27282
  get error() {
26596
27283
  return this._error;
@@ -26616,15 +27303,20 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26616
27303
  constructor() {
26617
27304
  var _a;
26618
27305
  super();
26619
- this._apiService = new _services_api_service__WEBPACK_IMPORTED_MODULE_11__.ApiService();
26620
- this._socketService = new _services_socket_service__WEBPACK_IMPORTED_MODULE_5__.SocketService();
27306
+ this._apiService = new _services_api_service__WEBPACK_IMPORTED_MODULE_10__.ApiService();
27307
+ this._socketService = new _services_socket_service__WEBPACK_IMPORTED_MODULE_11__.SocketService();
26621
27308
  this._tracer = new _otel__WEBPACK_IMPORTED_MODULE_1__.TracerBrowserSDK();
26622
27309
  this._recorder = new _rrweb__WEBPACK_IMPORTED_MODULE_2__.RecorderBrowserSDK();
26623
- this._sessionWidget = new _sessionWidget__WEBPACK_IMPORTED_MODULE_9__.SessionWidget();
26624
- this._navigationRecorder = new _navigation__WEBPACK_IMPORTED_MODULE_13__.NavigationRecorder();
27310
+ this._sessionWidget = new _sessionWidget__WEBPACK_IMPORTED_MODULE_8__.SessionWidget();
27311
+ this._navigationRecorder = new _navigation__WEBPACK_IMPORTED_MODULE_15__.NavigationRecorder();
26625
27312
  this._startRequestController = null;
27313
+ this._tabId = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getOrCreateTabId)();
27314
+ this._bufferDb = new _services_indexedDb_service__WEBPACK_IMPORTED_MODULE_12__.IndexedDBService();
27315
+ this._crashBuffer = null;
27316
+ this._isFlushingBuffer = false;
27317
+ this._bufferLifecycleHandlersRegistered = false;
26626
27318
  this._isInitialized = false;
26627
- // Session ID and state are stored in localStorage
27319
+ // Session ID and state are stored in sessionStorage (with fallback) to avoid multi-tab conflicts
26628
27320
  this._sessionId = null;
26629
27321
  this._sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
26630
27322
  this._sessionState = null;
@@ -26637,10 +27329,10 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26637
27329
  this._error = '';
26638
27330
  // Safety: avoid accessing storage in SSR/non-browser environments
26639
27331
  const isBrowser = typeof window !== 'undefined';
26640
- const sessionLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_PROP_NAME, true) : null;
26641
- const sessionIdLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_ID_PROP_NAME) : null;
26642
- const sessionStateLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_STATE_PROP_NAME) : null;
26643
- const sessionTypeLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_TYPE_PROP_NAME) : null;
27332
+ const sessionLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_PROP_NAME, true) : null;
27333
+ const sessionIdLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_ID_PROP_NAME) : null;
27334
+ const sessionStateLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_STATE_PROP_NAME) : null;
27335
+ const sessionTypeLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_TYPE_PROP_NAME) : null;
26644
27336
  if ((0,_utils__WEBPACK_IMPORTED_MODULE_3__.isSessionActive)(sessionLocal, sessionTypeLocal)) {
26645
27337
  this.session = sessionLocal;
26646
27338
  this.sessionId = sessionIdLocal;
@@ -26654,7 +27346,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26654
27346
  this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
26655
27347
  }
26656
27348
  this._configs = {
26657
- ..._config__WEBPACK_IMPORTED_MODULE_6__.BASE_CONFIG,
27349
+ ..._config__WEBPACK_IMPORTED_MODULE_5__.BASE_CONFIG,
26658
27350
  apiKey: ((_a = this.session) === null || _a === void 0 ? void 0 : _a.tempApiKey) || '',
26659
27351
  };
26660
27352
  }
@@ -26663,18 +27355,23 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26663
27355
  * @param configs - custom configurations for session debugger
26664
27356
  */
26665
27357
  init(configs) {
27358
+ var _a;
26666
27359
  if (typeof window === 'undefined') {
26667
27360
  return;
26668
27361
  }
26669
- this._configs = (0,_config__WEBPACK_IMPORTED_MODULE_6__.getSessionRecorderConfig)({ ...this._configs, ...configs });
27362
+ this._configs = (0,_config__WEBPACK_IMPORTED_MODULE_5__.getSessionRecorderConfig)({ ...this._configs, ...configs });
26670
27363
  this._isInitialized = true;
26671
27364
  this._checkOperation('init');
26672
- (0,_patch__WEBPACK_IMPORTED_MODULE_7__.setMaxCapturingHttpPayloadSize)(this._configs.maxCapturingHttpPayloadSize || _config__WEBPACK_IMPORTED_MODULE_6__.DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE);
26673
- (0,_patch__WEBPACK_IMPORTED_MODULE_7__.setShouldRecordHttpData)(this._configs.captureBody, this._configs.captureHeaders);
27365
+ // GC: remove orphaned crash buffers from old tabs.
27366
+ // Keep TTL large to avoid any accidental data loss.
27367
+ void this._bufferDb.sweepStaleTabs(24 * 60 * 60 * 1000);
27368
+ (0,_patch__WEBPACK_IMPORTED_MODULE_6__.setMaxCapturingHttpPayloadSize)(this._configs.maxCapturingHttpPayloadSize || _config__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE);
27369
+ (0,_patch__WEBPACK_IMPORTED_MODULE_6__.setShouldRecordHttpData)(this._configs.captureBody, this._configs.captureHeaders);
26674
27370
  this._tracer.init(this._configs);
26675
27371
  this._apiService.init(this._configs);
26676
27372
  this._sessionWidget.init(this._configs);
26677
27373
  this._socketService.init({
27374
+ clientId: this._tracer.clientId,
26678
27375
  apiKey: this._configs.apiKey,
26679
27376
  socketUrl: this._configs.apiBaseUrl || '',
26680
27377
  keepAlive: Boolean(this._configs.useWebsocket),
@@ -26689,17 +27386,83 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26689
27386
  if (this._configs.apiKey) {
26690
27387
  this._recorder.init(this._configs, this._socketService);
26691
27388
  }
27389
+ // Crash buffer (browser): keep a short rolling window when not actively recording.
27390
+ if ((_a = this._configs.buffering) === null || _a === void 0 ? void 0 : _a.enabled) {
27391
+ const windowMinutes = this._configs.buffering.windowMinutes || 1;
27392
+ const windowMs = Math.max(10000, windowMinutes * 60 * 1000);
27393
+ this._crashBuffer = new _services_crashBuffer_service__WEBPACK_IMPORTED_MODULE_13__.CrashBufferService(this._bufferDb, this._tabId, windowMs);
27394
+ this._recorder.setCrashBuffer(this._crashBuffer);
27395
+ this._tracer.setCrashBuffer(this._crashBuffer);
27396
+ this._crashBuffer.setAttrs({
27397
+ sessionAttributes: this.sessionAttributes,
27398
+ resourceAttributes: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getNavigatorInfo)(),
27399
+ userAttributes: this._userAttributes,
27400
+ });
27401
+ this._registerCrashBufferLifecycleHandlers();
27402
+ }
26692
27403
  if (this.sessionId
26693
27404
  && (this.sessionState === _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.started
26694
27405
  || this.sessionState === _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.paused)) {
26695
27406
  this._start();
26696
27407
  }
27408
+ else {
27409
+ // Buffer-only recording when there is no active debug session.
27410
+ this._startBufferOnlyRecording();
27411
+ }
26697
27412
  this._registerWidgetEvents();
26698
27413
  this._registerSocketServiceListeners();
26699
- _services_messaging_service__WEBPACK_IMPORTED_MODULE_10__["default"].sendMessage('state-change', this.sessionState);
27414
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_9__["default"].sendMessage('state-change', this.sessionState);
26700
27415
  // Emit init observable event
26701
27416
  this.emit('init', [this]);
26702
27417
  }
27418
+ _registerCrashBufferLifecycleHandlers() {
27419
+ if (this._bufferLifecycleHandlersRegistered)
27420
+ return;
27421
+ if (typeof window === 'undefined')
27422
+ return;
27423
+ if (typeof document === 'undefined')
27424
+ return;
27425
+ if (!this._crashBuffer)
27426
+ return;
27427
+ this._bufferLifecycleHandlersRegistered = true;
27428
+ const update = () => this._updateCrashBufferActiveState();
27429
+ window.addEventListener('focus', update, { passive: true });
27430
+ window.addEventListener('blur', update, { passive: true });
27431
+ document.addEventListener('visibilitychange', update, { passive: true });
27432
+ // Set initial state.
27433
+ update();
27434
+ }
27435
+ _updateCrashBufferActiveState() {
27436
+ if (!this._crashBuffer)
27437
+ return;
27438
+ if (typeof document === 'undefined')
27439
+ return;
27440
+ let hasFocus = true;
27441
+ try {
27442
+ hasFocus = typeof document.hasFocus === 'function' ? document.hasFocus() : true;
27443
+ }
27444
+ catch (_e) {
27445
+ hasFocus = true;
27446
+ }
27447
+ const isVisible = document.visibilityState === 'visible' && !document.hidden;
27448
+ const active = isVisible && hasFocus;
27449
+ this._crashBuffer.setActive(active);
27450
+ if (active && this._crashBuffer.needsFullSnapshot()) {
27451
+ // If the buffer was cleared while inactive, the next stored rrweb event must be a FullSnapshot.
27452
+ this._recorder.takeFullSnapshot();
27453
+ }
27454
+ }
27455
+ _startBufferOnlyRecording() {
27456
+ var _a, _b;
27457
+ if (!((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled))
27458
+ return;
27459
+ if (!this._crashBuffer)
27460
+ return;
27461
+ // Don’t start if a session is active.
27462
+ if (this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped || this.sessionId)
27463
+ return;
27464
+ void this._recorder.restart(null, _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL);
27465
+ }
26703
27466
  /**
26704
27467
  * Save the continuous recording session
26705
27468
  */
@@ -26709,14 +27472,14 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26709
27472
  if (!this.continuousRecording || !this._configs.showContinuousRecording) {
26710
27473
  return;
26711
27474
  }
26712
- this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_12__.ContinuousRecordingSaveButtonState.SAVING);
27475
+ this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_14__.ContinuousRecordingSaveButtonState.SAVING);
26713
27476
  const res = await this._apiService.saveContinuousDebugSession(this.sessionId, {
26714
27477
  sessionAttributes: this.sessionAttributes,
26715
27478
  resourceAttributes: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getNavigatorInfo)(),
26716
27479
  stoppedAt: this._recorder.stoppedAt,
26717
27480
  name: this._getSessionName()
26718
27481
  });
26719
- this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_12__.ContinuousRecordingSaveButtonState.SAVED);
27482
+ this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_14__.ContinuousRecordingSaveButtonState.SAVED);
26720
27483
  const sessionUrl = res === null || res === void 0 ? void 0 : res.url;
26721
27484
  this._sessionWidget.showToast({
26722
27485
  type: 'success',
@@ -26729,11 +27492,11 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26729
27492
  }
26730
27493
  catch (error) {
26731
27494
  this.error = error.message;
26732
- this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_12__.ContinuousRecordingSaveButtonState.ERROR);
27495
+ this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_14__.ContinuousRecordingSaveButtonState.ERROR);
26733
27496
  }
26734
27497
  finally {
26735
27498
  setTimeout(() => {
26736
- this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_12__.ContinuousRecordingSaveButtonState.IDLE);
27499
+ this._sessionWidget.updateSaveContinuousDebugSessionState(_sessionWidget_buttonStateConfigs__WEBPACK_IMPORTED_MODULE_14__.ContinuousRecordingSaveButtonState.IDLE);
26737
27500
  }, 3000);
26738
27501
  }
26739
27502
  }
@@ -26775,7 +27538,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26775
27538
  stoppedAt: this._recorder.stoppedAt,
26776
27539
  };
26777
27540
  const response = await this._apiService.stopSession(this.sessionId, request);
26778
- _eventBus__WEBPACK_IMPORTED_MODULE_8__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_RESPONSE, response);
27541
+ _eventBus__WEBPACK_IMPORTED_MODULE_7__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_RESPONSE, response);
26779
27542
  }
26780
27543
  this._clearSession();
26781
27544
  }
@@ -26863,11 +27626,70 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26863
27626
  const normalizedError = this._normalizeError(error);
26864
27627
  const normalizedErrorInfo = this._normalizeErrorInfo(errorInfo);
26865
27628
  this._tracer.captureException(normalizedError, normalizedErrorInfo);
27629
+ // If user isn't actively recording, auto-flush the crash buffer.
27630
+ if (this.sessionState === _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped && !this.sessionId) {
27631
+ void this.flushBuffer({ reason: 'exception' });
27632
+ }
26866
27633
  }
26867
27634
  catch (e) {
26868
27635
  this.error = (e === null || e === void 0 ? void 0 : e.message) || 'Failed to capture exception';
26869
27636
  }
26870
27637
  }
27638
+ async flushBuffer(payload) {
27639
+ var _a, _b;
27640
+ if (!((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled))
27641
+ return null;
27642
+ if (!this._crashBuffer)
27643
+ return null;
27644
+ if (this._isFlushingBuffer)
27645
+ return null;
27646
+ // Don’t flush while a live recording is active.
27647
+ if (this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped || this.sessionId)
27648
+ return null;
27649
+ this._isFlushingBuffer = true;
27650
+ try {
27651
+ const reason = (payload === null || payload === void 0 ? void 0 : payload.reason) || 'manual';
27652
+ await this._crashBuffer.setAttrs({
27653
+ sessionAttributes: this.sessionAttributes,
27654
+ resourceAttributes: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getNavigatorInfo)(),
27655
+ userAttributes: this._userAttributes,
27656
+ });
27657
+ const snapshot = await this._crashBuffer.snapshot();
27658
+ if (snapshot.rrwebEvents.length === 0 && snapshot.otelSpans.length === 0) {
27659
+ return null;
27660
+ }
27661
+ const request = {
27662
+ name: this._getSessionName(),
27663
+ stoppedAt: new Date().toISOString(),
27664
+ sessionAttributes: this.sessionAttributes,
27665
+ resourceAttributes: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getNavigatorInfo)(),
27666
+ ...(this._userAttributes ? { userAttributes: this._userAttributes } : {}),
27667
+ debugSessionData: {
27668
+ meta: {
27669
+ reason,
27670
+ windowMs: snapshot.windowMs,
27671
+ fromTs: snapshot.fromTs,
27672
+ toTs: snapshot.toTs,
27673
+ },
27674
+ events: snapshot.rrwebEvents.map((e) => e.event),
27675
+ spans: snapshot.otelSpans.map((s) => s.span),
27676
+ attrs: snapshot.attrs,
27677
+ },
27678
+ };
27679
+ try {
27680
+ const res = await this._apiService.startSession(request);
27681
+ await this._crashBuffer.clear();
27682
+ return res;
27683
+ }
27684
+ catch (_e) {
27685
+ // swallow: flush is best-effort; never throw into app code
27686
+ return null;
27687
+ }
27688
+ }
27689
+ finally {
27690
+ this._isFlushingBuffer = false;
27691
+ }
27692
+ }
26871
27693
  /**
26872
27694
  * @description Check if session should be started/stopped automatically
26873
27695
  * @param {ISession} [sessionPayload]
@@ -26999,12 +27821,12 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26999
27821
  * Register socket service event listeners
27000
27822
  */
27001
27823
  _registerSocketServiceListeners() {
27002
- this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_STOPPED_EVENT, () => {
27824
+ this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_STOPPED_EVENT, () => {
27003
27825
  this._stop();
27004
27826
  this._clearSession();
27005
27827
  this._sessionWidget.handleUIReseting();
27006
27828
  });
27007
- this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_AUTO_CREATED, (payload) => {
27829
+ this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_AUTO_CREATED, (payload) => {
27008
27830
  var _a;
27009
27831
  if (!(payload === null || payload === void 0 ? void 0 : payload.data))
27010
27832
  return;
@@ -27017,18 +27839,23 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
27017
27839
  },
27018
27840
  }, 5000);
27019
27841
  });
27020
- this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_6__.REMOTE_SESSION_RECORDING_START, (payload) => {
27842
+ this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.REMOTE_SESSION_RECORDING_START, (payload) => {
27021
27843
  console.log('REMOTE_SESSION_RECORDING_START', payload);
27022
27844
  if (this.sessionState === _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
27023
27845
  this.start();
27024
27846
  }
27025
27847
  });
27026
- this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_6__.REMOTE_SESSION_RECORDING_STOP, (payload) => {
27848
+ this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.REMOTE_SESSION_RECORDING_STOP, (payload) => {
27027
27849
  console.log('REMOTE_SESSION_RECORDING_STOP', payload);
27028
27850
  if (this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
27029
27851
  this.stop();
27030
27852
  }
27031
27853
  });
27854
+ this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_SAVE_BUFFER_EVENT, (payload) => {
27855
+ // Backend asks the client to flush its crash buffer as a debug session.
27856
+ const reason = (payload === null || payload === void 0 ? void 0 : payload.reason) || 'remote';
27857
+ void this.flushBuffer({ reason });
27858
+ });
27032
27859
  }
27033
27860
  /**
27034
27861
  * Create a new session and start it
@@ -27071,10 +27898,11 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
27071
27898
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.started;
27072
27899
  this.sessionType = this.sessionType;
27073
27900
  this._tracer.start(this.sessionId, this.sessionType);
27074
- this._recorder.start(this.sessionId, this.sessionType);
27901
+ // Ensure we switch from buffer-only recording to session recording cleanly.
27902
+ void this._recorder.restart(this.sessionId, this.sessionType);
27075
27903
  this._navigationRecorder.start({ sessionId: this.sessionId, sessionType: this.sessionType, });
27076
27904
  if (this.session) {
27077
- _eventBus__WEBPACK_IMPORTED_MODULE_8__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_6__.SESSION_STARTED_EVENT, this.session);
27905
+ _eventBus__WEBPACK_IMPORTED_MODULE_7__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_STARTED_EVENT, this.session);
27078
27906
  this._socketService.subscribeToSession(this.session);
27079
27907
  this._sessionWidget.seconds = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getTimeDifferenceInSeconds)((_a = this.session) === null || _a === void 0 ? void 0 : _a.startedAt);
27080
27908
  }
@@ -27088,6 +27916,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
27088
27916
  this._tracer.stop();
27089
27917
  this._recorder.stop();
27090
27918
  this._navigationRecorder.stop();
27919
+ this._startBufferOnlyRecording();
27091
27920
  }
27092
27921
  /**
27093
27922
  * Pause the session tracing and recording
@@ -27103,7 +27932,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
27103
27932
  */
27104
27933
  _resume() {
27105
27934
  this._tracer.start(this.sessionId, this.sessionType);
27106
- this._recorder.start(this.sessionId, this.sessionType);
27935
+ void this._recorder.restart(this.sessionId, this.sessionType);
27107
27936
  this._navigationRecorder.resume();
27108
27937
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.started;
27109
27938
  }
@@ -27119,7 +27948,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
27119
27948
  this._start();
27120
27949
  }
27121
27950
  /**
27122
- * Set the session ID in localStorage
27951
+ * Set the session ID in sessionStorage (with fallback)
27123
27952
  * @param sessionId - the session ID to set or clear
27124
27953
  */
27125
27954
  _setSession(session) {
@@ -28780,6 +29609,7 @@ const userAgent = navigator === null || navigator === void 0 ? void 0 : navigato
28780
29609
  /* harmony export */ formatTimeForSessionTimer: () => (/* reexport safe */ _time__WEBPACK_IMPORTED_MODULE_2__.formatTimeForSessionTimer),
28781
29610
  /* harmony export */ getFormattedDate: () => (/* reexport safe */ _time__WEBPACK_IMPORTED_MODULE_2__.getFormattedDate),
28782
29611
  /* harmony export */ getNavigatorInfo: () => (/* reexport safe */ _navigator__WEBPACK_IMPORTED_MODULE_0__.getNavigatorInfo),
29612
+ /* harmony export */ getOrCreateTabId: () => (/* reexport safe */ _tabId__WEBPACK_IMPORTED_MODULE_8__.getOrCreateTabId),
28783
29613
  /* harmony export */ getStoredItem: () => (/* reexport safe */ _storage__WEBPACK_IMPORTED_MODULE_1__.getStoredItem),
28784
29614
  /* harmony export */ getTimeDifferenceInSeconds: () => (/* reexport safe */ _time__WEBPACK_IMPORTED_MODULE_2__.getTimeDifferenceInSeconds),
28785
29615
  /* harmony export */ injectStylesIntoShadowRoot: () => (/* reexport safe */ _dom__WEBPACK_IMPORTED_MODULE_4__.injectStylesIntoShadowRoot),
@@ -28797,6 +29627,7 @@ const userAgent = navigator === null || navigator === void 0 ? void 0 : navigato
28797
29627
  /* harmony import */ var _array__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./array */ "./src/utils/array.ts");
28798
29628
  /* harmony import */ var _type_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./type-utils */ "./src/utils/type-utils.ts");
28799
29629
  /* harmony import */ var _globals__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./globals */ "./src/utils/globals.ts");
29630
+ /* harmony import */ var _tabId__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./tabId */ "./src/utils/tabId.ts");
28800
29631
  // Export all utility functions
28801
29632
 
28802
29633
 
@@ -28808,6 +29639,7 @@ const userAgent = navigator === null || navigator === void 0 ? void 0 : navigato
28808
29639
 
28809
29640
 
28810
29641
 
29642
+
28811
29643
  /***/ }),
28812
29644
 
28813
29645
  /***/ "./src/utils/navigator.ts":
@@ -29044,32 +29876,89 @@ const isConsoleEvent = (event) => {
29044
29876
  /* harmony export */ });
29045
29877
  /* unused harmony export removeStoredItem */
29046
29878
  /**
29047
- * LocalStorage utility functions
29879
+ * Storage utility functions.
29880
+ *
29881
+ * Session state must be isolated per-tab to avoid conflicts across multiple tabs.
29882
+ * We therefore prefer `sessionStorage` and fall back to `localStorage` if needed.
29048
29883
  */
29049
- const hasLocalStorage = typeof window !== 'undefined' && !!window.localStorage;
29050
- const getStoredItem = (key, parse) => {
29051
- if (!hasLocalStorage) {
29052
- return parse ? null : null;
29884
+ const hasWindow = typeof window !== 'undefined';
29885
+ const getStorage = () => {
29886
+ if (!hasWindow)
29887
+ return null;
29888
+ try {
29889
+ if (window.sessionStorage)
29890
+ return window.sessionStorage;
29891
+ }
29892
+ catch (_e) {
29893
+ // sessionStorage can throw (e.g. blocked in some environments)
29894
+ }
29895
+ try {
29896
+ if (window.localStorage)
29897
+ return window.localStorage;
29898
+ }
29899
+ catch (_e) {
29900
+ // localStorage can throw (e.g. blocked in some environments)
29053
29901
  }
29054
- const item = window.localStorage.getItem(key);
29902
+ return null;
29903
+ };
29904
+ const getStoredItem = (key, parse) => {
29905
+ const storage = getStorage();
29906
+ if (!storage)
29907
+ return null;
29908
+ const item = storage.getItem(key);
29055
29909
  return parse ? (item ? JSON.parse(item) : null) : item;
29056
29910
  };
29057
29911
  const setStoredItem = (key, value) => {
29058
- if (!hasLocalStorage) {
29912
+ const storage = getStorage();
29913
+ if (!storage)
29059
29914
  return;
29060
- }
29061
29915
  if (value === null || value === undefined) {
29062
- window.localStorage.removeItem(key);
29916
+ storage.removeItem(key);
29063
29917
  }
29064
29918
  else {
29065
- window.localStorage.setItem(key, typeof value === 'string' ? value : JSON.stringify(value));
29919
+ storage.setItem(key, typeof value === 'string' ? value : JSON.stringify(value));
29066
29920
  }
29067
29921
  };
29068
29922
  const removeStoredItem = (key) => {
29069
- if (!hasLocalStorage) {
29923
+ const storage = getStorage();
29924
+ if (!storage)
29070
29925
  return;
29926
+ storage.removeItem(key);
29927
+ };
29928
+
29929
+
29930
+ /***/ }),
29931
+
29932
+ /***/ "./src/utils/tabId.ts":
29933
+ /*!****************************!*\
29934
+ !*** ./src/utils/tabId.ts ***!
29935
+ \****************************/
29936
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
29937
+
29938
+ "use strict";
29939
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
29940
+ /* harmony export */ getOrCreateTabId: () => (/* binding */ getOrCreateTabId)
29941
+ /* harmony export */ });
29942
+ const TAB_ID_KEY = 'multiplayer-tab-id';
29943
+ const randomId = () => {
29944
+ // Avoid crypto dependency for older browsers; good enough for per-tab isolation
29945
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
29946
+ };
29947
+ const getOrCreateTabId = () => {
29948
+ if (typeof window === 'undefined')
29949
+ return 'ssr';
29950
+ try {
29951
+ const existing = window.sessionStorage.getItem(TAB_ID_KEY);
29952
+ if (existing)
29953
+ return existing;
29954
+ const id = randomId();
29955
+ window.sessionStorage.setItem(TAB_ID_KEY, id);
29956
+ return id;
29957
+ }
29958
+ catch (_e) {
29959
+ // If sessionStorage is blocked, fall back to a runtime-only id.
29960
+ return randomId();
29071
29961
  }
29072
- window.localStorage.removeItem(key);
29073
29962
  };
29074
29963
 
29075
29964
 
@@ -29218,42 +30107,48 @@ const isFile = (x) => {
29218
30107
  /* harmony export */ SessionRecorderIdGenerator: () => (/* binding */ SessionRecorderIdGenerator)
29219
30108
  /* harmony export */ });
29220
30109
  /* harmony import */ var _type__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./type */ "../session-recorder-common/dist/esm/type/index.js");
29221
- /* harmony import */ var _constants_constants_base__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./constants/constants.base */ "../session-recorder-common/dist/esm/constants/constants.base.js");
29222
- /* harmony import */ var _sdk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sdk */ "../session-recorder-common/dist/esm/sdk/index.js");
30110
+ /* harmony import */ var _sdk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sdk */ "../session-recorder-common/dist/esm/sdk/index.js");
30111
+ /* harmony import */ var _constants_constants_base__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./constants/constants.base */ "../session-recorder-common/dist/esm/constants/constants.base.js");
29223
30112
 
29224
30113
 
29225
30114
 
29226
30115
  var SessionRecorderIdGenerator = /** @class */ (function () {
29227
30116
  function SessionRecorderIdGenerator() {
29228
- this.generateLongId = (0,_sdk__WEBPACK_IMPORTED_MODULE_2__.getIdGenerator)(16);
29229
- this.generateShortId = (0,_sdk__WEBPACK_IMPORTED_MODULE_2__.getIdGenerator)(8);
30117
+ this.generateLongId = (0,_sdk__WEBPACK_IMPORTED_MODULE_1__.getIdGenerator)(16);
30118
+ this.generateShortId = (0,_sdk__WEBPACK_IMPORTED_MODULE_1__.getIdGenerator)(8);
29230
30119
  this.sessionShortId = '';
30120
+ this.clientId = '';
29231
30121
  this.sessionType = _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
29232
30122
  }
29233
30123
  SessionRecorderIdGenerator.prototype.generateTraceId = function () {
29234
30124
  var traceId = this.generateLongId();
29235
- if (this.sessionShortId) {
29236
- var sessionTypePrefix = '';
29237
- switch (this.sessionType) {
29238
- case _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS:
29239
- sessionTypePrefix = _constants_constants_base__WEBPACK_IMPORTED_MODULE_1__.MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX;
29240
- break;
29241
- default:
29242
- sessionTypePrefix = _constants_constants_base__WEBPACK_IMPORTED_MODULE_1__.MULTIPLAYER_TRACE_DEBUG_PREFIX;
29243
- }
29244
- var prefix = "".concat(sessionTypePrefix).concat(this.sessionShortId);
29245
- var sessionTraceId = "".concat(prefix).concat(traceId.substring(prefix.length, traceId.length));
29246
- return sessionTraceId;
30125
+ if (!this.sessionShortId && !this.sessionType) {
30126
+ return traceId;
29247
30127
  }
29248
- return traceId;
30128
+ var sessionTypePrefix = _constants_constants_base__WEBPACK_IMPORTED_MODULE_2__.MULTIPLAYER_TRACE_PREFIX_MAP[this.sessionType];
30129
+ var prefix = "".concat(sessionTypePrefix).concat([_type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS_SESSION_CACHE, _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.SESSION_CACHE].includes(this.sessionType) ? this.clientId : '').concat(this.sessionShortId);
30130
+ var sessionTraceId = "".concat(prefix).concat(traceId.substring(prefix.length, traceId.length));
30131
+ return sessionTraceId;
29249
30132
  };
29250
30133
  SessionRecorderIdGenerator.prototype.generateSpanId = function () {
29251
30134
  return this.generateShortId();
29252
30135
  };
29253
- SessionRecorderIdGenerator.prototype.setSessionId = function (sessionShortId, sessionType) {
30136
+ SessionRecorderIdGenerator.prototype.setSessionId = function (sessionShortId, sessionType, clientId) {
29254
30137
  if (sessionType === void 0) { sessionType = _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL; }
30138
+ if (clientId === void 0) { clientId = ''; }
30139
+ if (!clientId &&
30140
+ [
30141
+ _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.SESSION_CACHE,
30142
+ _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS_SESSION_CACHE,
30143
+ ].includes(sessionType)) {
30144
+ throw new Error("Client ID is required for ".concat([
30145
+ _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.SESSION_CACHE,
30146
+ _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS_SESSION_CACHE,
30147
+ ].join(', '), " session types"));
30148
+ }
29255
30149
  this.sessionShortId = sessionShortId;
29256
30150
  this.sessionType = sessionType;
30151
+ this.clientId = clientId;
29257
30152
  };
29258
30153
  return SessionRecorderIdGenerator;
29259
30154
  }());
@@ -29356,6 +30251,7 @@ var SessionRecorderTraceIdRatioBasedSampler = /** @class */ (function () {
29356
30251
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE: () => (/* binding */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE),
29357
30252
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING: () => (/* binding */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING),
29358
30253
  /* harmony export */ ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE: () => (/* binding */ ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE),
30254
+ /* harmony export */ ATTR_MULTIPLAYER_SESSION_CLIENT_ID: () => (/* binding */ ATTR_MULTIPLAYER_SESSION_CLIENT_ID),
29359
30255
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_ID: () => (/* binding */ ATTR_MULTIPLAYER_SESSION_ID),
29360
30256
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION: () => (/* binding */ ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION),
29361
30257
  /* harmony export */ ATTR_MULTIPLAYER_USER_HASH: () => (/* binding */ ATTR_MULTIPLAYER_USER_HASH),
@@ -29369,18 +30265,34 @@ var SessionRecorderTraceIdRatioBasedSampler = /** @class */ (function () {
29369
30265
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL: () => (/* binding */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL),
29370
30266
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL: () => (/* binding */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL),
29371
30267
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL: () => (/* binding */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL),
30268
+ /* harmony export */ MULTIPLAYER_TRACE_CLIENT_ID_LENGTH: () => (/* binding */ MULTIPLAYER_TRACE_CLIENT_ID_LENGTH),
29372
30269
  /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX),
30270
+ /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX),
29373
30271
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_DEBUG_PREFIX),
29374
30272
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH: () => (/* binding */ MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH),
29375
- /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_DOC_PREFIX)
30273
+ /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_DOC_PREFIX),
30274
+ /* harmony export */ MULTIPLAYER_TRACE_PREFIX_MAP: () => (/* binding */ MULTIPLAYER_TRACE_PREFIX_MAP),
30275
+ /* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* binding */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX)
29376
30276
  /* harmony export */ });
30277
+ /* harmony import */ var _type__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../type */ "../session-recorder-common/dist/esm/type/index.js");
30278
+ var _a;
30279
+
29377
30280
  /**
29378
30281
  * @deprecated
29379
30282
  */
29380
30283
  var MULTIPLAYER_TRACE_DOC_PREFIX = 'd0cd0c';
29381
30284
  var MULTIPLAYER_TRACE_DEBUG_PREFIX = 'debdeb';
29382
30285
  var MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX = 'cdbcdb';
29383
- var MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH = 16;
30286
+ var MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX = 'cdbcac';
30287
+ var MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX = 'debcdb';
30288
+ var MULTIPLAYER_TRACE_PREFIX_MAP = (_a = {},
30289
+ _a[_type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS] = MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,
30290
+ _a[_type__WEBPACK_IMPORTED_MODULE_0__.SessionType.SESSION_CACHE] = MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX,
30291
+ _a[_type__WEBPACK_IMPORTED_MODULE_0__.SessionType.CONTINUOUS_SESSION_CACHE] = MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX,
30292
+ _a[_type__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL] = MULTIPLAYER_TRACE_DEBUG_PREFIX,
30293
+ _a);
30294
+ var MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH = 8;
30295
+ var MULTIPLAYER_TRACE_CLIENT_ID_LENGTH = 8;
29384
30296
  /**
29385
30297
  * @deprecated Use MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL instead
29386
30298
  */
@@ -29404,6 +30316,7 @@ var ATTR_MULTIPLAYER_PLATFORM_NAME = 'multiplayer.platform.name';
29404
30316
  var ATTR_MULTIPLAYER_CLIENT_ID = 'multiplayer.client.id';
29405
30317
  var ATTR_MULTIPLAYER_INTEGRATION_ID = 'multiplayer.integration.id';
29406
30318
  var ATTR_MULTIPLAYER_SESSION_ID = 'multiplayer.session.id';
30319
+ var ATTR_MULTIPLAYER_SESSION_CLIENT_ID = 'multiplayer.session.client.id';
29407
30320
  var ATTR_MULTIPLAYER_HTTP_PROXY = 'multiplayer.http.proxy';
29408
30321
  var ATTR_MULTIPLAYER_HTTP_PROXY_TYPE = 'multiplayer.http.proxy.type';
29409
30322
  var ATTR_MULTIPLAYER_HTTP_REQUEST_BODY = 'multiplayer.http.request.body';
@@ -29462,6 +30375,7 @@ var MASK_PLACEHOLDER = '***MASKED***';
29462
30375
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE),
29463
30376
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING),
29464
30377
  /* harmony export */ ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE),
30378
+ /* harmony export */ ATTR_MULTIPLAYER_SESSION_CLIENT_ID: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_CLIENT_ID),
29465
30379
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_ID: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_ID),
29466
30380
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION),
29467
30381
  /* harmony export */ ATTR_MULTIPLAYER_USER_HASH: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_USER_HASH),
@@ -29475,10 +30389,14 @@ var MASK_PLACEHOLDER = '***MASKED***';
29475
30389
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL),
29476
30390
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL),
29477
30391
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL),
30392
+ /* harmony export */ MULTIPLAYER_TRACE_CLIENT_ID_LENGTH: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH),
29478
30393
  /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX),
30394
+ /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX),
29479
30395
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DEBUG_PREFIX),
29480
30396
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH),
29481
- /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DOC_PREFIX)
30397
+ /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DOC_PREFIX),
30398
+ /* harmony export */ MULTIPLAYER_TRACE_PREFIX_MAP: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_PREFIX_MAP),
30399
+ /* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* reexport safe */ _constants_base__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX)
29482
30400
  /* harmony export */ });
29483
30401
  /* harmony import */ var _constants_base__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants.base */ "../session-recorder-common/dist/esm/constants/constants.base.js");
29484
30402
 
@@ -29671,6 +30589,7 @@ var SessionRecorderBrowserTraceExporter = /** @class */ (function () {
29671
30589
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE),
29672
30590
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING),
29673
30591
  /* harmony export */ ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE),
30592
+ /* harmony export */ ATTR_MULTIPLAYER_SESSION_CLIENT_ID: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_CLIENT_ID),
29674
30593
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_ID: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_ID),
29675
30594
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION),
29676
30595
  /* harmony export */ ATTR_MULTIPLAYER_USER_HASH: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.ATTR_MULTIPLAYER_USER_HASH),
@@ -29685,10 +30604,14 @@ var SessionRecorderBrowserTraceExporter = /** @class */ (function () {
29685
30604
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL),
29686
30605
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL),
29687
30606
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL),
30607
+ /* harmony export */ MULTIPLAYER_TRACE_CLIENT_ID_LENGTH: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH),
29688
30608
  /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX),
30609
+ /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX),
29689
30610
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_PREFIX: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DEBUG_PREFIX),
29690
30611
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH),
29691
30612
  /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_DOC_PREFIX),
30613
+ /* harmony export */ MULTIPLAYER_TRACE_PREFIX_MAP: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_PREFIX_MAP),
30614
+ /* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* reexport safe */ _constants_constants_browser__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX),
29692
30615
  /* harmony export */ SessionRecorderBrowserTraceExporter: () => (/* reexport safe */ _exporters_index_browser__WEBPACK_IMPORTED_MODULE_5__.SessionRecorderBrowserTraceExporter),
29693
30616
  /* harmony export */ SessionRecorderIdGenerator: () => (/* reexport safe */ _SessionRecorderIdGenerator__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderIdGenerator),
29694
30617
  /* harmony export */ SessionRecorderSdk: () => (/* reexport module object */ _sdk__WEBPACK_IMPORTED_MODULE_3__),
@@ -30333,6 +31256,8 @@ var SessionType;
30333
31256
  */
30334
31257
  SessionType["PLAIN"] = "MANUAL";
30335
31258
  SessionType["MANUAL"] = "MANUAL";
31259
+ SessionType["CONTINUOUS_SESSION_CACHE"] = "CONTINUOUS_SESSION_CACHE";
31260
+ SessionType["SESSION_CACHE"] = "SESSION_CACHE";
30336
31261
  })(SessionType || (SessionType = {}));
30337
31262
  //# sourceMappingURL=session-type.enum.js.map
30338
31263
 
@@ -32192,6 +33117,116 @@ const getRecordConsolePlugin = (options) => ({
32192
33117
  //# sourceMappingURL=rrweb-plugin-console-record.js.map
32193
33118
 
32194
33119
 
33120
+ /***/ }),
33121
+
33122
+ /***/ "../../node_modules/@rrweb/types/dist/types.js":
33123
+ /*!*****************************************************!*\
33124
+ !*** ../../node_modules/@rrweb/types/dist/types.js ***!
33125
+ \*****************************************************/
33126
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
33127
+
33128
+ "use strict";
33129
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
33130
+ /* harmony export */ EventType: () => (/* binding */ EventType)
33131
+ /* harmony export */ });
33132
+ /* unused harmony exports CanvasContext, IncrementalSource, MediaInteractions, MouseInteractions, NodeType, PointerTypes, ReplayerEvents */
33133
+ var EventType = /* @__PURE__ */ ((EventType2) => {
33134
+ EventType2[EventType2["DomContentLoaded"] = 0] = "DomContentLoaded";
33135
+ EventType2[EventType2["Load"] = 1] = "Load";
33136
+ EventType2[EventType2["FullSnapshot"] = 2] = "FullSnapshot";
33137
+ EventType2[EventType2["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
33138
+ EventType2[EventType2["Meta"] = 4] = "Meta";
33139
+ EventType2[EventType2["Custom"] = 5] = "Custom";
33140
+ EventType2[EventType2["Plugin"] = 6] = "Plugin";
33141
+ return EventType2;
33142
+ })(EventType || {});
33143
+ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
33144
+ IncrementalSource2[IncrementalSource2["Mutation"] = 0] = "Mutation";
33145
+ IncrementalSource2[IncrementalSource2["MouseMove"] = 1] = "MouseMove";
33146
+ IncrementalSource2[IncrementalSource2["MouseInteraction"] = 2] = "MouseInteraction";
33147
+ IncrementalSource2[IncrementalSource2["Scroll"] = 3] = "Scroll";
33148
+ IncrementalSource2[IncrementalSource2["ViewportResize"] = 4] = "ViewportResize";
33149
+ IncrementalSource2[IncrementalSource2["Input"] = 5] = "Input";
33150
+ IncrementalSource2[IncrementalSource2["TouchMove"] = 6] = "TouchMove";
33151
+ IncrementalSource2[IncrementalSource2["MediaInteraction"] = 7] = "MediaInteraction";
33152
+ IncrementalSource2[IncrementalSource2["StyleSheetRule"] = 8] = "StyleSheetRule";
33153
+ IncrementalSource2[IncrementalSource2["CanvasMutation"] = 9] = "CanvasMutation";
33154
+ IncrementalSource2[IncrementalSource2["Font"] = 10] = "Font";
33155
+ IncrementalSource2[IncrementalSource2["Log"] = 11] = "Log";
33156
+ IncrementalSource2[IncrementalSource2["Drag"] = 12] = "Drag";
33157
+ IncrementalSource2[IncrementalSource2["StyleDeclaration"] = 13] = "StyleDeclaration";
33158
+ IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
33159
+ IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
33160
+ IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
33161
+ return IncrementalSource2;
33162
+ })(IncrementalSource || {});
33163
+ var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
33164
+ MouseInteractions2[MouseInteractions2["MouseUp"] = 0] = "MouseUp";
33165
+ MouseInteractions2[MouseInteractions2["MouseDown"] = 1] = "MouseDown";
33166
+ MouseInteractions2[MouseInteractions2["Click"] = 2] = "Click";
33167
+ MouseInteractions2[MouseInteractions2["ContextMenu"] = 3] = "ContextMenu";
33168
+ MouseInteractions2[MouseInteractions2["DblClick"] = 4] = "DblClick";
33169
+ MouseInteractions2[MouseInteractions2["Focus"] = 5] = "Focus";
33170
+ MouseInteractions2[MouseInteractions2["Blur"] = 6] = "Blur";
33171
+ MouseInteractions2[MouseInteractions2["TouchStart"] = 7] = "TouchStart";
33172
+ MouseInteractions2[MouseInteractions2["TouchMove_Departed"] = 8] = "TouchMove_Departed";
33173
+ MouseInteractions2[MouseInteractions2["TouchEnd"] = 9] = "TouchEnd";
33174
+ MouseInteractions2[MouseInteractions2["TouchCancel"] = 10] = "TouchCancel";
33175
+ return MouseInteractions2;
33176
+ })(MouseInteractions || {});
33177
+ var PointerTypes = /* @__PURE__ */ ((PointerTypes2) => {
33178
+ PointerTypes2[PointerTypes2["Mouse"] = 0] = "Mouse";
33179
+ PointerTypes2[PointerTypes2["Pen"] = 1] = "Pen";
33180
+ PointerTypes2[PointerTypes2["Touch"] = 2] = "Touch";
33181
+ return PointerTypes2;
33182
+ })(PointerTypes || {});
33183
+ var CanvasContext = /* @__PURE__ */ ((CanvasContext2) => {
33184
+ CanvasContext2[CanvasContext2["2D"] = 0] = "2D";
33185
+ CanvasContext2[CanvasContext2["WebGL"] = 1] = "WebGL";
33186
+ CanvasContext2[CanvasContext2["WebGL2"] = 2] = "WebGL2";
33187
+ return CanvasContext2;
33188
+ })(CanvasContext || {});
33189
+ var MediaInteractions = /* @__PURE__ */ ((MediaInteractions2) => {
33190
+ MediaInteractions2[MediaInteractions2["Play"] = 0] = "Play";
33191
+ MediaInteractions2[MediaInteractions2["Pause"] = 1] = "Pause";
33192
+ MediaInteractions2[MediaInteractions2["Seeked"] = 2] = "Seeked";
33193
+ MediaInteractions2[MediaInteractions2["VolumeChange"] = 3] = "VolumeChange";
33194
+ MediaInteractions2[MediaInteractions2["RateChange"] = 4] = "RateChange";
33195
+ return MediaInteractions2;
33196
+ })(MediaInteractions || {});
33197
+ var ReplayerEvents = /* @__PURE__ */ ((ReplayerEvents2) => {
33198
+ ReplayerEvents2["Start"] = "start";
33199
+ ReplayerEvents2["Pause"] = "pause";
33200
+ ReplayerEvents2["Resume"] = "resume";
33201
+ ReplayerEvents2["Resize"] = "resize";
33202
+ ReplayerEvents2["Finish"] = "finish";
33203
+ ReplayerEvents2["FullsnapshotRebuilded"] = "fullsnapshot-rebuilded";
33204
+ ReplayerEvents2["LoadStylesheetStart"] = "load-stylesheet-start";
33205
+ ReplayerEvents2["LoadStylesheetEnd"] = "load-stylesheet-end";
33206
+ ReplayerEvents2["SkipStart"] = "skip-start";
33207
+ ReplayerEvents2["SkipEnd"] = "skip-end";
33208
+ ReplayerEvents2["MouseInteraction"] = "mouse-interaction";
33209
+ ReplayerEvents2["EventCast"] = "event-cast";
33210
+ ReplayerEvents2["CustomEvent"] = "custom-event";
33211
+ ReplayerEvents2["Flush"] = "flush";
33212
+ ReplayerEvents2["StateChange"] = "state-change";
33213
+ ReplayerEvents2["PlayBack"] = "play-back";
33214
+ ReplayerEvents2["Destroy"] = "destroy";
33215
+ return ReplayerEvents2;
33216
+ })(ReplayerEvents || {});
33217
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
33218
+ NodeType2[NodeType2["Document"] = 0] = "Document";
33219
+ NodeType2[NodeType2["DocumentType"] = 1] = "DocumentType";
33220
+ NodeType2[NodeType2["Element"] = 2] = "Element";
33221
+ NodeType2[NodeType2["Text"] = 3] = "Text";
33222
+ NodeType2[NodeType2["CDATA"] = 4] = "CDATA";
33223
+ NodeType2[NodeType2["Comment"] = 5] = "Comment";
33224
+ return NodeType2;
33225
+ })(NodeType || {});
33226
+
33227
+ //# sourceMappingURL=types.js.map
33228
+
33229
+
32195
33230
  /***/ }),
32196
33231
 
32197
33232
  /***/ "../../node_modules/@socket.io/component-emitter/lib/esm/index.js":
@@ -48645,6 +49680,7 @@ __webpack_require__.r(__webpack_exports__);
48645
49680
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE),
48646
49681
  /* harmony export */ ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_RPC_REQUEST_MESSAGE_ENCODING),
48647
49682
  /* harmony export */ ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_RPC_RESPONSE_MESSAGE),
49683
+ /* harmony export */ ATTR_MULTIPLAYER_SESSION_CLIENT_ID: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_SESSION_CLIENT_ID),
48648
49684
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_ID: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_SESSION_ID),
48649
49685
  /* harmony export */ ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION),
48650
49686
  /* harmony export */ ATTR_MULTIPLAYER_USER_HASH: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.ATTR_MULTIPLAYER_USER_HASH),
@@ -48659,10 +49695,14 @@ __webpack_require__.r(__webpack_exports__);
48659
49695
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_GRPC_URL),
48660
49696
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL),
48661
49697
  /* harmony export */ MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_URL),
49698
+ /* harmony export */ MULTIPLAYER_TRACE_CLIENT_ID_LENGTH: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH),
48662
49699
  /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX),
49700
+ /* harmony export */ MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_CONTINUOUS_SESSION_DEBUG_PREFIX),
48663
49701
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_DEBUG_PREFIX),
48664
49702
  /* harmony export */ MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH),
48665
49703
  /* harmony export */ MULTIPLAYER_TRACE_DOC_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_DOC_PREFIX),
49704
+ /* harmony export */ MULTIPLAYER_TRACE_PREFIX_MAP: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_PREFIX_MAP),
49705
+ /* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX),
48666
49706
  /* harmony export */ NavigationRecorder: () => (/* reexport safe */ _navigation__WEBPACK_IMPORTED_MODULE_6__.NavigationRecorder),
48667
49707
  /* harmony export */ SessionRecorderBrowserTraceExporter: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderBrowserTraceExporter),
48668
49708
  /* harmony export */ SessionRecorderIdGenerator: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderIdGenerator),