@multiplayer-app/session-recorder-browser 2.0.88 → 2.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7064,7 +7064,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
7064
7064
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
7065
7065
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
7066
7066
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
7067
- const PACKAGE_VERSION_EXPORT = "2.0.88" || 0;
7067
+ const PACKAGE_VERSION_EXPORT = "2.0.89" || 0;
7068
7068
  // Regex patterns for OpenTelemetry ignore URLs
7069
7069
  const OTEL_IGNORE_URLS = [
7070
7070
  // Traces endpoint
@@ -7463,24 +7463,43 @@ const isBrowserExtension = isBrowser && SESSION_RECORDER_INJECTED in globalObj;
7463
7463
  /* harmony export */ setupListeners: () => (/* binding */ setupListeners)
7464
7464
  /* harmony export */ });
7465
7465
  /* harmony import */ var _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./services/messaging.service */ "./src/services/messaging.service.ts");
7466
- /* 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");
7466
+ /* harmony import */ var _config_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./config/constants */ "./src/config/constants.ts");
7467
+ /* 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");
7468
+
7467
7469
 
7468
7470
 
7469
7471
  function setupListeners(sessionRecorder) {
7470
- // Send ready message with session info
7471
- _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('ready', {
7472
- session: sessionRecorder.session,
7473
- sessionState: sessionRecorder.sessionState,
7472
+ const announceState = () => {
7473
+ // Send continuous flag first so it is applied before the consumer reacts to
7474
+ // the 'ready' message (postMessage preserves delivery order).
7475
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('continuous-debugging', sessionRecorder.continuousRecording);
7476
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('ready', {
7477
+ session: sessionRecorder.session,
7478
+ sessionState: sessionRecorder.sessionState,
7479
+ // Lets the extension popup detect libs too old to support on-demand state
7480
+ // sync (the `get-state` request below).
7481
+ version: _config_constants__WEBPACK_IMPORTED_MODULE_1__.PACKAGE_VERSION_EXPORT,
7482
+ });
7483
+ };
7484
+ // Announce current state on load...
7485
+ announceState();
7486
+ // ...and whenever the extension asks (e.g. the popup was opened after the
7487
+ // recorder had already initialized, so it missed the initial announcement).
7488
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('get-state', () => {
7489
+ announceState();
7474
7490
  });
7475
7491
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('init', (payload) => {
7476
7492
  sessionRecorder.init(payload);
7477
7493
  });
7478
7494
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('start', (payload) => {
7479
- sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL, payload);
7495
+ sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__.SessionType.MANUAL, payload);
7480
7496
  });
7481
7497
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('end', (payload) => {
7482
7498
  sessionRecorder.stop(payload);
7483
7499
  });
7500
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('stop', (payload) => {
7501
+ sessionRecorder.stop(payload);
7502
+ });
7484
7503
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('pause', () => {
7485
7504
  sessionRecorder.pause();
7486
7505
  });
@@ -7492,7 +7511,7 @@ function setupListeners(sessionRecorder) {
7492
7511
  });
7493
7512
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('toggle-continuous-debugging', (payload) => {
7494
7513
  if (payload.enabled) {
7495
- sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.CONTINUOUS, payload.session);
7514
+ sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__.SessionType.CONTINUOUS, payload.session);
7496
7515
  }
7497
7516
  else {
7498
7517
  sessionRecorder.stop();
@@ -10346,6 +10365,10 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
10346
10365
  // Session ID and state are stored in sessionStorage (with fallback) to avoid multi-tab conflicts
10347
10366
  this._sessionId = null;
10348
10367
  this._sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL;
10368
+ // Guards against overlapping start() calls. `_checkOperation('start')` only
10369
+ // rejects once sessionState is `started`, but `_createSessionAndStart` is
10370
+ // async, so two rapid starts could both pass and create duplicate sessions.
10371
+ this._startInProgress = false;
10349
10372
  this._sessionState = null;
10350
10373
  this._session = null;
10351
10374
  this._sessionAttributes = null;
@@ -10552,7 +10575,10 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
10552
10575
  * @param session - the session to start
10553
10576
  */
