@multiplayer-app/session-recorder-browser 1.3.14 → 1.3.16

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.
@@ -25051,7 +25051,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
25051
25051
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
25052
25052
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
25053
25053
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
25054
- const PACKAGE_VERSION_EXPORT = "1.3.14" || 0;
25054
+ const PACKAGE_VERSION_EXPORT = "1.3.16" || 0;
25055
25055
  // Regex patterns for OpenTelemetry ignore URLs
25056
25056
  const OTEL_IGNORE_URLS = [
25057
25057
  // Traces endpoint
@@ -26280,7 +26280,7 @@ __webpack_require__.r(__webpack_exports__);
26280
26280
 
26281
26281
 
26282
26282
 
26283
- function _tryReadFetchBody({ body, url, }) {
26283
+ function _tryReadFetchBody({ body, url }) {
26284
26284
  if ((0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(body)) {
26285
26285
  return null;
26286
26286
  }
@@ -26303,32 +26303,82 @@ function _tryReadFetchBody({ body, url, }) {
26303
26303
  }
26304
26304
  return `[Fetch] Cannot read body of type ${toString.call(body)}`;
26305
26305
  }
26306
+ /**
26307
+ * Detects if a response is a streaming response that should NOT have its body read.
26308
+ * Reading the body of streaming responses (SSE, chunked streams, etc.) will either:
26309
+ * - Block forever (SSE streams never end)
26310
+ * - Corrupt the stream for the actual consumer
26311
+ */
26312
+ function _isStreamingResponse(response) {
26313
+ var _a, _b, _c;
26314
+ const contentType = (_b = (_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
26315
+ // SSE - Server-Sent Events (infinite stream)
26316
+ if (contentType.includes('text/event-stream')) {
26317
+ return true;
26318
+ }
26319
+ // Binary streams that are typically long-running
26320
+ if (contentType.includes('application/octet-stream')) {
26321
+ return true;
26322
+ }
26323
+ // NDJSON streaming (newline-delimited JSON, common in streaming APIs)
26324
+ if (contentType.includes('application/x-ndjson') || contentType.includes('application/ndjson')) {
26325
+ return true;
26326
+ }
26327
+ // gRPC-web streaming
26328
+ if (contentType.includes('application/grpc')) {
26329
+ return true;
26330
+ }
26331
+ // Check for chunked transfer encoding (often indicates streaming)
26332
+ const transferEncoding = (_c = response.headers.get('transfer-encoding')) === null || _c === void 0 ? void 0 : _c.toLowerCase();
26333
+ if (transferEncoding === null || transferEncoding === void 0 ? void 0 : transferEncoding.includes('chunked')) {
26334
+ // Chunked alone isn't definitive, but combined with no content-length = streaming
26335
+ const contentLength = response.headers.get('content-length');
26336
+ if (!contentLength) {
26337
+ return true;
26338
+ }
26339
+ }
26340
+ return false;
26341
+ }
26342
+ /**
26343
+ * Safely reads response body for non-streaming responses.
26344
+ * Returns null for streaming responses to avoid blocking/corruption.
26345
+ */
26306
26346
  async function _tryReadResponseBody(response) {
26307
26347
  var _a, _b;
26348
+ // CRITICAL: Never attempt to read streaming response bodies
26349
+ if (_isStreamingResponse(response)) {
26350
+ return null;
26351
+ }
26308
26352
  try {
26309
- // Clone the response to avoid consuming the original stream
26353
+ // Clone the response to avoid consuming the original
26310
26354
  const clonedResponse = response.clone();
26311
- // Try different methods to read the body
26312
- if ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) {
26355
+ const contentType = (_b = (_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
26356
+ // Check content-length to avoid reading massive responses
26357
+ const contentLength = response.headers.get('content-length');
26358
+ if (contentLength) {
26359
+ const length = parseInt(contentLength, 10);
26360
+ if (!isNaN(length) && length > _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
26361
+ return `[Fetch] Response too large (${length} bytes)`;
26362
+ }
26363
+ }
26364
+ if (contentType.includes('application/json')) {
26313
26365
  const json = await clonedResponse.json();
26314
26366
  return JSON.stringify(json);
26315
26367
  }
26316
- else if ((_b = response.headers.get('content-type')) === null || _b === void 0 ? void 0 : _b.includes('text/')) {
26368
+ if (contentType.includes('text/')) {
26317
26369
  return await clonedResponse.text();
26318
26370
  }
26319
- else {
26320
- // For other content types, try text first, fallback to arrayBuffer
26371
+ // For unknown types, attempt text read with timeout protection
26372
+ try {
26373
+ return await clonedResponse.text();
26374
+ }
26375
+ catch (_c) {
26321
26376
  try {
26322
- return await clonedResponse.text();
26377
+ const arrayBuffer = await clonedResponse.arrayBuffer();
26378
+ return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`;
26323
26379
  }
26324
- catch (_c) {
26325
- try {
26326
- const arrayBuffer = await clonedResponse.arrayBuffer();
26327
- return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`;
26328
- }
26329
- catch (_d) {
26330
- return '[Fetch] Unable to read response body';
26331
- }
26380
+ catch (_d) {
26381
+ return '[Fetch] Unable to read response body';
26332
26382
  }
26333
26383
  }
26334
26384
  }
@@ -26371,6 +26421,7 @@ if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
26371
26421
  }
26372
26422
  else {
26373
26423
  // @ts-ignore
26424
+ ;
26374
26425
  window.fetch.__mp_session_recorder_patched__ = true;
26375
26426
  // Store original fetch
26376
26427
  const originalFetch = window.fetch;
@@ -26392,7 +26443,9 @@ if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
26392
26443
  if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
26393
26444
  const urlStr = inputIsRequest
26394
26445
  ? input.url
26395
- : (typeof input === 'string' || input instanceof URL ? String(input) : '');
26446
+ : typeof input === 'string' || input instanceof URL
26447
+ ? String(input)
26448
+ : '';
26396
26449
  // Only attempt to read the body from init (safe); avoid constructing/cloning Requests
26397
26450
  // If the caller passed a Request as input, we do not attempt to read its body here
26398
26451
  // eslint-disable-next-line
@@ -26400,10 +26453,9 @@ if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
26400
26453
  if (!(0,_utils_type_utils__WEBPACK_IMPORTED_MODULE_0__.isNullish)(candidateBody)) {
26401
26454
  const requestBody = _tryReadFetchBody({
26402
26455
  body: candidateBody,
26403
- url: urlStr,
26456
+ url: urlStr
26404
26457
  });
26405
- if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) &&
26406
- new Blob([requestBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
26458
+ if ((requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) && new Blob([requestBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
26407
26459
  networkRequest.requestBody = requestBody;
26408
26460
  }
26409
26461
  }
@@ -26417,8 +26469,7 @@ if (typeof window !== 'undefined' && typeof window.fetch !== 'undefined') {
26417
26469
  }
26418
26470
  if (_configs__WEBPACK_IMPORTED_MODULE_2__.configs.shouldRecordBody) {
26419
26471
  const responseBody = await _tryReadResponseBody(response);
26420
- if ((responseBody === null || responseBody === void 0 ? void 0 : responseBody.length) &&
26421
- new Blob([responseBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
26472
+ if ((responseBody === null || responseBody === void 0 ? void 0 : responseBody.length) && new Blob([responseBody]).size <= _configs__WEBPACK_IMPORTED_MODULE_2__.configs.maxCapturingHttpPayloadSize) {
26422
26473
  networkRequest.responseBody = responseBody;
26423
26474
  }
26424
26475
  }