@devskin/browser-sdk 1.0.30 → 1.0.32
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/collectors/network.d.ts.map +1 -1
- package/dist/collectors/performance.d.ts.map +1 -1
- package/dist/devskin.cjs.js +172 -182
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +172 -182
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +172 -182
- 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 +3 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/types.d.ts +8 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.esm.js
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
|
|
4
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
5
|
+
purpose with or without fee is hereby granted.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
***************************************************************************** */
|
|
15
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
function __awaiter$1(thisArg, _arguments, P, generator) {
|
|
19
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
20
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
21
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
22
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
23
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
24
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
29
|
+
var e = new Error(message);
|
|
30
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
31
|
+
};
|
|
32
|
+
|
|
1
33
|
class DeviceCollector {
|
|
2
34
|
constructor(config) {
|
|
3
35
|
this.config = config;
|
|
@@ -115,38 +147,6 @@ class DeviceCollector {
|
|
|
115
147
|
}
|
|
116
148
|
}
|
|
117
149
|
|
|
118
|
-
/******************************************************************************
|
|
119
|
-
Copyright (c) Microsoft Corporation.
|
|
120
|
-
|
|
121
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
122
|
-
purpose with or without fee is hereby granted.
|
|
123
|
-
|
|
124
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
125
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
126
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
127
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
128
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
129
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
130
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
131
|
-
***************************************************************************** */
|
|
132
|
-
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
function __awaiter$1(thisArg, _arguments, P, generator) {
|
|
136
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
137
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
138
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
139
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
140
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
141
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
146
|
-
var e = new Error(message);
|
|
147
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
148
|
-
};
|
|
149
|
-
|
|
150
150
|
class LocationCollector {
|
|
151
151
|
constructor(config) {
|
|
152
152
|
this.config = config;
|
|
@@ -334,12 +334,12 @@ class PerformanceCollector {
|
|
|
334
334
|
if (this.config.debug) {
|
|
335
335
|
console.log(`[DevSkin] Web Vital ${metric.name}:`, metric.value);
|
|
336
336
|
}
|
|
337
|
-
// Send metric to backend
|
|
337
|
+
// Send metric to backend - match backend schema
|
|
338
338
|
this.transport.sendPerformanceMetric({
|
|
339
|
-
|
|
339
|
+
metricName: metric.name, // Changed from 'name' to 'metricName'
|
|
340
340
|
value: metric.value,
|
|
341
341
|
rating: metric.rating,
|
|
342
|
-
|
|
342
|
+
url: window.location.href,
|
|
343
343
|
timestamp: new Date().toISOString(),
|
|
344
344
|
});
|
|
345
345
|
}
|
|
@@ -362,19 +362,9 @@ class PerformanceCollector {
|
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
this.transport.sendPerformanceMetric({
|
|
365
|
-
|
|
365
|
+
metricName: 'Navigation',
|
|
366
366
|
value: windowLoad,
|
|
367
|
-
|
|
368
|
-
domLoad,
|
|
369
|
-
windowLoad,
|
|
370
|
-
navigationType: navigation.type,
|
|
371
|
-
redirectCount: navigation.redirectCount,
|
|
372
|
-
dns: timing.domainLookupEnd - timing.domainLookupStart,
|
|
373
|
-
tcp: timing.connectEnd - timing.connectStart,
|
|
374
|
-
request: timing.responseStart - timing.requestStart,
|
|
375
|
-
response: timing.responseEnd - timing.responseStart,
|
|
376
|
-
dom: timing.domComplete - timing.domLoading,
|
|
377
|
-
},
|
|
367
|
+
url: window.location.href,
|
|
378
368
|
timestamp: new Date().toISOString(),
|
|
379
369
|
});
|
|
380
370
|
}, 0);
|
|
@@ -408,9 +398,9 @@ class PerformanceCollector {
|
|
|
408
398
|
console.log('[DevSkin] Resource Timings:', resourceStats);
|
|
409
399
|
}
|
|
410
400
|
this.transport.sendPerformanceMetric({
|
|
411
|
-
|
|
401
|
+
metricName: 'Resources',
|
|
412
402
|
value: resources.length,
|
|
413
|
-
|
|
403
|
+
url: window.location.href,
|
|
414
404
|
timestamp: new Date().toISOString(),
|
|
415
405
|
});
|
|
416
406
|
}, 1000);
|
|
@@ -427,13 +417,9 @@ class PerformanceCollector {
|
|
|
427
417
|
console.log('[DevSkin] Long Task detected:', entry);
|
|
428
418
|
}
|
|
429
419
|
this.transport.sendPerformanceMetric({
|
|
430
|
-
|
|
420
|
+
metricName: 'LongTask',
|
|
431
421
|
value: entry.duration,
|
|
432
|
-
|
|
433
|
-
name: entry.name,
|
|
434
|
-
entryType: entry.entryType,
|
|
435
|
-
startTime: entry.startTime,
|
|
436
|
-
},
|
|
422
|
+
url: window.location.href,
|
|
437
423
|
timestamp: new Date().toISOString(),
|
|
438
424
|
});
|
|
439
425
|
}
|
|
@@ -673,7 +659,7 @@ class NetworkCollector {
|
|
|
673
659
|
return;
|
|
674
660
|
const originalFetch = window.fetch;
|
|
675
661
|
window.fetch = (...args) => __awaiter$1(this, void 0, void 0, function* () {
|
|
676
|
-
var _a, _b
|
|
662
|
+
var _a, _b;
|
|
677
663
|
const [resource, config] = args;
|
|
678
664
|
const url = typeof resource === 'string'
|
|
679
665
|
? resource
|
|
@@ -699,26 +685,18 @@ class NetworkCollector {
|
|
|
699
685
|
const networkRequest = {
|
|
700
686
|
url,
|
|
701
687
|
method,
|
|
702
|
-
|
|
703
|
-
duration,
|
|
704
|
-
|
|
705
|
-
type: 'fetch',
|
|
688
|
+
statusCode: response.status,
|
|
689
|
+
durationMs: duration,
|
|
690
|
+
responseSize: yield this.getResponseSize(clonedResponse),
|
|
706
691
|
timestamp: new Date().toISOString(),
|
|
707
|
-
failed: !response.ok,
|
|
708
692
|
};
|
|
709
693
|
// Capture headers if enabled
|
|
710
694
|
if ((_b = this.config.networkRequestOptions) === null || _b === void 0 ? void 0 : _b.captureHeaders) {
|
|
711
|
-
networkRequest.
|
|
695
|
+
networkRequest.responseHeaders = this.headersToObject(response.headers);
|
|
712
696
|
}
|
|
713
|
-
// Capture
|
|
714
|
-
if (
|
|
715
|
-
|
|
716
|
-
const text = yield clonedResponse.text();
|
|
717
|
-
networkRequest.body = text.substring(0, 10000); // Limit to 10KB
|
|
718
|
-
}
|
|
719
|
-
catch (error) {
|
|
720
|
-
// Body might not be readable
|
|
721
|
-
}
|
|
697
|
+
// Capture error message for failed requests
|
|
698
|
+
if (!response.ok) {
|
|
699
|
+
networkRequest.errorMessage = `HTTP ${response.status} ${response.statusText}`;
|
|
722
700
|
}
|
|
723
701
|
if (this.config.debug) {
|
|
724
702
|
console.log('[DevSkin] Network request tracked:', networkRequest);
|
|
@@ -732,10 +710,9 @@ class NetworkCollector {
|
|
|
732
710
|
const networkRequest = {
|
|
733
711
|
url,
|
|
734
712
|
method,
|
|
735
|
-
duration,
|
|
736
|
-
type: 'fetch',
|
|
713
|
+
durationMs: duration,
|
|
737
714
|
timestamp: new Date().toISOString(),
|
|
738
|
-
|
|
715
|
+
errorMessage: error instanceof Error ? error.message : 'Network request failed',
|
|
739
716
|
};
|
|
740
717
|
if (this.config.debug) {
|
|
741
718
|
console.log('[DevSkin] Network request failed:', networkRequest);
|
|
@@ -774,7 +751,7 @@ class NetworkCollector {
|
|
|
774
751
|
const collector = window.__devskinNetworkCollector;
|
|
775
752
|
// Track when request completes
|
|
776
753
|
const handleLoad = () => {
|
|
777
|
-
var _a, _b
|
|
754
|
+
var _a, _b;
|
|
778
755
|
const duration = Date.now() - devskin.startTime;
|
|
779
756
|
// Check if should be ignored
|
|
780
757
|
if (collector === null || collector === void 0 ? void 0 : collector.shouldIgnoreUrl(devskin.url)) {
|
|
@@ -789,25 +766,17 @@ class NetworkCollector {
|
|
|
789
766
|
const networkRequest = {
|
|
790
767
|
url: devskin.url,
|
|
791
768
|
method: devskin.method,
|
|
792
|
-
|
|
793
|
-
duration,
|
|
794
|
-
type: 'xhr',
|
|
769
|
+
statusCode: xhr.status,
|
|
770
|
+
durationMs: duration,
|
|
795
771
|
timestamp: new Date().toISOString(),
|
|
796
|
-
failed: xhr.status === 0 || xhr.status >= 400,
|
|
797
772
|
};
|
|
798
773
|
// Capture headers if enabled
|
|
799
774
|
if ((_b = collector === null || collector === void 0 ? void 0 : collector.config.networkRequestOptions) === null || _b === void 0 ? void 0 : _b.captureHeaders) {
|
|
800
|
-
networkRequest.
|
|
775
|
+
networkRequest.responseHeaders = collector.parseResponseHeaders(xhr.getAllResponseHeaders());
|
|
801
776
|
}
|
|
802
|
-
// Capture
|
|
803
|
-
if (
|
|
804
|
-
networkRequest.
|
|
805
|
-
try {
|
|
806
|
-
networkRequest.body = (_d = xhr.responseText) === null || _d === void 0 ? void 0 : _d.substring(0, 10000);
|
|
807
|
-
}
|
|
808
|
-
catch (error) {
|
|
809
|
-
// Response might not be readable
|
|
810
|
-
}
|
|
777
|
+
// Capture error message for failed requests
|
|
778
|
+
if (xhr.status === 0 || xhr.status >= 400) {
|
|
779
|
+
networkRequest.errorMessage = `HTTP ${xhr.status} ${xhr.statusText}`;
|
|
811
780
|
}
|
|
812
781
|
if (collector === null || collector === void 0 ? void 0 : collector.config.debug) {
|
|
813
782
|
console.log('[DevSkin] XHR request tracked:', networkRequest);
|
|
@@ -820,10 +789,9 @@ class NetworkCollector {
|
|
|
820
789
|
const networkRequest = {
|
|
821
790
|
url: devskin.url,
|
|
822
791
|
method: devskin.method,
|
|
823
|
-
duration,
|
|
824
|
-
type: 'xhr',
|
|
792
|
+
durationMs: duration,
|
|
825
793
|
timestamp: new Date().toISOString(),
|
|
826
|
-
|
|
794
|
+
errorMessage: 'XHR request failed',
|
|
827
795
|
};
|
|
828
796
|
if (collector === null || collector === void 0 ? void 0 : collector.config.debug) {
|
|
829
797
|
console.log('[DevSkin] XHR request failed:', networkRequest);
|
|
@@ -13586,6 +13554,7 @@ class Transport {
|
|
|
13586
13554
|
this.flushInterval = null;
|
|
13587
13555
|
this.maxQueueSize = 20; // Reduced from 50
|
|
13588
13556
|
this.flushIntervalMs = 2000; // 2 seconds (reduced from 5s)
|
|
13557
|
+
this.sessionId = null;
|
|
13589
13558
|
this.apiUrl = config.apiUrl || 'https://api.devskin.com';
|
|
13590
13559
|
// Start periodic flush
|
|
13591
13560
|
this.startPeriodicFlush();
|
|
@@ -13602,6 +13571,9 @@ class Transport {
|
|
|
13602
13571
|
});
|
|
13603
13572
|
}
|
|
13604
13573
|
}
|
|
13574
|
+
setSessionId(sessionId) {
|
|
13575
|
+
this.sessionId = sessionId;
|
|
13576
|
+
}
|
|
13605
13577
|
sendEvent(event) {
|
|
13606
13578
|
this.enqueue('event', event);
|
|
13607
13579
|
}
|
|
@@ -13610,8 +13582,11 @@ class Transport {
|
|
|
13610
13582
|
this.sendToBackend('/v1/analytics/identify', user);
|
|
13611
13583
|
}
|
|
13612
13584
|
startSession(session) {
|
|
13613
|
-
|
|
13614
|
-
|
|
13585
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
13586
|
+
// Send session start immediately to RUM endpoint
|
|
13587
|
+
// MUST await to ensure session is created before other requests
|
|
13588
|
+
yield this.sendToBackend('/v1/rum/sessions', session);
|
|
13589
|
+
});
|
|
13615
13590
|
}
|
|
13616
13591
|
sendError(error) {
|
|
13617
13592
|
this.enqueue('error', error);
|
|
@@ -13723,9 +13698,16 @@ class Transport {
|
|
|
13723
13698
|
}
|
|
13724
13699
|
}
|
|
13725
13700
|
enqueue(type, data) {
|
|
13726
|
-
// Add applicationId to RUM events (event, error, network, performance)
|
|
13701
|
+
// Add applicationId and sessionId to RUM events (event, error, network, performance)
|
|
13727
13702
|
// Heatmap uses apiKey/appId in payload root instead
|
|
13728
|
-
|
|
13703
|
+
let enrichedData = data;
|
|
13704
|
+
if (type !== 'heatmap') {
|
|
13705
|
+
enrichedData = Object.assign(Object.assign({}, data), { applicationId: this.config.appId });
|
|
13706
|
+
// Add sessionId to network and performance requests (required by backend)
|
|
13707
|
+
if ((type === 'network' || type === 'performance') && this.sessionId) {
|
|
13708
|
+
enrichedData.sessionId = this.sessionId;
|
|
13709
|
+
}
|
|
13710
|
+
}
|
|
13729
13711
|
this.queue.push({
|
|
13730
13712
|
type,
|
|
13731
13713
|
data: enrichedData,
|
|
@@ -13889,7 +13871,6 @@ class DevSkinSDK {
|
|
|
13889
13871
|
* Initialize the DevSkin SDK
|
|
13890
13872
|
*/
|
|
13891
13873
|
init(config) {
|
|
13892
|
-
var _a;
|
|
13893
13874
|
if (this.initialized) {
|
|
13894
13875
|
console.warn('[DevSkin] SDK already initialized');
|
|
13895
13876
|
return;
|
|
@@ -13912,69 +13893,71 @@ class DevSkinSDK {
|
|
|
13912
13893
|
this.locationCollector = new LocationCollector(this.config);
|
|
13913
13894
|
this.browserCollector = new BrowserCollector(this.config);
|
|
13914
13895
|
// Start session (will now include device/browser/location data)
|
|
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
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
(
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13896
|
+
// Wait for session creation to complete before starting collectors
|
|
13897
|
+
this.startSession().then(() => {
|
|
13898
|
+
// Session created, now safe to start collectors that send data
|
|
13899
|
+
var _a, _b;
|
|
13900
|
+
if (this.config.captureWebVitals) {
|
|
13901
|
+
this.performanceCollector = new PerformanceCollector(this.config, this.transport);
|
|
13902
|
+
this.performanceCollector.start();
|
|
13903
|
+
}
|
|
13904
|
+
if (this.config.captureErrors) {
|
|
13905
|
+
this.errorCollector = new ErrorCollector(this.config, this.transport);
|
|
13906
|
+
this.errorCollector.start();
|
|
13907
|
+
}
|
|
13908
|
+
if (this.config.captureNetworkRequests) {
|
|
13909
|
+
this.networkCollector = new NetworkCollector(this.config, this.transport);
|
|
13910
|
+
this.networkCollector.start();
|
|
13911
|
+
}
|
|
13912
|
+
// Initialize heatmap collector - SEMPRE habilitado
|
|
13913
|
+
// Merge default heatmap config with user config
|
|
13914
|
+
const heatmapConfig = Object.assign({ enabled: true, trackClicks: true, trackScroll: true, trackMouseMovement: true, mouseMoveSampling: 0.1 }, this.config.heatmapOptions);
|
|
13915
|
+
this.config.heatmapOptions = heatmapConfig;
|
|
13916
|
+
this.heatmapCollector = new HeatmapCollector(this.config, this.transport);
|
|
13917
|
+
this.heatmapCollector.start();
|
|
13918
|
+
// Initialize screenshot collector and capture page
|
|
13919
|
+
this.screenshotCollector = new ScreenshotCollector(this.config, this.transport);
|
|
13920
|
+
this.screenshotCollector.captureAndSend(this.sessionId, window.location.href);
|
|
13921
|
+
if (this.config.debug) {
|
|
13922
|
+
console.log('[DevSkin] Heatmap collection enabled (always on)');
|
|
13923
|
+
}
|
|
13924
|
+
// Initialize session recording with rrweb
|
|
13925
|
+
if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
13926
|
+
// Use RRWebRecorder for complete DOM recording
|
|
13927
|
+
this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
|
|
13928
|
+
enabled: true,
|
|
13929
|
+
sampleRate: this.config.sessionRecording.sampling || 0.5,
|
|
13930
|
+
blockClass: 'rr-block',
|
|
13931
|
+
ignoreClass: this.config.sessionRecording.ignoreClass || 'rr-ignore',
|
|
13932
|
+
maskAllInputs: this.config.sessionRecording.maskAllInputs !== undefined
|
|
13933
|
+
? this.config.sessionRecording.maskAllInputs
|
|
13934
|
+
: true,
|
|
13935
|
+
maskInputOptions: {
|
|
13936
|
+
password: true,
|
|
13937
|
+
email: true,
|
|
13938
|
+
tel: true,
|
|
13939
|
+
},
|
|
13940
|
+
recordCanvas: this.config.sessionRecording.recordCanvas || false,
|
|
13941
|
+
collectFonts: true,
|
|
13942
|
+
inlineStylesheet: true,
|
|
13943
|
+
checkoutEveryNms: 5 * 60 * 1000, // Every 5 minutes
|
|
13944
|
+
checkoutEveryNth: 200, // Every 200 events
|
|
13945
|
+
}, (events) => {
|
|
13946
|
+
var _a;
|
|
13947
|
+
// Send rrweb events to backend
|
|
13948
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
|
|
13949
|
+
});
|
|
13950
|
+
// Start recording immediately (session already created)
|
|
13951
|
+
this.rrwebRecorder.start();
|
|
13971
13952
|
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
13972
13953
|
console.log('[DevSkin] RRWeb recording started for session:', this.sessionId);
|
|
13973
13954
|
}
|
|
13974
|
-
}
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13955
|
+
}
|
|
13956
|
+
// Track initial page view
|
|
13957
|
+
this.trackPageView();
|
|
13958
|
+
}).catch((err) => {
|
|
13959
|
+
console.error('[DevSkin] Failed to create session:', err);
|
|
13960
|
+
});
|
|
13978
13961
|
// Track page visibility changes
|
|
13979
13962
|
this.setupVisibilityTracking();
|
|
13980
13963
|
// Track page unload
|
|
@@ -14099,32 +14082,39 @@ class DevSkinSDK {
|
|
|
14099
14082
|
* Private methods
|
|
14100
14083
|
*/
|
|
14101
14084
|
startSession() {
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14085
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
14086
|
+
var _a, _b, _c, _d, _e;
|
|
14087
|
+
// Check if there's an active session (stored in sessionStorage to persist across page navigations)
|
|
14088
|
+
const existingSessionId = sessionStorage.getItem('devskin_session_id');
|
|
14089
|
+
const existingSessionStart = sessionStorage.getItem('devskin_session_start');
|
|
14090
|
+
if (existingSessionId && existingSessionStart) {
|
|
14091
|
+
// Resume existing session
|
|
14092
|
+
this.sessionId = existingSessionId;
|
|
14093
|
+
this.sessionStartTime = parseInt(existingSessionStart, 10);
|
|
14094
|
+
// Set sessionId in transport so it can be added to network/performance requests
|
|
14095
|
+
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.setSessionId(this.sessionId);
|
|
14096
|
+
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
|
|
14097
|
+
console.log('[DevSkin] Resuming existing session:', this.sessionId);
|
|
14098
|
+
}
|
|
14099
|
+
// Send page view but DON'T create a new session
|
|
14100
|
+
// The session is already created, just continue it
|
|
14101
|
+
return;
|
|
14112
14102
|
}
|
|
14113
|
-
//
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
}
|
|
14103
|
+
// Create new session
|
|
14104
|
+
this.sessionId = this.generateId();
|
|
14105
|
+
this.sessionStartTime = Date.now();
|
|
14106
|
+
// Store in sessionStorage (persists across page navigations in same tab)
|
|
14107
|
+
sessionStorage.setItem('devskin_session_id', this.sessionId);
|
|
14108
|
+
sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
|
|
14109
|
+
// Set sessionId in transport so it can be added to network/performance requests
|
|
14110
|
+
(_c = this.transport) === null || _c === void 0 ? void 0 : _c.setSessionId(this.sessionId);
|
|
14111
|
+
const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
|
|
14112
|
+
// CRITICAL: Await session creation to ensure it exists before sending metrics/requests
|
|
14113
|
+
yield ((_d = this.transport) === null || _d === void 0 ? void 0 : _d.startSession(sessionData));
|
|
14114
|
+
if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.debug) {
|
|
14115
|
+
console.log('[DevSkin] New session created:', this.sessionId);
|
|
14116
|
+
}
|
|
14117
|
+
});
|
|
14128
14118
|
}
|
|
14129
14119
|
getContextData() {
|
|
14130
14120
|
var _a, _b, _c, _d;
|