@multiplayer-app/session-recorder-browser 1.2.28 → 1.2.30
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 +0 -60
- package/dist/browser/index.js +229 -173
- package/dist/browser/index.js.map +1 -1
- package/dist/exporters/index.js +1 -1
- package/dist/exporters/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +229 -173
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +229 -173
- package/dist/index.umd.js.map +1 -1
- package/dist/patch/fetch.js +79 -77
- package/dist/patch/fetch.js.map +1 -1
- package/dist/patch/xhr.js +75 -53
- package/dist/patch/xhr.js.map +1 -1
- package/dist/sessionRecorder.d.ts +2 -2
- package/dist/sessionRecorder.d.ts.map +1 -1
- package/dist/sessionRecorder.js +10 -5
- package/dist/sessionRecorder.js.map +1 -1
- package/dist/sessionWidget/index.d.ts +12 -11
- package/dist/sessionWidget/index.d.ts.map +1 -1
- package/dist/sessionWidget/index.js +27 -27
- package/dist/sessionWidget/index.js.map +1 -1
- package/dist/types/sessionRecorder.d.ts +1 -1
- package/dist/types/sessionRecorder.d.ts.map +1 -1
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +14 -4
- package/dist/utils/storage.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -339,66 +339,6 @@ activeSpan.setAttribute(SessionRecorder.ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO
|
|
|
339
339
|
|
|
340
340
|
## Session Recorder for Next.js
|
|
341
341
|
|
|
342
|
-
To integrate the MySessionRecorder component into your Next.js application, follow these steps:
|
|
343
|
-
|
|
344
|
-
- Create a new file (e.g., MySessionRecorder.js or MySessionRecorder.tsx) in your root directory or a components directory.
|
|
345
|
-
|
|
346
|
-
- Import the component
|
|
347
|
-
|
|
348
|
-
In the newly created file, add the following code:
|
|
349
|
-
|
|
350
|
-
```javascript
|
|
351
|
-
'use client' // Mark as Client Component
|
|
352
|
-
import { useEffect } from 'react'
|
|
353
|
-
import SessionRecorder from '@multiplayer-app/session-recorder-browser'
|
|
354
|
-
|
|
355
|
-
export default function MySessionRecorder() {
|
|
356
|
-
useEffect(() => {
|
|
357
|
-
if (typeof window !== 'undefined') {
|
|
358
|
-
SessionRecorder.init({
|
|
359
|
-
version: '{YOUR_APPLICATION_VERSION}',
|
|
360
|
-
application: '{YOUR_APPLICATION_NAME}',
|
|
361
|
-
environment: '{YOUR_APPLICATION_ENVIRONMENT}',
|
|
362
|
-
apiKey: '{YOUR_API_KEY}',
|
|
363
|
-
recordCanvas: true, // Enable canvas recording
|
|
364
|
-
masking: {
|
|
365
|
-
maskAllInputs: true,
|
|
366
|
-
maskInputOptions: {
|
|
367
|
-
password: true,
|
|
368
|
-
email: false,
|
|
369
|
-
tel: false
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
})
|
|
373
|
-
|
|
374
|
-
SessionRecorder.setSessionAttributes({
|
|
375
|
-
userId: '{userId}',
|
|
376
|
-
userName: '{userName}'
|
|
377
|
-
})
|
|
378
|
-
}
|
|
379
|
-
}, [])
|
|
380
|
-
|
|
381
|
-
return null // No UI output needed
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
Replace the placeholders with the actual information.
|
|
386
|
-
|
|
387
|
-
Now, you can use the MySessionRecorder component in your application by adding it to your desired page or layout file:
|
|
388
|
-
|
|
389
|
-
```javascript
|
|
390
|
-
import MySessionRecorder from './MySessionRecorder' // Adjust the path as necessary
|
|
391
|
-
|
|
392
|
-
export default function MyApp() {
|
|
393
|
-
return (
|
|
394
|
-
<>
|
|
395
|
-
<MySessionRecorder />
|
|
396
|
-
{/* Other components */}
|
|
397
|
-
</>
|
|
398
|
-
)
|
|
399
|
-
}
|
|
400
|
-
```
|
|
401
|
-
|
|
402
342
|
### Next.js 15.3+ (App Router) — instrumentation-client.ts
|
|
403
343
|
|
|
404
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).
|
package/dist/browser/index.js
CHANGED
|
@@ -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.
|
|
25097
|
+
const PACKAGE_VERSION_EXPORT = "1.2.30" || 0;
|
|
25098
25098
|
// Regex patterns for OpenTelemetry ignore URLs
|
|
25099
25099
|
const OTEL_IGNORE_URLS = [
|
|
25100
25100
|
// Traces endpoint
|
|
@@ -26369,91 +26369,93 @@ function _headersInitToObject(headersInit) {
|
|
|
26369
26369
|
}
|
|
26370
26370
|
return result;
|
|
26371
26371
|
}
|
|
26372
|
-
|
|
26373
|
-
|
|
26374
|
-
|
|
26375
|
-
|
|
26376
|
-
|
|
26377
|
-
|
|
26378
|
-
|
|
26379
|
-
|
|
26380
|
-
|
|
26381
|
-
|
|
26382
|
-
|
|
26383
|
-
|
|
26384
|
-
|
|
26385
|
-
|
|
26386
|
-
|
|
26387
|
-
|
|
26388
|
-
|
|
26389
|
-
|
|
26390
|
-
|
|
26391
|
-
|
|
26392
|
-
}
|
|
26393
|
-
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordRequestHeaders) {
|
|
26394
|
-
if (requestForMetadata) {
|
|
26395
|
-
networkRequest.requestHeaders = _headersToObject(requestForMetadata.headers);
|
|
26396
|
-
}
|
|
26397
|
-
else if (inputIsRequest) {
|
|
26398
|
-
networkRequest.requestHeaders = _headersToObject(input.headers);
|
|
26399
|
-
}
|
|
26400
|
-
else {
|
|
26401
|
-
networkRequest.requestHeaders = _headersInitToObject(init === null || init === void 0 ? void 0 : init.headers);
|
|
26402
|
-
}
|
|
26403
|
-
}
|
|
26404
|
-
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
|
|
26405
|
-
// Prefer reading from the safely constructed Request; else fallback to init.body
|
|
26406
|
-
const urlStr = inputIsRequest
|
|
26407
|
-
? input.url
|
|
26408
|
-
: (typeof input === 'string' || input instanceof URL ? String(input) : '');
|
|
26409
|
-
const candidateBody = requestForMetadata
|
|
26410
|
-
? requestForMetadata.body
|
|
26411
|
-
: (inputIsRequest ? init === null || init === void 0 ? void 0 : init.body : init === null || init === void 0 ? void 0 : init.body);
|
|
26412
|
-
if (!(0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(candidateBody)) {
|
|
26413
|
-
const requestBody = _tryReadFetchBody({
|
|
26414
|
-
body: candidateBody,
|
|
26415
|
-
url: urlStr,
|
|
26416
|
-
});
|
|
26417
|
-
if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) &&
|
|
26418
|
-
new Blob([requestBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
|
|
26419
|
-
networkRequest.requestBody = requestBody;
|
|
26372
|
+
if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
|
|
26373
|
+
// Store original fetch
|
|
26374
|
+
const originalFetch = window.fetch;
|
|
26375
|
+
// Override fetch
|
|
26376
|
+
window.fetch = async function (input,
|
|
26377
|
+
// eslint-disable-next-line
|
|
26378
|
+
init) {
|
|
26379
|
+
const networkRequest = {};
|
|
26380
|
+
// Capture request data
|
|
26381
|
+
const inputIsRequest = typeof Request !== 'undefined' && input instanceof Request;
|
|
26382
|
+
const safeToConstructRequest = !inputIsRequest || !input.bodyUsed;
|
|
26383
|
+
// Only construct a new Request when it's safe (i.e., body not already used)
|
|
26384
|
+
let requestForMetadata = null;
|
|
26385
|
+
if (safeToConstructRequest) {
|
|
26386
|
+
try {
|
|
26387
|
+
requestForMetadata = new Request(input, init);
|
|
26388
|
+
}
|
|
26389
|
+
catch (_a) {
|
|
26390
|
+
// If construction fails for any reason, fall back to using available data
|
|
26391
|
+
requestForMetadata = null;
|
|
26420
26392
|
}
|
|
26421
26393
|
}
|
|
26422
|
-
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26394
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordRequestHeaders) {
|
|
26395
|
+
if (requestForMetadata) {
|
|
26396
|
+
networkRequest.requestHeaders = _headersToObject(requestForMetadata.headers);
|
|
26397
|
+
}
|
|
26398
|
+
else if (inputIsRequest) {
|
|
26399
|
+
networkRequest.requestHeaders = _headersToObject(input.headers);
|
|
26400
|
+
}
|
|
26401
|
+
else {
|
|
26402
|
+
networkRequest.requestHeaders = _headersInitToObject(init === null || init === void 0 ? void 0 : init.headers);
|
|
26403
|
+
}
|
|
26429
26404
|
}
|
|
26430
26405
|
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
|
|
26431
|
-
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
|
|
26406
|
+
// Prefer reading from the safely constructed Request; else fallback to init.body
|
|
26407
|
+
const urlStr = inputIsRequest
|
|
26408
|
+
? input.url
|
|
26409
|
+
: (typeof input === 'string' || input instanceof URL ? String(input) : '');
|
|
26410
|
+
const candidateBody = requestForMetadata
|
|
26411
|
+
? requestForMetadata.body
|
|
26412
|
+
: (inputIsRequest ? init === null || init === void 0 ? void 0 : init.body : init === null || init === void 0 ? void 0 : init.body);
|
|
26413
|
+
if (!(0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(candidateBody)) {
|
|
26414
|
+
const requestBody = _tryReadFetchBody({
|
|
26415
|
+
body: candidateBody,
|
|
26416
|
+
url: urlStr,
|
|
26417
|
+
});
|
|
26418
|
+
if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) &&
|
|
26419
|
+
new Blob([requestBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
|
|
26420
|
+
networkRequest.requestBody = requestBody;
|
|
26421
|
+
}
|
|
26435
26422
|
}
|
|
26436
26423
|
}
|
|
26437
|
-
|
|
26438
|
-
|
|
26439
|
-
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26443
|
-
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26424
|
+
try {
|
|
26425
|
+
// Make the actual fetch request
|
|
26426
|
+
const response = await originalFetch(input, init);
|
|
26427
|
+
// Capture response data
|
|
26428
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordResponseHeaders) {
|
|
26429
|
+
networkRequest.responseHeaders = _headersToObject(response.headers);
|
|
26430
|
+
}
|
|
26431
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
|
|
26432
|
+
const responseBody = await _tryReadResponseBody(response);
|
|
26433
|
+
if ((responseBody === null || responseBody === void 0 ? void 0 : responseBody.length) &&
|
|
26434
|
+
new Blob([responseBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
|
|
26435
|
+
networkRequest.responseBody = responseBody;
|
|
26436
|
+
}
|
|
26437
|
+
}
|
|
26438
|
+
// Attach network request data to the response for later access
|
|
26447
26439
|
// @ts-ignore
|
|
26448
|
-
|
|
26440
|
+
response.networkRequest = networkRequest;
|
|
26441
|
+
return response;
|
|
26449
26442
|
}
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
//
|
|
26454
|
-
|
|
26455
|
-
|
|
26456
|
-
|
|
26443
|
+
catch (error) {
|
|
26444
|
+
// Even if the fetch fails, we can still capture the request data
|
|
26445
|
+
// Attach captured request data to the thrown error for downstream handling
|
|
26446
|
+
// @ts-ignore
|
|
26447
|
+
if (error && typeof error === 'object') {
|
|
26448
|
+
// @ts-ignore
|
|
26449
|
+
error.networkRequest = networkRequest;
|
|
26450
|
+
}
|
|
26451
|
+
throw error;
|
|
26452
|
+
}
|
|
26453
|
+
};
|
|
26454
|
+
// Preserve the original fetch function's properties
|
|
26455
|
+
Object.setPrototypeOf(window.fetch, originalFetch);
|
|
26456
|
+
Object.defineProperty(window.fetch, 'name', { value: 'fetch' });
|
|
26457
|
+
Object.defineProperty(window.fetch, 'length', { value: originalFetch.length });
|
|
26458
|
+
}
|
|
26457
26459
|
|
|
26458
26460
|
|
|
26459
26461
|
/***/ }),
|
|
@@ -26518,64 +26520,86 @@ function _tryReadXHRBody({ body, url, }) {
|
|
|
26518
26520
|
}
|
|
26519
26521
|
return `[XHR] Cannot read body of type ${toString.call(body)}`;
|
|
26520
26522
|
}
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26525
|
-
|
|
26523
|
+
function _isWithinPayloadLimit(payload) {
|
|
26524
|
+
try {
|
|
26525
|
+
if (typeof Blob !== 'undefined') {
|
|
26526
|
+
return new Blob([payload]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize;
|
|
26527
|
+
}
|
|
26528
|
+
}
|
|
26529
|
+
catch (_a) {
|
|
26530
|
+
// ignore and fallback to string length
|
|
26531
|
+
}
|
|
26532
|
+
return payload.length <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize;
|
|
26533
|
+
}
|
|
26534
|
+
// Only patch XHR in environments where it exists (avoid SSR/Node)
|
|
26535
|
+
if (typeof XMLHttpRequest !== 'undefined') {
|
|
26536
|
+
(function (xhr) {
|
|
26537
|
+
// Idempotency guard: avoid double-patching
|
|
26526
26538
|
// @ts-ignore
|
|
26527
|
-
|
|
26528
|
-
|
|
26529
|
-
xhr.setRequestHeader = (header, value) => {
|
|
26530
|
-
requestHeaders[header] = value;
|
|
26531
|
-
return originalSetRequestHeader(header, value);
|
|
26532
|
-
};
|
|
26533
|
-
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordRequestHeaders) {
|
|
26534
|
-
networkRequest.requestHeaders = requestHeaders;
|
|
26539
|
+
if (xhr.__mp_session_recorder_patched__) {
|
|
26540
|
+
return;
|
|
26535
26541
|
}
|
|
26536
|
-
|
|
26537
|
-
|
|
26538
|
-
|
|
26539
|
-
|
|
26540
|
-
|
|
26541
|
-
|
|
26542
|
-
|
|
26543
|
-
}
|
|
26544
|
-
}
|
|
26545
|
-
return originalSend(body);
|
|
26546
|
-
};
|
|
26547
|
-
xhr.addEventListener('readystatechange', () => {
|
|
26548
|
-
if (xhr.readyState !== xhr.DONE) {
|
|
26549
|
-
return;
|
|
26550
|
-
}
|
|
26542
|
+
// @ts-ignore
|
|
26543
|
+
;
|
|
26544
|
+
xhr.__mp_session_recorder_patched__ = true;
|
|
26545
|
+
const originalOpen = xhr.open;
|
|
26546
|
+
xhr.open = function (method, url, async = true, username, password) {
|
|
26547
|
+
const xhr = this;
|
|
26548
|
+
const networkRequest = {};
|
|
26551
26549
|
// @ts-ignore
|
|
26552
|
-
const
|
|
26553
|
-
const
|
|
26554
|
-
|
|
26555
|
-
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
|
|
26560
|
-
|
|
26550
|
+
const requestHeaders = {};
|
|
26551
|
+
const originalSetRequestHeader = xhr.setRequestHeader.bind(xhr);
|
|
26552
|
+
xhr.setRequestHeader = (header, value) => {
|
|
26553
|
+
requestHeaders[header] = value;
|
|
26554
|
+
return originalSetRequestHeader(header, value);
|
|
26555
|
+
};
|
|
26556
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordRequestHeaders) {
|
|
26557
|
+
networkRequest.requestHeaders = requestHeaders;
|
|
26558
|
+
}
|
|
26559
|
+
const originalSend = xhr.send.bind(xhr);
|
|
26560
|
+
xhr.send = (body) => {
|
|
26561
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
|
|
26562
|
+
const requestBody = _tryReadXHRBody({ body, url });
|
|
26563
|
+
if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length)
|
|
26564
|
+
&& _isWithinPayloadLimit(requestBody)) {
|
|
26565
|
+
networkRequest.requestBody = requestBody;
|
|
26566
|
+
}
|
|
26561
26567
|
}
|
|
26562
|
-
|
|
26563
|
-
|
|
26564
|
-
|
|
26565
|
-
|
|
26566
|
-
|
|
26567
|
-
const responseBody = _tryReadXHRBody({ body: xhr.response, url });
|
|
26568
|
-
if ((responseBody === null || responseBody === void 0 ? void 0 : responseBody.length)
|
|
26569
|
-
&& new Blob([responseBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
|
|
26570
|
-
networkRequest.responseBody = responseBody;
|
|
26568
|
+
return originalSend(body);
|
|
26569
|
+
};
|
|
26570
|
+
xhr.addEventListener('readystatechange', () => {
|
|
26571
|
+
if (xhr.readyState !== xhr.DONE) {
|
|
26572
|
+
return;
|
|
26571
26573
|
}
|
|
26572
|
-
|
|
26573
|
-
|
|
26574
|
-
|
|
26575
|
-
|
|
26576
|
-
|
|
26577
|
-
|
|
26578
|
-
|
|
26574
|
+
// @ts-ignore
|
|
26575
|
+
const responseHeaders = {};
|
|
26576
|
+
const rawHeaders = xhr.getAllResponseHeaders();
|
|
26577
|
+
const headers = rawHeaders.trim().split(/[\r\n]+/);
|
|
26578
|
+
headers.forEach((line) => {
|
|
26579
|
+
const parts = line.split(': ');
|
|
26580
|
+
const header = parts.shift();
|
|
26581
|
+
const value = parts.join(': ');
|
|
26582
|
+
if (header) {
|
|
26583
|
+
responseHeaders[header] = value;
|
|
26584
|
+
}
|
|
26585
|
+
});
|
|
26586
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.recordResponseHeaders) {
|
|
26587
|
+
networkRequest.responseHeaders = responseHeaders;
|
|
26588
|
+
}
|
|
26589
|
+
if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
|
|
26590
|
+
const responseBody = _tryReadXHRBody({ body: xhr.response, url });
|
|
26591
|
+
if ((responseBody === null || responseBody === void 0 ? void 0 : responseBody.length)
|
|
26592
|
+
&& _isWithinPayloadLimit(responseBody)) {
|
|
26593
|
+
networkRequest.responseBody = responseBody;
|
|
26594
|
+
}
|
|
26595
|
+
}
|
|
26596
|
+
});
|
|
26597
|
+
// @ts-ignore
|
|
26598
|
+
xhr.networkRequest = networkRequest;
|
|
26599
|
+
originalOpen.call(xhr, method, url, async, username, password);
|
|
26600
|
+
};
|
|
26601
|
+
})(XMLHttpRequest.prototype);
|
|
26602
|
+
}
|
|
26579
26603
|
|
|
26580
26604
|
|
|
26581
26605
|
/***/ }),
|
|
@@ -27265,7 +27289,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
|
|
|
27265
27289
|
*
|
|
27266
27290
|
* This element is used to control the start/stop recording functionality in the session widget UI.
|
|
27267
27291
|
*
|
|
27268
|
-
* @returns {HTMLButtonElement} The recorder button element from the session widget.
|
|
27292
|
+
* @returns {HTMLButtonElement | null} The recorder button element from the session widget.
|
|
27269
27293
|
*/
|
|
27270
27294
|
get sessionWidgetButtonElement() {
|
|
27271
27295
|
return this._sessionWidget.recorderButton;
|
|
@@ -27293,10 +27317,12 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
|
|
|
27293
27317
|
* Error message getter and setter
|
|
27294
27318
|
*/
|
|
27295
27319
|
this._error = '';
|
|
27296
|
-
|
|
27297
|
-
const
|
|
27298
|
-
const
|
|
27299
|
-
const
|
|
27320
|
+
// Safety: avoid accessing storage in SSR/non-browser environments
|
|
27321
|
+
const isBrowser = typeof window !== 'undefined';
|
|
27322
|
+
const sessionLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_4__.SESSION_PROP_NAME, true) : null;
|
|
27323
|
+
const sessionIdLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_4__.SESSION_ID_PROP_NAME) : null;
|
|
27324
|
+
const sessionStateLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_4__.SESSION_STATE_PROP_NAME) : null;
|
|
27325
|
+
const sessionTypeLocal = isBrowser ? (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getStoredItem)(_config__WEBPACK_IMPORTED_MODULE_4__.SESSION_TYPE_PROP_NAME) : null;
|
|
27300
27326
|
if ((0,_utils__WEBPACK_IMPORTED_MODULE_2__.isSessionActive)(sessionLocal, sessionTypeLocal)) {
|
|
27301
27327
|
this.session = sessionLocal;
|
|
27302
27328
|
this.sessionId = sessionIdLocal;
|
|
@@ -27319,6 +27345,9 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
|
|
|
27319
27345
|
* @param configs - custom configurations for session debugger
|
|
27320
27346
|
*/
|
|
27321
27347
|
init(configs) {
|
|
27348
|
+
if (typeof window === 'undefined') {
|
|
27349
|
+
return;
|
|
27350
|
+
}
|
|
27322
27351
|
this._configs = (0,_config__WEBPACK_IMPORTED_MODULE_4__.getSessionRecorderConfig)({ ...this._configs, ...configs });
|
|
27323
27352
|
this._isInitialized = true;
|
|
27324
27353
|
this._checkOperation('init');
|
|
@@ -28299,13 +28328,13 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
|
|
|
28299
28328
|
this._isStarted = false;
|
|
28300
28329
|
this._isPaused = false;
|
|
28301
28330
|
this._isInitialized = false;
|
|
28302
|
-
this._recorderPlacement = '';
|
|
28303
28331
|
this._error = '';
|
|
28304
|
-
this.
|
|
28332
|
+
this._recorderPlacement = '';
|
|
28305
28333
|
this._finalPopoverVisible = false;
|
|
28306
|
-
this.
|
|
28334
|
+
this._initialPopoverVisible = false;
|
|
28307
28335
|
this._continuousRecording = false;
|
|
28308
28336
|
this._showContinuousRecording = true;
|
|
28337
|
+
this._buttonState = _buttonStateConfigs__WEBPACK_IMPORTED_MODULE_6__.ButtonState.IDLE;
|
|
28309
28338
|
this._widgetTextOverrides = _config__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_WIDGET_TEXT_CONFIG;
|
|
28310
28339
|
this.commentTextarea = null;
|
|
28311
28340
|
this.dragManager = null;
|
|
@@ -28331,21 +28360,6 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
|
|
|
28331
28360
|
}
|
|
28332
28361
|
}
|
|
28333
28362
|
};
|
|
28334
|
-
this.recorderButton = document.createElement('button');
|
|
28335
|
-
this.initialPopover = document.createElement('div');
|
|
28336
|
-
this.finalPopover = document.createElement('div');
|
|
28337
|
-
this.overlay = document.createElement('div');
|
|
28338
|
-
this.toast = document.createElement('div');
|
|
28339
|
-
this.submitSessionDialog = document.createElement('div');
|
|
28340
|
-
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);
|
|
28341
|
-
this.uiManager.setRecorderButtonProps();
|
|
28342
|
-
this.uiManager.setInitialPopoverProps();
|
|
28343
|
-
this.uiManager.setFinalPopoverProps();
|
|
28344
|
-
this.uiManager.setOverlayProps();
|
|
28345
|
-
this.uiManager.setSubmitSessionDialogProps();
|
|
28346
|
-
this.uiManager.setToastProps();
|
|
28347
|
-
this.commentTextarea = this.finalPopover.querySelector('.mp-session-debugger-popover-textarea');
|
|
28348
|
-
this.observeButtonDraggableMode();
|
|
28349
28363
|
}
|
|
28350
28364
|
updateState(state, continuousRecording) {
|
|
28351
28365
|
this._continuousRecording = continuousRecording;
|
|
@@ -28416,9 +28430,32 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
|
|
|
28416
28430
|
}
|
|
28417
28431
|
});
|
|
28418
28432
|
}
|
|
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
|
+
}
|
|
28419
28452
|
init(options) {
|
|
28420
28453
|
if (this._isInitialized)
|
|
28421
28454
|
return;
|
|
28455
|
+
// Safety guard: avoid DOM access in SSR/non-browser environments
|
|
28456
|
+
if (typeof document === 'undefined') {
|
|
28457
|
+
return;
|
|
28458
|
+
}
|
|
28422
28459
|
this._isInitialized = true;
|
|
28423
28460
|
this.showRecorderButton = options.showWidget;
|
|
28424
28461
|
this._showContinuousRecording = options.showContinuousRecording;
|
|
@@ -28426,15 +28463,7 @@ class SessionWidget extends lib0_observable__WEBPACK_IMPORTED_MODULE_7__.Observa
|
|
|
28426
28463
|
...this._widgetTextOverrides,
|
|
28427
28464
|
...options.widgetTextOverrides,
|
|
28428
28465
|
};
|
|
28429
|
-
|
|
28430
|
-
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);
|
|
28431
|
-
// Re-initialize templates with new config
|
|
28432
|
-
this.uiManager.setRecorderButtonProps();
|
|
28433
|
-
this.uiManager.setInitialPopoverProps();
|
|
28434
|
-
this.uiManager.setFinalPopoverProps();
|
|
28435
|
-
this.uiManager.setOverlayProps();
|
|
28436
|
-
this.uiManager.setSubmitSessionDialogProps();
|
|
28437
|
-
this.uiManager.setToastProps();
|
|
28466
|
+
this.initUiManager();
|
|
28438
28467
|
const elements = [this.toast];
|
|
28439
28468
|
if (options.showWidget) {
|
|
28440
28469
|
elements.push(this.recorderButton, this.initialPopover, this.finalPopover, this.submitSessionDialog);
|
|
@@ -29574,20 +29603,30 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
29574
29603
|
/**
|
|
29575
29604
|
* LocalStorage utility functions
|
|
29576
29605
|
*/
|
|
29606
|
+
const hasLocalStorage = typeof window !== 'undefined' && !!window.localStorage;
|
|
29577
29607
|
const getStoredItem = (key, parse) => {
|
|
29578
|
-
|
|
29608
|
+
if (!hasLocalStorage) {
|
|
29609
|
+
return parse ? null : null;
|
|
29610
|
+
}
|
|
29611
|
+
const item = window.localStorage.getItem(key);
|
|
29579
29612
|
return parse ? (item ? JSON.parse(item) : null) : item;
|
|
29580
29613
|
};
|
|
29581
29614
|
const setStoredItem = (key, value) => {
|
|
29615
|
+
if (!hasLocalStorage) {
|
|
29616
|
+
return;
|
|
29617
|
+
}
|
|
29582
29618
|
if (value === null || value === undefined) {
|
|
29583
|
-
localStorage
|
|
29619
|
+
window.localStorage.removeItem(key);
|
|
29584
29620
|
}
|
|
29585
29621
|
else {
|
|
29586
|
-
localStorage
|
|
29622
|
+
window.localStorage.setItem(key, typeof value === 'string' ? value : JSON.stringify(value));
|
|
29587
29623
|
}
|
|
29588
29624
|
};
|
|
29589
29625
|
const removeStoredItem = (key) => {
|
|
29590
|
-
|
|
29626
|
+
if (!hasLocalStorage) {
|
|
29627
|
+
return;
|
|
29628
|
+
}
|
|
29629
|
+
window.localStorage.removeItem(key);
|
|
29591
29630
|
};
|
|
29592
29631
|
|
|
29593
29632
|
|
|
@@ -49234,12 +49273,29 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
49234
49273
|
|
|
49235
49274
|
|
|
49236
49275
|
|
|
49237
|
-
|
|
49238
|
-
|
|
49239
|
-
|
|
49240
|
-
|
|
49241
|
-
|
|
49242
|
-
(
|
|
49276
|
+
// Create or reuse a single global instance, but be safe in non-browser environments
|
|
49277
|
+
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
49278
|
+
// Prefer globalThis when available; fall back to window in browsers
|
|
49279
|
+
const globalObj = typeof globalThis !== 'undefined'
|
|
49280
|
+
? globalThis
|
|
49281
|
+
: (isBrowser ? window : {});
|
|
49282
|
+
let SessionRecorderInstance;
|
|
49283
|
+
if (isBrowser) {
|
|
49284
|
+
// Reuse existing instance if already injected (e.g., by an extension)
|
|
49285
|
+
const existing = globalObj['SessionRecorder'];
|
|
49286
|
+
SessionRecorderInstance = existing !== null && existing !== void 0 ? existing : new _sessionRecorder__WEBPACK_IMPORTED_MODULE_3__.SessionRecorder();
|
|
49287
|
+
// Attach to the global object for reuse across bundles/loads
|
|
49288
|
+
globalObj['SessionRecorder'] = SessionRecorderInstance;
|
|
49289
|
+
globalObj['__SESSION_RECORDER_LOADED'] = true;
|
|
49290
|
+
// Ensure listeners are set up only once
|
|
49291
|
+
if (!globalObj['__SESSION_RECORDER_LISTENERS_SETUP__']) {
|
|
49292
|
+
(0,_listeners__WEBPACK_IMPORTED_MODULE_1__.setupListeners)(SessionRecorderInstance);
|
|
49293
|
+
globalObj['__SESSION_RECORDER_LISTENERS_SETUP__'] = true;
|
|
49294
|
+
}
|
|
49295
|
+
}
|
|
49296
|
+
else {
|
|
49297
|
+
// SSR / non-DOM environments: create an instance but don't touch globals or listeners
|
|
49298
|
+
SessionRecorderInstance = new _sessionRecorder__WEBPACK_IMPORTED_MODULE_3__.SessionRecorder();
|
|
49243
49299
|
}
|
|
49244
49300
|
|
|
49245
49301
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SessionRecorderInstance);
|