@devskin/browser-sdk 1.0.31 → 1.0.33
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 +134 -125
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +134 -125
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +134 -125
- package/dist/devskin.umd.js.map +1 -1
- package/dist/devskin.umd.min.js +3 -3
- package/dist/devskin.umd.min.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.cjs.js
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
function __awaiter$1(thisArg, _arguments, P, generator) {
|
|
23
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
24
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
25
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
26
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
27
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
28
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
33
|
+
var e = new Error(message);
|
|
34
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
35
|
+
};
|
|
36
|
+
|
|
5
37
|
class DeviceCollector {
|
|
6
38
|
constructor(config) {
|
|
7
39
|
this.config = config;
|
|
@@ -119,38 +151,6 @@ class DeviceCollector {
|
|
|
119
151
|
}
|
|
120
152
|
}
|
|
121
153
|
|
|
122
|
-
/******************************************************************************
|
|
123
|
-
Copyright (c) Microsoft Corporation.
|
|
124
|
-
|
|
125
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
126
|
-
purpose with or without fee is hereby granted.
|
|
127
|
-
|
|
128
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
129
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
130
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
131
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
132
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
133
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
134
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
135
|
-
***************************************************************************** */
|
|
136
|
-
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
function __awaiter$1(thisArg, _arguments, P, generator) {
|
|
140
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
141
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
142
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
143
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
144
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
145
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
150
|
-
var e = new Error(message);
|
|
151
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
154
|
class LocationCollector {
|
|
155
155
|
constructor(config) {
|
|
156
156
|
this.config = config;
|
|
@@ -13585,9 +13585,13 @@ class Transport {
|
|
|
13585
13585
|
// Send user identification immediately (don't queue)
|
|
13586
13586
|
this.sendToBackend('/v1/analytics/identify', user);
|
|
13587
13587
|
}
|
|
13588
|
-
startSession(
|
|
13589
|
-
|
|
13590
|
-
|
|
13588
|
+
startSession(session_1) {
|
|
13589
|
+
return __awaiter$1(this, arguments, void 0, function* (session, useBeacon = false) {
|
|
13590
|
+
// Send session start immediately to RUM endpoint
|
|
13591
|
+
// MUST await to ensure session is created before other requests
|
|
13592
|
+
// Use beacon for page unload events (more reliable)
|
|
13593
|
+
yield this.sendToBackend('/v1/rum/sessions', session, useBeacon);
|
|
13594
|
+
});
|
|
13591
13595
|
}
|
|
13592
13596
|
sendError(error) {
|
|
13593
13597
|
this.enqueue('error', error);
|
|
@@ -13872,7 +13876,6 @@ class DevSkinSDK {
|
|
|
13872
13876
|
* Initialize the DevSkin SDK
|
|
13873
13877
|
*/
|
|
13874
13878
|
init(config) {
|
|
13875
|
-
var _a;
|
|
13876
13879
|
if (this.initialized) {
|
|
13877
13880
|
console.warn('[DevSkin] SDK already initialized');
|
|
13878
13881
|
return;
|
|
@@ -13895,69 +13898,71 @@ class DevSkinSDK {
|
|
|
13895
13898
|
this.locationCollector = new LocationCollector(this.config);
|
|
13896
13899
|
this.browserCollector = new BrowserCollector(this.config);
|
|
13897
13900
|
// Start session (will now include device/browser/location data)
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
:
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
(
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13901
|
+
// Wait for session creation to complete before starting collectors
|
|
13902
|
+
this.startSession().then(() => {
|
|
13903
|
+
// Session created, now safe to start collectors that send data
|
|
13904
|
+
var _a, _b;
|
|
13905
|
+
if (this.config.captureWebVitals) {
|
|
13906
|
+
this.performanceCollector = new PerformanceCollector(this.config, this.transport);
|
|
13907
|
+
this.performanceCollector.start();
|
|
13908
|
+
}
|
|
13909
|
+
if (this.config.captureErrors) {
|
|
13910
|
+
this.errorCollector = new ErrorCollector(this.config, this.transport);
|
|
13911
|
+
this.errorCollector.start();
|
|
13912
|
+
}
|
|
13913
|
+
if (this.config.captureNetworkRequests) {
|
|
13914
|
+
this.networkCollector = new NetworkCollector(this.config, this.transport);
|
|
13915
|
+
this.networkCollector.start();
|
|
13916
|
+
}
|
|
13917
|
+
// Initialize heatmap collector - SEMPRE habilitado
|
|
13918
|
+
// Merge default heatmap config with user config
|
|
13919
|
+
const heatmapConfig = Object.assign({ enabled: true, trackClicks: true, trackScroll: true, trackMouseMovement: true, mouseMoveSampling: 0.1 }, this.config.heatmapOptions);
|
|
13920
|
+
this.config.heatmapOptions = heatmapConfig;
|
|
13921
|
+
this.heatmapCollector = new HeatmapCollector(this.config, this.transport);
|
|
13922
|
+
this.heatmapCollector.start();
|
|
13923
|
+
// Initialize screenshot collector and capture page
|
|
13924
|
+
this.screenshotCollector = new ScreenshotCollector(this.config, this.transport);
|
|
13925
|
+
this.screenshotCollector.captureAndSend(this.sessionId, window.location.href);
|
|
13926
|
+
if (this.config.debug) {
|
|
13927
|
+
console.log('[DevSkin] Heatmap collection enabled (always on)');
|
|
13928
|
+
}
|
|
13929
|
+
// Initialize session recording with rrweb
|
|
13930
|
+
if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
13931
|
+
// Use RRWebRecorder for complete DOM recording
|
|
13932
|
+
this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
|
|
13933
|
+
enabled: true,
|
|
13934
|
+
sampleRate: this.config.sessionRecording.sampling || 0.5,
|
|
13935
|
+
blockClass: 'rr-block',
|
|
13936
|
+
ignoreClass: this.config.sessionRecording.ignoreClass || 'rr-ignore',
|
|
13937
|
+
maskAllInputs: this.config.sessionRecording.maskAllInputs !== undefined
|
|
13938
|
+
? this.config.sessionRecording.maskAllInputs
|
|
13939
|
+
: true,
|
|
13940
|
+
maskInputOptions: {
|
|
13941
|
+
password: true,
|
|
13942
|
+
email: true,
|
|
13943
|
+
tel: true,
|
|
13944
|
+
},
|
|
13945
|
+
recordCanvas: this.config.sessionRecording.recordCanvas || false,
|
|
13946
|
+
collectFonts: true,
|
|
13947
|
+
inlineStylesheet: true,
|
|
13948
|
+
checkoutEveryNms: 5 * 60 * 1000, // Every 5 minutes
|
|
13949
|
+
checkoutEveryNth: 200, // Every 200 events
|
|
13950
|
+
}, (events) => {
|
|
13951
|
+
var _a;
|
|
13952
|
+
// Send rrweb events to backend
|
|
13953
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
|
|
13954
|
+
});
|
|
13955
|
+
// Start recording immediately (session already created)
|
|
13956
|
+
this.rrwebRecorder.start();
|
|
13954
13957
|
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
13955
13958
|
console.log('[DevSkin] RRWeb recording started for session:', this.sessionId);
|
|
13956
13959
|
}
|
|
13957
|
-
}
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13960
|
+
}
|
|
13961
|
+
// Track initial page view
|
|
13962
|
+
this.trackPageView();
|
|
13963
|
+
}).catch((err) => {
|
|
13964
|
+
console.error('[DevSkin] Failed to create session:', err);
|
|
13965
|
+
});
|
|
13961
13966
|
// Track page visibility changes
|
|
13962
13967
|
this.setupVisibilityTracking();
|
|
13963
13968
|
// Track page unload
|
|
@@ -14082,36 +14087,39 @@ class DevSkinSDK {
|
|
|
14082
14087
|
* Private methods
|
|
14083
14088
|
*/
|
|
14084
14089
|
startSession() {
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14090
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
14091
|
+
var _a, _b, _c, _d, _e;
|
|
14092
|
+
// Check if there's an active session (stored in sessionStorage to persist across page navigations)
|
|
14093
|
+
const existingSessionId = sessionStorage.getItem('devskin_session_id');
|
|
14094
|
+
const existingSessionStart = sessionStorage.getItem('devskin_session_start');
|
|
14095
|
+
if (existingSessionId && existingSessionStart) {
|
|
14096
|
+
// Resume existing session
|
|
14097
|
+
this.sessionId = existingSessionId;
|
|
14098
|
+
this.sessionStartTime = parseInt(existingSessionStart, 10);
|
|
14099
|
+
// Set sessionId in transport so it can be added to network/performance requests
|
|
14100
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.setSessionId(this.sessionId);
|
|
14101
|
+
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
14102
|
+
console.log('[DevSkin] Resuming existing session:', this.sessionId);
|
|
14103
|
+
}
|
|
14104
|
+
// Send page view but DON'T create a new session
|
|
14105
|
+
// The session is already created, just continue it
|
|
14106
|
+
return;
|
|
14107
|
+
}
|
|
14108
|
+
// Create new session
|
|
14109
|
+
this.sessionId = this.generateId();
|
|
14110
|
+
this.sessionStartTime = Date.now();
|
|
14111
|
+
// Store in sessionStorage (persists across page navigations in same tab)
|
|
14112
|
+
sessionStorage.setItem('devskin_session_id', this.sessionId);
|
|
14113
|
+
sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
|
|
14093
14114
|
// Set sessionId in transport so it can be added to network/performance requests
|
|
14094
|
-
(
|
|
14095
|
-
|
|
14096
|
-
|
|
14115
|
+
(_c = this.transport) === null || _c === void 0 ? void 0 : _c.setSessionId(this.sessionId);
|
|
14116
|
+
const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
|
|
14117
|
+
// CRITICAL: Await session creation to ensure it exists before sending metrics/requests
|
|
14118
|
+
yield ((_d = this.transport) === null || _d === void 0 ? void 0 : _d.startSession(sessionData));
|
|
14119
|
+
if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.debug) {
|
|
14120
|
+
console.log('[DevSkin] New session created:', this.sessionId);
|
|
14097
14121
|
}
|
|
14098
|
-
|
|
14099
|
-
// The session is already created, just continue it
|
|
14100
|
-
return;
|
|
14101
|
-
}
|
|
14102
|
-
// Create new session
|
|
14103
|
-
this.sessionId = this.generateId();
|
|
14104
|
-
this.sessionStartTime = Date.now();
|
|
14105
|
-
// Store in sessionStorage (persists across page navigations in same tab)
|
|
14106
|
-
sessionStorage.setItem('devskin_session_id', this.sessionId);
|
|
14107
|
-
sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
|
|
14108
|
-
// Set sessionId in transport so it can be added to network/performance requests
|
|
14109
|
-
(_c = this.transport) === null || _c === void 0 ? void 0 : _c.setSessionId(this.sessionId);
|
|
14110
|
-
const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
|
|
14111
|
-
(_d = this.transport) === null || _d === void 0 ? void 0 : _d.startSession(sessionData);
|
|
14112
|
-
if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.debug) {
|
|
14113
|
-
console.log('[DevSkin] New session created:', this.sessionId);
|
|
14114
|
-
}
|
|
14122
|
+
});
|
|
14115
14123
|
}
|
|
14116
14124
|
getContextData() {
|
|
14117
14125
|
var _a, _b, _c, _d;
|
|
@@ -14186,7 +14194,8 @@ class DevSkinSDK {
|
|
|
14186
14194
|
if (this.sessionId && this.sessionStartTime) {
|
|
14187
14195
|
const endedAt = new Date();
|
|
14188
14196
|
const durationMs = Date.now() - this.sessionStartTime;
|
|
14189
|
-
|
|
14197
|
+
// Use beacon for reliable delivery during page unload
|
|
14198
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.startSession(Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, endedAt: endedAt.toISOString(), durationMs: durationMs, platform: 'web' }, this.getContextData()), true); // true = use sendBeacon
|
|
14190
14199
|
// Clear session storage since session is ending
|
|
14191
14200
|
sessionStorage.removeItem('devskin_session_id');
|
|
14192
14201
|
sessionStorage.removeItem('devskin_session_start');
|