10554
10577
  start(type = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL, session) {
10578
+ if (this._startInProgress)
10579
+ return;
10555
10580
  this._checkOperation('start');
10581
+ this._startInProgress = true;
10556
10582
  // If continuous recording is disabled, force plain mode
10557
10583
  if (type === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.CONTINUOUS &&
10558
10584
  !this._configs.showContinuousRecording) {
@@ -10934,6 +10960,7 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
10934
10960
  }
10935
10961
  }
10936
10962
  catch (error) {
10963
+ this._startInProgress = false;
10937
10964
  this.error = error.message;
10938
10965
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_5__.SessionState.stopped;
10939
10966
  if (this.continuousRecording) {
@@ -10946,6 +10973,7 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
10946
10973
  */
10947
10974
  _start() {
10948
10975
  var _a, _b;
10976
+ this._startInProgress = false;
10949
10977
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_5__.SessionState.started;
10950
10978
  // eslint-disable-next-line no-self-assign
10951
10979
  this.sessionType = this.sessionType;
package/dist/index.umd.js CHANGED
@@ -21497,7 +21497,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
21497
21497
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
21498
21498
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
21499
21499
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
21500
- const PACKAGE_VERSION_EXPORT = "2.0.88" || 0;
21500
+ const PACKAGE_VERSION_EXPORT = "2.0.89" || 0;
21501
21501
  // Regex patterns for OpenTelemetry ignore URLs
21502
21502
  const OTEL_IGNORE_URLS = [
21503
21503
  // Traces endpoint
@@ -21904,24 +21904,43 @@ const isBrowserExtension = isBrowser && SESSION_RECORDER_INJECTED in globalObj;
21904
21904
  /* harmony export */ setupListeners: () => (/* binding */ setupListeners)
21905
21905
  /* harmony export */ });
21906
21906
  /* harmony import */ var _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./services/messaging.service */ "./src/services/messaging.service.ts");
21907
- /* 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");
21907
+ /* harmony import */ var _config_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./config/constants */ "./src/config/constants.ts");
21908
+ /* 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");
21909
+
21908
21910
 
21909
21911
 
21910
21912
  function setupListeners(sessionRecorder) {
21911
- // Send ready message with session info
21912
- _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('ready', {
21913
- session: sessionRecorder.session,
21914
- sessionState: sessionRecorder.sessionState,
21913
+ const announceState = () => {
21914
+ // Send continuous flag first so it is applied before the consumer reacts to
21915
+ // the 'ready' message (postMessage preserves delivery order).
21916
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('continuous-debugging', sessionRecorder.continuousRecording);
21917
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].sendMessage('ready', {
21918
+ session: sessionRecorder.session,
21919
+ sessionState: sessionRecorder.sessionState,
21920
+ // Lets the extension popup detect libs too old to support on-demand state
21921
+ // sync (the `get-state` request below).
21922
+ version: _config_constants__WEBPACK_IMPORTED_MODULE_1__.PACKAGE_VERSION_EXPORT,
21923
+ });
21924
+ };
21925
+ // Announce current state on load...
21926
+ announceState();
21927
+ // ...and whenever the extension asks (e.g. the popup was opened after the
21928
+ // recorder had already initialized, so it missed the initial announcement).
21929
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('get-state', () => {
21930
+ announceState();
21915
21931
  });
21916
21932
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('init', (payload) => {
21917
21933
  sessionRecorder.init(payload);
21918
21934
  });
21919
21935
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('start', (payload) => {
21920
- sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL, payload);
21936
+ sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__.SessionType.MANUAL, payload);
21921
21937
  });
21922
21938
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('end', (payload) => {
21923
21939
  sessionRecorder.stop(payload);
21924
21940
  });
21941
+ _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('stop', (payload) => {
21942
+ sessionRecorder.stop(payload);
21943
+ });
21925
21944
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('pause', () => {
21926
21945
  sessionRecorder.pause();
21927
21946
  });
@@ -21933,7 +21952,7 @@ function setupListeners(sessionRecorder) {
21933
21952
  });
21934
21953
  _services_messaging_service__WEBPACK_IMPORTED_MODULE_0__["default"].on('toggle-continuous-debugging', (payload) => {
21935
21954
  if (payload.enabled) {
21936
- sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.CONTINUOUS, payload.session);
21955
+ sessionRecorder.start(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_2__.SessionType.CONTINUOUS, payload.session);
21937
21956
  }
21938
21957
  else {
21939
21958
  sessionRecorder.stop();
@@ -24807,6 +24826,10 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
24807
24826
  // Session ID and state are stored in sessionStorage (with fallback) to avoid multi-tab conflicts
24808
24827
  this._sessionId = null;
24809
24828
  this._sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL;
24829
+ // Guards against overlapping start() calls. `_checkOperation('start')` only
24830
+ // rejects once sessionState is `started`, but `_createSessionAndStart` is
24831
+ // async, so two rapid starts could both pass and create duplicate sessions.
24832
+ this._startInProgress = false;
24810
24833
  this._sessionState = null;
24811
24834
  this._session = null;
24812
24835
  this._sessionAttributes = null;
@@ -25013,7 +25036,10 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
25013
25036
  * @param session - the session to start
25014
25037
  */
