@devskin/browser-sdk 1.0.34 → 1.0.36
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/devskin.cjs.js +27 -19
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +27 -19
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +27 -19
- package/dist/devskin.umd.js.map +1 -1
- package/dist/devskin.umd.min.js +1 -1
- package/dist/devskin.umd.min.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/recorder/rrweb.d.ts +3 -1
- package/dist/recorder/rrweb.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.cjs.js
CHANGED
|
@@ -13423,15 +13423,20 @@ record.takeFullSnapshot = (isCheckout) => {
|
|
|
13423
13423
|
record.mirror = mirror;
|
|
13424
13424
|
|
|
13425
13425
|
class RRWebRecorder {
|
|
13426
|
-
constructor(sessionId, config, onEventsReady) {
|
|
13426
|
+
constructor(sessionId, config, onEventsReady, sessionStartTime = 0) {
|
|
13427
13427
|
this.stopFn = null;
|
|
13428
13428
|
this.events = [];
|
|
13429
13429
|
this.onEventsReady = null;
|
|
13430
13430
|
this.flushInterval = null;
|
|
13431
13431
|
this.hasFullSnapshot = false;
|
|
13432
|
+
this.sessionStartTime = 0; // Session start time (for relative timestamps)
|
|
13433
|
+
this.recordingStartTime = 0; // When this recorder instance started
|
|
13432
13434
|
this.sessionId = sessionId;
|
|
13433
13435
|
this.config = config;
|
|
13434
13436
|
this.onEventsReady = onEventsReady;
|
|
13437
|
+
this.sessionStartTime = sessionStartTime || Date.now();
|
|
13438
|
+
this.recordingStartTime = Date.now();
|
|
13439
|
+
console.log(`[RRWeb] Recording initialized - session started at ${this.sessionStartTime}, recording started at ${this.recordingStartTime}`);
|
|
13435
13440
|
}
|
|
13436
13441
|
start() {
|
|
13437
13442
|
if (!this.config.enabled) {
|
|
@@ -13445,6 +13450,13 @@ class RRWebRecorder {
|
|
|
13445
13450
|
try {
|
|
13446
13451
|
this.stopFn = record({
|
|
13447
13452
|
emit: (event) => {
|
|
13453
|
+
// Convert absolute timestamps to relative to session start
|
|
13454
|
+
// This ensures continuity across page navigations within same session
|
|
13455
|
+
const originalTimestamp = event.timestamp;
|
|
13456
|
+
event.timestamp = event.timestamp - this.sessionStartTime;
|
|
13457
|
+
if (this.config.enabled && event.type === 2) {
|
|
13458
|
+
console.log(`[RRWeb] FullSnapshot - original: ${originalTimestamp}, relative: ${event.timestamp}, session start: ${this.sessionStartTime}`);
|
|
13459
|
+
}
|
|
13448
13460
|
this.events.push(event);
|
|
13449
13461
|
// Check if this is a FullSnapshot (type 2)
|
|
13450
13462
|
if (event.type === 2) {
|
|
@@ -13930,6 +13942,7 @@ class DevSkinSDK {
|
|
|
13930
13942
|
// Initialize session recording with rrweb
|
|
13931
13943
|
if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
13932
13944
|
// Use RRWebRecorder for complete DOM recording
|
|
13945
|
+
// Pass sessionStartTime to ensure timestamp continuity across page navigations
|
|
13933
13946
|
this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
|
|
13934
13947
|
enabled: true,
|
|
13935
13948
|
sampleRate: this.config.sessionRecording.sampling || 0.5,
|
|
@@ -13952,7 +13965,8 @@ class DevSkinSDK {
|
|
|
13952
13965
|
var _a;
|
|
13953
13966
|
// Send rrweb events to backend
|
|
13954
13967
|
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
|
|
13955
|
-
}
|
|
13968
|
+
}, this.sessionStartTime // Pass session start time for timestamp continuity
|
|
13969
|
+
);
|
|
13956
13970
|
// Start recording immediately (session already created)
|
|
13957
13971
|
this.rrwebRecorder.start();
|
|
13958
13972
|
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
@@ -14178,6 +14192,7 @@ class DevSkinSDK {
|
|
|
14178
14192
|
}
|
|
14179
14193
|
setupUnloadTracking() {
|
|
14180
14194
|
// CRITICAL: Flush data BEFORE page unloads to avoid losing final events
|
|
14195
|
+
// IMPORTANT: NEVER clear sessionStorage - it expires naturally when tab closes
|
|
14181
14196
|
// 1. visibilitychange - fires when tab is hidden (most reliable)
|
|
14182
14197
|
document.addEventListener('visibilitychange', () => {
|
|
14183
14198
|
var _a, _b;
|
|
@@ -14189,30 +14204,23 @@ class DevSkinSDK {
|
|
|
14189
14204
|
}
|
|
14190
14205
|
});
|
|
14191
14206
|
// 2. pagehide - fires when page is being unloaded
|
|
14192
|
-
window.addEventListener('pagehide', (
|
|
14207
|
+
window.addEventListener('pagehide', () => {
|
|
14193
14208
|
var _a, _b;
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
sessionStorage.removeItem('devskin_session_start');
|
|
14202
|
-
}
|
|
14203
|
-
else {
|
|
14204
|
-
// Navigation - track page change
|
|
14205
|
-
this.track('page_navigation');
|
|
14206
|
-
this.updateSessionDuration();
|
|
14207
|
-
}
|
|
14208
|
-
// ALWAYS flush (whether navigation or close)
|
|
14209
|
+
// Track navigation (we can't distinguish between page navigation and tab close reliably)
|
|
14210
|
+
this.track('page_navigation');
|
|
14211
|
+
// Update duration but DON'T mark as ending (let heartbeat timeout handle session expiry)
|
|
14212
|
+
this.updateSessionDuration(false);
|
|
14213
|
+
// NEVER clear sessionStorage - it persists across navigations in same tab
|
|
14214
|
+
// and expires automatically when tab actually closes
|
|
14215
|
+
// Flush data before page unloads
|
|
14209
14216
|
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop(); // Stop recording and flush remaining events
|
|
14210
14217
|
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true); // Use beacon for reliability
|
|
14211
14218
|
});
|
|
14212
14219
|
// 3. beforeunload - backup for older browsers
|
|
14213
14220
|
window.addEventListener('beforeunload', () => {
|
|
14214
14221
|
var _a, _b;
|
|
14215
|
-
|
|
14222
|
+
// Update duration but DON'T mark as ending
|
|
14223
|
+
this.updateSessionDuration(false);
|
|
14216
14224
|
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop();
|
|
14217
14225
|
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true);
|
|
14218
14226
|
});
|