@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.esm.js
CHANGED
|
@@ -13419,15 +13419,20 @@ record.takeFullSnapshot = (isCheckout) => {
|
|
|
13419
13419
|
record.mirror = mirror;
|
|
13420
13420
|
|
|
13421
13421
|
class RRWebRecorder {
|
|
13422
|
-
constructor(sessionId, config, onEventsReady) {
|
|
13422
|
+
constructor(sessionId, config, onEventsReady, sessionStartTime = 0) {
|
|
13423
13423
|
this.stopFn = null;
|
|
13424
13424
|
this.events = [];
|
|
13425
13425
|
this.onEventsReady = null;
|
|
13426
13426
|
this.flushInterval = null;
|
|
13427
13427
|
this.hasFullSnapshot = false;
|
|
13428
|
+
this.sessionStartTime = 0; // Session start time (for relative timestamps)
|
|
13429
|
+
this.recordingStartTime = 0; // When this recorder instance started
|
|
13428
13430
|
this.sessionId = sessionId;
|
|
13429
13431
|
this.config = config;
|
|
13430
13432
|
this.onEventsReady = onEventsReady;
|
|
13433
|
+
this.sessionStartTime = sessionStartTime || Date.now();
|
|
13434
|
+
this.recordingStartTime = Date.now();
|
|
13435
|
+
console.log(`[RRWeb] Recording initialized - session started at ${this.sessionStartTime}, recording started at ${this.recordingStartTime}`);
|
|
13431
13436
|
}
|
|
13432
13437
|
start() {
|
|
13433
13438
|
if (!this.config.enabled) {
|
|
@@ -13441,6 +13446,13 @@ class RRWebRecorder {
|
|
|
13441
13446
|
try {
|
|
13442
13447
|
this.stopFn = record({
|
|
13443
13448
|
emit: (event) => {
|
|
13449
|
+
// Convert absolute timestamps to relative to session start
|
|
13450
|
+
// This ensures continuity across page navigations within same session
|
|
13451
|
+
const originalTimestamp = event.timestamp;
|
|
13452
|
+
event.timestamp = event.timestamp - this.sessionStartTime;
|
|
13453
|
+
if (this.config.enabled && event.type === 2) {
|
|
13454
|
+
console.log(`[RRWeb] FullSnapshot - original: ${originalTimestamp}, relative: ${event.timestamp}, session start: ${this.sessionStartTime}`);
|
|
13455
|
+
}
|
|
13444
13456
|
this.events.push(event);
|
|
13445
13457
|
// Check if this is a FullSnapshot (type 2)
|
|
13446
13458
|
if (event.type === 2) {
|
|
@@ -13926,6 +13938,7 @@ class DevSkinSDK {
|
|
|
13926
13938
|
// Initialize session recording with rrweb
|
|
13927
13939
|
if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
13928
13940
|
// Use RRWebRecorder for complete DOM recording
|
|
13941
|
+
// Pass sessionStartTime to ensure timestamp continuity across page navigations
|
|
13929
13942
|
this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
|
|
13930
13943
|
enabled: true,
|
|
13931
13944
|
sampleRate: this.config.sessionRecording.sampling || 0.5,
|
|
@@ -13948,7 +13961,8 @@ class DevSkinSDK {
|
|
|
13948
13961
|
var _a;
|
|
13949
13962
|
// Send rrweb events to backend
|
|
13950
13963
|
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
|
|
13951
|
-
}
|
|
13964
|
+
}, this.sessionStartTime // Pass session start time for timestamp continuity
|
|
13965
|
+
);
|
|
13952
13966
|
// Start recording immediately (session already created)
|
|
13953
13967
|
this.rrwebRecorder.start();
|
|
13954
13968
|
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
@@ -14174,6 +14188,7 @@ class DevSkinSDK {
|
|
|
14174
14188
|
}
|
|
14175
14189
|
setupUnloadTracking() {
|
|
14176
14190
|
// CRITICAL: Flush data BEFORE page unloads to avoid losing final events
|
|
14191
|
+
// IMPORTANT: NEVER clear sessionStorage - it expires naturally when tab closes
|
|
14177
14192
|
// 1. visibilitychange - fires when tab is hidden (most reliable)
|
|
14178
14193
|
document.addEventListener('visibilitychange', () => {
|
|
14179
14194
|
var _a, _b;
|
|
@@ -14185,30 +14200,23 @@ class DevSkinSDK {
|
|
|
14185
14200
|
}
|
|
14186
14201
|
});
|
|
14187
14202
|
// 2. pagehide - fires when page is being unloaded
|
|
14188
|
-
window.addEventListener('pagehide', (
|
|
14203
|
+
window.addEventListener('pagehide', () => {
|
|
14189
14204
|
var _a, _b;
|
|
14190
|
-
|
|
14191
|
-
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
sessionStorage.removeItem('devskin_session_start');
|
|
14198
|
-
}
|
|
14199
|
-
else {
|
|
14200
|
-
// Navigation - track page change
|
|
14201
|
-
this.track('page_navigation');
|
|
14202
|
-
this.updateSessionDuration();
|
|
14203
|
-
}
|
|
14204
|
-
// ALWAYS flush (whether navigation or close)
|
|
14205
|
+
// Track navigation (we can't distinguish between page navigation and tab close reliably)
|
|
14206
|
+
this.track('page_navigation');
|
|
14207
|
+
// Update duration but DON'T mark as ending (let heartbeat timeout handle session expiry)
|
|
14208
|
+
this.updateSessionDuration(false);
|
|
14209
|
+
// NEVER clear sessionStorage - it persists across navigations in same tab
|
|
14210
|
+
// and expires automatically when tab actually closes
|
|
14211
|
+
// Flush data before page unloads
|
|
14205
14212
|
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop(); // Stop recording and flush remaining events
|
|
14206
14213
|
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true); // Use beacon for reliability
|
|
14207
14214
|
});
|
|
14208
14215
|
// 3. beforeunload - backup for older browsers
|
|
14209
14216
|
window.addEventListener('beforeunload', () => {
|
|
14210
14217
|
var _a, _b;
|
|
14211
|
-
|
|
14218
|
+
// Update duration but DON'T mark as ending
|
|
14219
|
+
this.updateSessionDuration(false);
|
|
14212
14220
|
(_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.stop();
|
|
14213
14221
|
(_b = this.transport) === null || _b === void 0 ? void 0 : _b.flush(true);
|
|
14214
14222
|
});
|