@cedarai/session-replay-sdk 0.4.0 → 0.5.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.
- package/dist/index.js +121 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -299,10 +299,36 @@ var ErrorCapture = class {
|
|
|
299
299
|
// src/network.ts
|
|
300
300
|
var nextId = 0;
|
|
301
301
|
var RESPONSE_BODY_MAX_SIZE = 100 * 1024;
|
|
302
|
+
function extractHeaders(headers) {
|
|
303
|
+
if (!headers) return void 0;
|
|
304
|
+
const result = {};
|
|
305
|
+
if (headers instanceof Headers) {
|
|
306
|
+
headers.forEach((v, k) => {
|
|
307
|
+
result[k] = v;
|
|
308
|
+
});
|
|
309
|
+
} else if (Array.isArray(headers)) {
|
|
310
|
+
for (const [k, v] of headers) {
|
|
311
|
+
result[k] = v;
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
Object.assign(result, headers);
|
|
315
|
+
}
|
|
316
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
317
|
+
}
|
|
318
|
+
function headersToRecord(headers) {
|
|
319
|
+
const result = {};
|
|
320
|
+
headers.forEach((v, k) => {
|
|
321
|
+
result[k] = v;
|
|
322
|
+
});
|
|
323
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
324
|
+
}
|
|
302
325
|
var NetworkCapture = class {
|
|
303
326
|
onEvent;
|
|
304
327
|
serverUrl;
|
|
305
328
|
originalFetch = null;
|
|
329
|
+
originalXHROpen = null;
|
|
330
|
+
originalXHRSend = null;
|
|
331
|
+
originalXHRSetHeader = null;
|
|
306
332
|
started = false;
|
|
307
333
|
constructor(onEvent2, serverUrl) {
|
|
308
334
|
this.onEvent = onEvent2;
|
|
@@ -311,6 +337,31 @@ var NetworkCapture = class {
|
|
|
311
337
|
start() {
|
|
312
338
|
if (this.started) return;
|
|
313
339
|
this.started = true;
|
|
340
|
+
this.interceptFetch();
|
|
341
|
+
this.interceptXHR();
|
|
342
|
+
}
|
|
343
|
+
stop() {
|
|
344
|
+
if (!this.started) return;
|
|
345
|
+
this.started = false;
|
|
346
|
+
if (this.originalFetch) {
|
|
347
|
+
globalThis.fetch = this.originalFetch;
|
|
348
|
+
this.originalFetch = null;
|
|
349
|
+
}
|
|
350
|
+
if (this.originalXHROpen) {
|
|
351
|
+
XMLHttpRequest.prototype.open = this.originalXHROpen;
|
|
352
|
+
this.originalXHROpen = null;
|
|
353
|
+
}
|
|
354
|
+
if (this.originalXHRSend) {
|
|
355
|
+
XMLHttpRequest.prototype.send = this.originalXHRSend;
|
|
356
|
+
this.originalXHRSend = null;
|
|
357
|
+
}
|
|
358
|
+
if (this.originalXHRSetHeader) {
|
|
359
|
+
XMLHttpRequest.prototype.setRequestHeader = this.originalXHRSetHeader;
|
|
360
|
+
this.originalXHRSetHeader = null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// ── Fetch interception ────────────────────────────────────────
|
|
364
|
+
interceptFetch() {
|
|
314
365
|
this.originalFetch = globalThis.fetch;
|
|
315
366
|
globalThis.fetch = async (input, init) => {
|
|
316
367
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
@@ -319,6 +370,7 @@ var NetworkCapture = class {
|
|
|
319
370
|
}
|
|
320
371
|
const method = init?.method?.toUpperCase() ?? "GET";
|
|
321
372
|
const requestBody = init?.body ? String(init.body) : void 0;
|
|
373
|
+
const requestHeaders = extractHeaders(init?.headers);
|
|
322
374
|
const startTime = performance.now();
|
|
323
375
|
const id = String(++nextId);
|
|
324
376
|
let graphqlOperationName;
|
|
@@ -354,8 +406,10 @@ var NetworkCapture = class {
|
|
|
354
406
|
method,
|
|
355
407
|
url,
|
|
356
408
|
graphqlOperationName,
|
|
409
|
+
requestHeaders,
|
|
357
410
|
requestBody,
|
|
358
411
|
status: response.status,
|
|
412
|
+
responseHeaders: headersToRecord(response.headers),
|
|
359
413
|
responseBody,
|
|
360
414
|
startTime,
|
|
361
415
|
endTime,
|
|
@@ -373,6 +427,7 @@ var NetworkCapture = class {
|
|
|
373
427
|
method,
|
|
374
428
|
url,
|
|
375
429
|
graphqlOperationName,
|
|
430
|
+
requestHeaders,
|
|
376
431
|
requestBody,
|
|
377
432
|
startTime,
|
|
378
433
|
endTime,
|
|
@@ -384,13 +439,72 @@ var NetworkCapture = class {
|
|
|
384
439
|
}
|
|
385
440
|
};
|
|
386
441
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
442
|
+
// ── XMLHttpRequest interception ───────────────────────────────
|
|
443
|
+
interceptXHR() {
|
|
444
|
+
const self = this;
|
|
445
|
+
const xhrData = /* @__PURE__ */ new WeakMap();
|
|
446
|
+
this.originalXHROpen = XMLHttpRequest.prototype.open;
|
|
447
|
+
this.originalXHRSend = XMLHttpRequest.prototype.send;
|
|
448
|
+
this.originalXHRSetHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
449
|
+
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
|
|
450
|
+
const urlStr = typeof url === "string" ? url : url.href;
|
|
451
|
+
xhrData.set(this, { method: method.toUpperCase(), url: urlStr, headers: {}, startTime: 0 });
|
|
452
|
+
return self.originalXHROpen.apply(this, [method, url, ...rest]);
|
|
453
|
+
};
|
|
454
|
+
XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
|
|
455
|
+
const data = xhrData.get(this);
|
|
456
|
+
if (data) data.headers[name] = value;
|
|
457
|
+
return self.originalXHRSetHeader.apply(this, [name, value]);
|
|
458
|
+
};
|
|
459
|
+
XMLHttpRequest.prototype.send = function(body) {
|
|
460
|
+
const data = xhrData.get(this);
|
|
461
|
+
if (data && data.url.startsWith(self.serverUrl)) {
|
|
462
|
+
return self.originalXHRSend.apply(this, [body]);
|
|
463
|
+
}
|
|
464
|
+
if (data) {
|
|
465
|
+
data.startTime = performance.now();
|
|
466
|
+
}
|
|
467
|
+
const requestBody = body != null ? String(body) : void 0;
|
|
468
|
+
this.addEventListener("loadend", function() {
|
|
469
|
+
if (!data) return;
|
|
470
|
+
const endTime = performance.now();
|
|
471
|
+
const rawHeaders = this.getAllResponseHeaders();
|
|
472
|
+
const responseHeaders = {};
|
|
473
|
+
if (rawHeaders) {
|
|
474
|
+
rawHeaders.trim().split(/[\r\n]+/).forEach((line) => {
|
|
475
|
+
const idx = line.indexOf(": ");
|
|
476
|
+
if (idx > 0) responseHeaders[line.substring(0, idx)] = line.substring(idx + 2);
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
let responseBody;
|
|
480
|
+
if (this.responseType === "" || this.responseType === "text") {
|
|
481
|
+
try {
|
|
482
|
+
const text = this.responseText;
|
|
483
|
+
if (text.length <= RESPONSE_BODY_MAX_SIZE) responseBody = text;
|
|
484
|
+
} catch {
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
self.onEvent({
|
|
488
|
+
type: "network",
|
|
489
|
+
timestamp: Date.now(),
|
|
490
|
+
data: {
|
|
491
|
+
id: String(++nextId),
|
|
492
|
+
method: data.method,
|
|
493
|
+
url: data.url,
|
|
494
|
+
requestHeaders: Object.keys(data.headers).length > 0 ? data.headers : void 0,
|
|
495
|
+
requestBody,
|
|
496
|
+
status: this.status,
|
|
497
|
+
responseHeaders: Object.keys(responseHeaders).length > 0 ? responseHeaders : void 0,
|
|
498
|
+
responseBody,
|
|
499
|
+
startTime: data.startTime,
|
|
500
|
+
endTime,
|
|
501
|
+
duration: endTime - data.startTime,
|
|
502
|
+
error: this.status === 0 ? "Network error" : void 0
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
return self.originalXHRSend.apply(this, [body]);
|
|
507
|
+
};
|
|
394
508
|
}
|
|
395
509
|
};
|
|
396
510
|
|