@multiplayer-app/session-recorder-browser 1.2.30 → 1.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -339,88 +339,10 @@ activeSpan.setAttribute(SessionRecorder.ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO
339
339
 
340
340
  ## Session Recorder for Next.js
341
341
 
342
- ### Next.js 15.3+ (App Router) instrumentation-client.ts
342
+ Use the React wrapper for Next.js. It includes idiomatic Next.js guidance and helpers:
343
343
 
344
- On Next.js 15.3+ you can initialize the Session Recorder as early as possible with `src/instrumentation-client.ts|js`, which runs before hydration. You can also export `onRouterTransitionStart` to observe navigation. See the official docs: [instrumentation-client.ts](https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation-client).
345
-
346
- 1. Create `app/instrumentation-client.ts|js`:
347
-
348
- ```ts
349
- import SessionRecorder from '@multiplayer-app/session-recorder-browser'
350
-
351
- // Initialize as early as possible (before hydration)
352
- try {
353
- SessionRecorder.init({
354
- application: 'my-next-app',
355
- version: '1.0.0',
356
- environment: process.env.NEXT_PUBLIC_ENVIRONMENT ?? 'production',
357
- apiKey: process.env.NEXT_PUBLIC_MULTIPLAYER_API_KEY!,
358
- showWidget: true,
359
- // If your APIs are on different origins, add them so OTLP headers are propagated
360
- // format: string | RegExp | Array
361
- propagateTraceHeaderCorsUrls: [new RegExp('https://api.example.com', 'i')]
362
- })
363
- } catch (error) {
364
- // Keep instrumentation resilient
365
- console.warn('[SessionRecorder] init failed in instrumentation-client:', error)
366
- }
367
-
368
- // Optional: Next.js will call this when navigation begins
369
- export function onRouterTransitionStart(url: string, navigationType: 'push' | 'replace' | 'traverse') {
370
- try {
371
- SessionRecorder.navigation.record({
372
- path: url || '/',
373
- navigationType,
374
- framework: 'nextjs',
375
- source: 'instrumentation-client'
376
- })
377
- } catch (error) {
378
- console.warn('[SessionRecorder] navigation record failed:', error)
379
- }
380
- }
381
- ```
382
-
383
- ## Note
384
-
385
- If frontend domain doesn't match to backend one, set backend domain to `propagateTraceHeaderCorsUrls` parameter:
386
-
387
- ```javascript
388
- import SessionRecorder from '@multiplayer-app/session-recorder-browser'
389
- try {
390
- SessionRecorder.init({
391
- application: 'my-next-app',
392
- version: '1.0.0',
393
- environment: process.env.NEXT_PUBLIC_ENVIRONMENT ?? 'production',
394
- apiKey: process.env.NEXT_PUBLIC_MULTIPLAYER_API_KEY!,
395
- propagateTraceHeaderCorsUrls: new RegExp(`https://your.backend.api.domain`, 'i')
396
- })
397
- } catch (error) {
398
- console.warn('[SessionRecorder] init failed:', error)
399
- }
400
- ```
401
-
402
- If frontend sends api requests to two or more different domains put them to `propagateTraceHeaderCorsUrls` as array:
403
-
404
- ```javascript
405
- import SessionRecorder from '@multiplayer-app/session-recorder-browser'
406
-
407
- try {
408
- SessionRecorder.init({
409
- // ... other config ...
410
- propagateTraceHeaderCorsUrls: [
411
- new RegExp(`https://your.backend.api.domain`, 'i'),
412
- new RegExp(`https://another.backend.api.domain`, 'i')
413
- ]
414
- })
415
- } catch (error) {
416
- console.warn('[SessionRecorder] init failed:', error)
417
- }
418
- ```
419
-
420
- ### Framework notes
421
-
422
- - Next.js: initialize the browser SDK in a Client Component (see example in the browser README). Ensure it runs only in the browser.
423
- - CORS: when your frontend calls multiple API domains, set `propagateTraceHeaderCorsUrls` to match them so parent/child spans correlate across services.
344
+ - React package: [@multiplayer-app/session-recorder-react](../session-recorder-react/README.md)
345
+ - Next.js guide: [Next.js integration tips](../session-recorder-react/README.md#nextjs-integration-tips)
424
346
 
425
347
  ## Documentation
426
348
 
@@ -25094,7 +25094,7 @@ const DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE = 100000;
25094
25094
  const SESSION_RESPONSE = 'multiplayer-debug-session-response';
25095
25095
  const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
25096
25096
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
25097
- const PACKAGE_VERSION_EXPORT = "1.2.30" || 0;
25097
+ const PACKAGE_VERSION_EXPORT = "1.2.32" || 0;
25098
25098
  // Regex patterns for OpenTelemetry ignore URLs
25099
25099
  const OTEL_IGNORE_URLS = [
25100
25100
  // Traces endpoint
@@ -28328,13 +28328,13 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
28328
28328
  this._isStarted = false;
28329
28329
  this._isPaused = false;
28330
28330
  this._isInitialized = false;
28331
- this._error = '';
28332
28331
  this._recorderPlacement = '';
28333
- this._finalPopoverVisible = false;
28332
+ this._error = '';
28334
28333
  this._initialPopoverVisible = false;
28334
+ this._finalPopoverVisible = false;
28335
+ this._buttonState = _buttonStateConfigs__WEBPACK_IMPORTED_MODULE_6__.ButtonState.IDLE;
28335
28336
  this._continuousRecording = false;
28336
28337
  this._showContinuousRecording = true;
28337
- this._buttonState = _buttonStateConfigs__WEBPACK_IMPORTED_MODULE_6__.ButtonState.IDLE;
28338
28338
  this._widgetTextOverrides = _config__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_WIDGET_TEXT_CONFIG;
28339
28339
  this.commentTextarea = null;
28340
28340
  this.dragManager = null;
@@ -28360,6 +28360,21 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
28360
28360
  }
28361
28361
  }
28362
28362
  };
28363
+ this.recorderButton = document.createElement('button');
28364
+ this.initialPopover = document.createElement('div');
28365
+ this.finalPopover = document.createElement('div');
28366
+ this.overlay = document.createElement('div');
28367
+ this.toast = document.createElement('div');
28368
+ this.submitSessionDialog = document.createElement('div');
28369
+ this.uiManager = new _UIManager__WEBPACK_IMPORTED_MODULE_5__.UIManager(this.recorderButton, this.initialPopover, this.finalPopover, this.overlay, this.submitSessionDialog, this.toast, _config__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_WIDGET_TEXT_CONFIG, true);
28370
+ this.uiManager.setRecorderButtonProps();
28371
+ this.uiManager.setInitialPopoverProps();
28372
+ this.uiManager.setFinalPopoverProps();
28373
+ this.uiManager.setOverlayProps();
28374
+ this.uiManager.setSubmitSessionDialogProps();
28375
+ this.uiManager.setToastProps();
28376
+ this.commentTextarea = this.finalPopover.querySelector('.mp-session-debugger-popover-textarea');
28377
+ this.observeButtonDraggableMode();
28363
28378
  }
28364
28379
  updateState(state, continuousRecording) {
28365
28380
  this._continuousRecording = continuousRecording;
@@ -28430,32 +28445,9 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
28430
28445
  }
28431
28446
  });
28432
28447
  }
28433
- initUiManager() {
28434
- this.recorderButton = document.createElement('button');
28435
- this.initialPopover = document.createElement('div');
28436
- this.finalPopover = document.createElement('div');
28437
- this.overlay = document.createElement('div');
28438
- this.toast = document.createElement('div');
28439
- this.submitSessionDialog = document.createElement('div');
28440
- // Recreate UIManager with proper config
28441
- this.uiManager = new _UIManager__WEBPACK_IMPORTED_MODULE_5__.UIManager(this.recorderButton, this.initialPopover, this.finalPopover, this.overlay, this.submitSessionDialog, this.toast, this._widgetTextOverrides, this._showContinuousRecording);
28442
- // Re-initialize templates with new config
28443
- this.uiManager.setRecorderButtonProps();
28444
- this.uiManager.setInitialPopoverProps();
28445
- this.uiManager.setFinalPopoverProps();
28446
- this.uiManager.setOverlayProps();
28447
- this.uiManager.setSubmitSessionDialogProps();
28448
- this.uiManager.setToastProps();
28449
- this.commentTextarea = this.finalPopover.querySelector('.mp-session-debugger-popover-textarea');
28450
- this.observeButtonDraggableMode();
28451
- }
28452
28448
  init(options) {
28453
28449
  if (this._isInitialized)
28454
28450
  return;
28455
- // Safety guard: avoid DOM access in SSR/non-browser environments
28456
- if (typeof document === 'undefined') {
28457
- return;
28458
- }
28459
28451
  this._isInitialized = true;
28460
28452
  this.showRecorderButton = options.showWidget;
28461
28453
  this._showContinuousRecording = options.showContinuousRecording;
@@ -28463,7 +28455,15 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
28463
28455
  ...this._widgetTextOverrides,
28464
28456
  ...options.widgetTextOverrides,
28465
28457
  };
28466
- this.initUiManager();
28458
+ // Recreate UIManager with proper config
28459
+ this.uiManager = new _UIManager__WEBPACK_IMPORTED_MODULE_5__.UIManager(this.recorderButton, this.initialPopover, this.finalPopover, this.overlay, this.submitSessionDialog, this.toast, this._widgetTextOverrides, this._showContinuousRecording);
28460
+ // Re-initialize templates with new config
28461
+ this.uiManager.setRecorderButtonProps();
28462
+ this.uiManager.setInitialPopoverProps();
28463
+ this.uiManager.setFinalPopoverProps();
28464
+ this.uiManager.setOverlayProps();
28465
+ this.uiManager.setSubmitSessionDialogProps();
28466
+ this.uiManager.setToastProps();
28467
28467
  const elements = [this.toast];
28468
28468
  if (options.showWidget) {
28469
28469
  elements.push(this.recorderButton, this.initialPopover, this.finalPopover, this.submitSessionDialog);