25015
25038
  start(type = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL, session) {
25039
+ if (this._startInProgress)
25040
+ return;
25016
25041
  this._checkOperation('start');
25042
+ this._startInProgress = true;
25017
25043
  // If continuous recording is disabled, force plain mode
25018
25044
  if (type === _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.CONTINUOUS &&
25019
25045
  !this._configs.showContinuousRecording) {
@@ -25395,6 +25421,7 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
25395
25421
  }
25396
25422
  }
25397
25423
  catch (error) {
25424
+ this._startInProgress = false;
25398
25425
  this.error = error.message;
25399
25426
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_5__.SessionState.stopped;
25400
25427
  if (this.continuousRecording) {
@@ -25407,6 +25434,7 @@ class SessionRecorder extends _observable__WEBPACK_IMPORTED_MODULE_0__.Observabl
25407
25434
  */
25408
25435
  _start() {
25409
25436
  var _a, _b;
25437
+ this._startInProgress = false;
25410
25438
  this.sessionState = _types__WEBPACK_IMPORTED_MODULE_5__.SessionState.started;
25411
25439
  // eslint-disable-next-line no-self-assign
25412
25440
  this.sessionType = this.sessionType;
package/dist/listeners.js CHANGED
@@ -1,10 +1,25 @@
1
1
  import messagingService from './services/messaging.service';
2
- import { SessionType } from '@multiplayer-app/session-recorder-common';
2
+ import { PACKAGE_VERSION_EXPORT } from './config/constants';
3
+ import { SessionType, } from '@multiplayer-app/session-recorder-common';
3
4
  export function setupListeners(sessionRecorder) {
4
- // Send ready message with session info
5
- messagingService.sendMessage('ready', {
6
- session: sessionRecorder.session,
7
- sessionState: sessionRecorder.sessionState,
5
+ const announceState = () => {
6
+ // Send continuous flag first so it is applied before the consumer reacts to
7
+ // the 'ready' message (postMessage preserves delivery order).
8
+ messagingService.sendMessage('continuous-debugging', sessionRecorder.continuousRecording);
9
+ messagingService.sendMessage('ready', {
10
+ session: sessionRecorder.session,
11
+ sessionState: sessionRecorder.sessionState,
12
+ // Lets the extension popup detect libs too old to support on-demand state
13
+ // sync (the `get-state` request below).
14
+ version: PACKAGE_VERSION_EXPORT,
15
+ });
16
+ };
17
+ // Announce current state on load...
18
+ announceState();
19
+ // ...and whenever the extension asks (e.g. the popup was opened after the
20
+ // recorder had already initialized, so it missed the initial announcement).
21
+ messagingService.on('get-state', () => {
22
+ announceState();
8
23
  });
9
24
  messagingService.on('init', (payload) => {
10
25
  sessionRecorder.init(payload);
@@ -15,6 +30,9 @@ export function setupListeners(sessionRecorder) {
15
30
  messagingService.on('end', (payload) => {
16
31
  sessionRecorder.stop(payload);
17
32
  });
33
+ messagingService.on('stop', (payload) => {
34
+ sessionRecorder.stop(payload);
35
+ });
18
36
  messagingService.on('pause', () => {
19
37
  sessionRecorder.pause();
20
38
  });
@@ -27,6 +27,7 @@ export declare class SessionRecorder extends Observable<SessionRecorderEvents> i
27
27
  get sessionType(): SessionType;
28
28
  set sessionType(sessionType: SessionType);
29
29
  get continuousRecording(): boolean;
30
+ private _startInProgress;
30
31
  private _sessionState;
31
32
  get sessionState(): SessionState | null;
32
33
  set sessionState(state: SessionState | null);
@@ -115,6 +115,10 @@ export class SessionRecorder extends Observable {
115
115
  // Session ID and state are stored in sessionStorage (with fallback) to avoid multi-tab conflicts
116
116
  this._sessionId = null;
117
117
  this._sessionType = SessionType.MANUAL;
118
+ // Guards against overlapping start() calls. `_checkOperation('start')` only
119
+ // rejects once sessionState is `started`, but `_createSessionAndStart` is
120
+ // async, so two rapid starts could both pass and create duplicate sessions.
121
+ this._startInProgress = false;
118
122
  this._sessionState = null;
119
123
  this._session = null;
120
124
  this._sessionAttributes = null;
@@ -321,7 +325,10 @@ export class SessionRecorder extends Observable {
321
325
  * @param session - the session to start
322
326
  */
323
327
  start(type = SessionType.MANUAL, session) {
328
+ if (this._startInProgress)
329
+ return;
324
330
  this._checkOperation('start');
331
+ this._startInProgress = true;
325
332
  // If continuous recording is disabled, force plain mode
326
333
  if (type === SessionType.CONTINUOUS &&
327
334
  !this._configs.showContinuousRecording) {
@@ -703,6 +710,7 @@ export class SessionRecorder extends Observable {
703
710
  }
704
711
  }
705
712
  catch (error) {
713
+ this._startInProgress = false;
706
714
  this.error = error.message;
707
715
  this.sessionState = SessionState.stopped;
708
716
  if (this.continuousRecording) {
@@ -715,6 +723,7 @@ export class SessionRecorder extends Observable {
715
723
  */
716
724
  _start() {
717
725
  var _a, _b;
726
+ this._startInProgress = false;
718
727
  this.sessionState = SessionState.started;
719
728
  // eslint-disable-next-line no-self-assign
720
729
  this.sessionType = this.sessionType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplayer-app/session-recorder-browser",
3
- "version": "2.0.88",
3
+ "version": "2.0.89",
4
4
  "description": "Multiplayer Fullstack Session Recorder for Browser",
5
5
  "author": {
6
6
  "name": "Multiplayer Software, Inc.",
@@ -75,7 +75,7 @@
75
75
  "webpack-cli": "5.1.4"
76
76
  },
77
77
  "dependencies": {
78
- "@multiplayer-app/session-recorder-common": "2.0.88",
78
+ "@multiplayer-app/session-recorder-common": "2.0.89",
79
79
  "@opentelemetry/core": "2.0.1",
80
80
  "@opentelemetry/exporter-trace-otlp-http": "0.203.0",
81
81
  "@opentelemetry/instrumentation": "0.203.0",