@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.
@@ -1 +1 @@
1
- {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/collectors/network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;gBADT,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS;IAG9B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,cAAc;IA6FtB,OAAO,CAAC,YAAY;IA8HpB,OAAO,CAAC,eAAe;YAiBT,eAAe;IAS7B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,oBAAoB;CAgB7B"}
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/collectors/network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;gBADT,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS;IAG9B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,cAAc;IAqFtB,OAAO,CAAC,YAAY;IAoHpB,OAAO,CAAC,eAAe;YAiBT,eAAe;IAS7B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,oBAAoB;CAgB7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/collectors/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,oBAAoB;IAI7B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IAJnB,OAAO,CAAC,OAAO,CAA0B;gBAG/B,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS;IAG9B,KAAK,IAAI,IAAI;IAoBb,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,sBAAsB;IA0C9B,OAAO,CAAC,gBAAgB;IAiCxB,UAAU,IAAI,kBAAkB;CAGjC"}
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/collectors/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,oBAAoB;IAI7B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IAJnB,OAAO,CAAC,OAAO,CAA0B;gBAG/B,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS;IAG9B,KAAK,IAAI,IAAI;IAoBb,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,wBAAwB;IAgChC,OAAO,CAAC,sBAAsB;IA0C9B,OAAO,CAAC,gBAAgB;IA6BxB,UAAU,IAAI,kBAAkB;CAGjC"}
@@ -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;
@@ -338,12 +338,12 @@ class PerformanceCollector {
338
338
  if (this.config.debug) {
339
339
  console.log(`[DevSkin] Web Vital ${metric.name}:`, metric.value);
340
340
  }
341
- // Send metric to backend
341
+ // Send metric to backend - match backend schema
342
342
  this.transport.sendPerformanceMetric({
343
- name: metric.name,
343
+ metricName: metric.name, // Changed from 'name' to 'metricName'
344
344
  value: metric.value,
345
345
  rating: metric.rating,
346
- delta: metric.delta,
346
+ url: window.location.href,
347
347
  timestamp: new Date().toISOString(),
348
348
  });
349
349
  }
@@ -366,19 +366,9 @@ class PerformanceCollector {
366
366
  });
367
367
  }
368
368
  this.transport.sendPerformanceMetric({
369
- name: 'Navigation',
369
+ metricName: 'Navigation',
370
370
  value: windowLoad,
371
- details: {
372
- domLoad,
373
- windowLoad,
374
- navigationType: navigation.type,
375
- redirectCount: navigation.redirectCount,
376
- dns: timing.domainLookupEnd - timing.domainLookupStart,
377
- tcp: timing.connectEnd - timing.connectStart,
378
- request: timing.responseStart - timing.requestStart,
379
- response: timing.responseEnd - timing.responseStart,
380
- dom: timing.domComplete - timing.domLoading,
381
- },
371
+ url: window.location.href,
382
372
  timestamp: new Date().toISOString(),
383
373
  });
384
374
  }, 0);
@@ -412,9 +402,9 @@ class PerformanceCollector {
412
402
  console.log('[DevSkin] Resource Timings:', resourceStats);
413
403
  }
414
404
  this.transport.sendPerformanceMetric({
415
- name: 'Resources',
405
+ metricName: 'Resources',
416
406
  value: resources.length,
417
- details: resourceStats,
407
+ url: window.location.href,
418
408
  timestamp: new Date().toISOString(),
419
409
  });
420
410
  }, 1000);
@@ -431,13 +421,9 @@ class PerformanceCollector {
431
421
  console.log('[DevSkin] Long Task detected:', entry);
432
422
  }
433
423
  this.transport.sendPerformanceMetric({
434
- name: 'LongTask',
424
+ metricName: 'LongTask',
435
425
  value: entry.duration,
436
- details: {
437
- name: entry.name,
438
- entryType: entry.entryType,
439
- startTime: entry.startTime,
440
- },
426
+ url: window.location.href,
441
427
  timestamp: new Date().toISOString(),
442
428
  });
443
429
  }
@@ -677,7 +663,7 @@ class NetworkCollector {
677
663
  return;
678
664
  const originalFetch = window.fetch;
679
665
  window.fetch = (...args) => __awaiter$1(this, void 0, void 0, function* () {
680
- var _a, _b, _c;
666
+ var _a, _b;
681
667
  const [resource, config] = args;
682
668
  const url = typeof resource === 'string'
683
669
  ? resource
@@ -703,26 +689,18 @@ class NetworkCollector {
703
689
  const networkRequest = {
704
690
  url,
705
691
  method,
706
- status: response.status,
707
- duration,
708
- size: yield this.getResponseSize(clonedResponse),
709
- type: 'fetch',
692
+ statusCode: response.status,
693
+ durationMs: duration,
694
+ responseSize: yield this.getResponseSize(clonedResponse),
710
695
  timestamp: new Date().toISOString(),
711
- failed: !response.ok,
712
696
  };
713
697
  // Capture headers if enabled
714
698
  if ((_b = this.config.networkRequestOptions) === null || _b === void 0 ? void 0 : _b.captureHeaders) {
715
- networkRequest.headers = this.headersToObject(response.headers);
699
+ networkRequest.responseHeaders = this.headersToObject(response.headers);
716
700
  }
717
- // Capture body if enabled (only for failed requests to avoid performance issues)
718
- if (((_c = this.config.networkRequestOptions) === null || _c === void 0 ? void 0 : _c.captureBody) && !response.ok) {
719
- try {
720
- const text = yield clonedResponse.text();
721
- networkRequest.body = text.substring(0, 10000); // Limit to 10KB
722
- }
723
- catch (error) {
724
- // Body might not be readable
725
- }
701
+ // Capture error message for failed requests
702
+ if (!response.ok) {
703
+ networkRequest.errorMessage = `HTTP ${response.status} ${response.statusText}`;
726
704
  }
727
705
  if (this.config.debug) {
728
706
  console.log('[DevSkin] Network request tracked:', networkRequest);
@@ -736,10 +714,9 @@ class NetworkCollector {
736
714
  const networkRequest = {
737
715
  url,
738
716
  method,
739
- duration,
740
- type: 'fetch',
717
+ durationMs: duration,
741
718
  timestamp: new Date().toISOString(),
742
- failed: true,
719
+ errorMessage: error instanceof Error ? error.message : 'Network request failed',
743
720
  };
744
721
  if (this.config.debug) {
745
722
  console.log('[DevSkin] Network request failed:', networkRequest);
@@ -778,7 +755,7 @@ class NetworkCollector {
778
755
  const collector = window.__devskinNetworkCollector;
779
756
  // Track when request completes
780
757
  const handleLoad = () => {
781
- var _a, _b, _c, _d;
758
+ var _a, _b;
782
759
  const duration = Date.now() - devskin.startTime;
783
760
  // Check if should be ignored
784
761
  if (collector === null || collector === void 0 ? void 0 : collector.shouldIgnoreUrl(devskin.url)) {
@@ -793,25 +770,17 @@ class NetworkCollector {
793
770
  const networkRequest = {
794
771
  url: devskin.url,
795
772
  method: devskin.method,
796
- status: xhr.status,
797
- duration,
798
- type: 'xhr',
773
+ statusCode: xhr.status,
774
+ durationMs: duration,
799
775
  timestamp: new Date().toISOString(),
800
- failed: xhr.status === 0 || xhr.status >= 400,
801
776
  };
802
777
  // Capture headers if enabled
803
778
  if ((_b = collector === null || collector === void 0 ? void 0 : collector.config.networkRequestOptions) === null || _b === void 0 ? void 0 : _b.captureHeaders) {
804
- networkRequest.headers = collector.parseResponseHeaders(xhr.getAllResponseHeaders());
779
+ networkRequest.responseHeaders = collector.parseResponseHeaders(xhr.getAllResponseHeaders());
805
780
  }
806
- // Capture body if enabled (only for failed requests)
807
- if (((_c = collector === null || collector === void 0 ? void 0 : collector.config.networkRequestOptions) === null || _c === void 0 ? void 0 : _c.captureBody) &&
808
- networkRequest.failed) {
809
- try {
810
- networkRequest.body = (_d = xhr.responseText) === null || _d === void 0 ? void 0 : _d.substring(0, 10000);
811
- }
812
- catch (error) {
813
- // Response might not be readable
814
- }
781
+ // Capture error message for failed requests
782
+ if (xhr.status === 0 || xhr.status >= 400) {
783
+ networkRequest.errorMessage = `HTTP ${xhr.status} ${xhr.statusText}`;
815
784
  }
816
785
  if (collector === null || collector === void 0 ? void 0 : collector.config.debug) {
817
786
  console.log('[DevSkin] XHR request tracked:', networkRequest);
@@ -824,10 +793,9 @@ class NetworkCollector {
824
793
  const networkRequest = {
825
794
  url: devskin.url,
826
795
  method: devskin.method,
827
- duration,
828
- type: 'xhr',
796
+ durationMs: duration,
829
797
  timestamp: new Date().toISOString(),
830
- failed: true,
798
+ errorMessage: 'XHR request failed',
831
799
  };
832
800
  if (collector === null || collector === void 0 ? void 0 : collector.config.debug) {
833
801
  console.log('[DevSkin] XHR request failed:', networkRequest);
@@ -13590,6 +13558,7 @@ class Transport {
13590
13558
  this.flushInterval = null;
13591
13559
  this.maxQueueSize = 20; // Reduced from 50
13592
13560
  this.flushIntervalMs = 2000; // 2 seconds (reduced from 5s)
13561
+ this.sessionId = null;
13593
13562
  this.apiUrl = config.apiUrl || 'https://api.devskin.com';
13594
13563
  // Start periodic flush
13595
13564
  this.startPeriodicFlush();
@@ -13606,6 +13575,9 @@ class Transport {
13606
13575
  });
13607
13576
  }
13608
13577
  }
13578
+ setSessionId(sessionId) {
13579
+ this.sessionId = sessionId;
13580
+ }
13609
13581
  sendEvent(event) {
13610
13582
  this.enqueue('event', event);
13611
13583
  }
@@ -13614,8 +13586,11 @@ class Transport {
13614
13586
  this.sendToBackend('/v1/analytics/identify', user);
13615
13587
  }
13616
13588
  startSession(session) {
13617
- // Send session start immediately to RUM endpoint
13618
- this.sendToBackend('/v1/rum/sessions', session);
13589
+ return __awaiter$1(this, void 0, void 0, function* () {
13590
+ // Send session start immediately to RUM endpoint
13591
+ // MUST await to ensure session is created before other requests
13592
+ yield this.sendToBackend('/v1/rum/sessions', session);
13593
+ });
13619
13594
  }
13620
13595
  sendError(error) {
13621
13596
  this.enqueue('error', error);
@@ -13727,9 +13702,16 @@ class Transport {
13727
13702
  }
13728
13703
  }
13729
13704
  enqueue(type, data) {
13730
- // Add applicationId to RUM events (event, error, network, performance)
13705
+ // Add applicationId and sessionId to RUM events (event, error, network, performance)
13731
13706
  // Heatmap uses apiKey/appId in payload root instead
13732
- const enrichedData = type !== 'heatmap' ? Object.assign(Object.assign({}, data), { applicationId: this.config.appId }) : data;
13707
+ let enrichedData = data;
13708
+ if (type !== 'heatmap') {
13709
+ enrichedData = Object.assign(Object.assign({}, data), { applicationId: this.config.appId });
13710
+ // Add sessionId to network and performance requests (required by backend)
13711
+ if ((type === 'network' || type === 'performance') && this.sessionId) {
13712
+ enrichedData.sessionId = this.sessionId;
13713
+ }
13714
+ }
13733
13715
  this.queue.push({
13734
13716
  type,
13735
13717
  data: enrichedData,
@@ -13893,7 +13875,6 @@ class DevSkinSDK {
13893
13875
  * Initialize the DevSkin SDK
13894
13876
  */
13895
13877
  init(config) {
13896
- var _a;
13897
13878
  if (this.initialized) {
13898
13879
  console.warn('[DevSkin] SDK already initialized');
13899
13880
  return;
@@ -13916,69 +13897,71 @@ class DevSkinSDK {
13916
13897
  this.locationCollector = new LocationCollector(this.config);
13917
13898
  this.browserCollector = new BrowserCollector(this.config);
13918
13899
  // Start session (will now include device/browser/location data)
13919
- this.startSession();
13920
- if (this.config.captureWebVitals) {
13921
- this.performanceCollector = new PerformanceCollector(this.config, this.transport);
13922
- this.performanceCollector.start();
13923
- }
13924
- if (this.config.captureErrors) {
13925
- this.errorCollector = new ErrorCollector(this.config, this.transport);
13926
- this.errorCollector.start();
13927
- }
13928
- if (this.config.captureNetworkRequests) {
13929
- this.networkCollector = new NetworkCollector(this.config, this.transport);
13930
- this.networkCollector.start();
13931
- }
13932
- // Initialize heatmap collector - SEMPRE habilitado
13933
- // Merge default heatmap config with user config
13934
- const heatmapConfig = Object.assign({ enabled: true, trackClicks: true, trackScroll: true, trackMouseMovement: true, mouseMoveSampling: 0.1 }, this.config.heatmapOptions);
13935
- this.config.heatmapOptions = heatmapConfig;
13936
- this.heatmapCollector = new HeatmapCollector(this.config, this.transport);
13937
- this.heatmapCollector.start();
13938
- // Initialize screenshot collector and capture page
13939
- this.screenshotCollector = new ScreenshotCollector(this.config, this.transport);
13940
- this.screenshotCollector.captureAndSend(this.sessionId, window.location.href);
13941
- if (this.config.debug) {
13942
- console.log('[DevSkin] Heatmap collection enabled (always on)');
13943
- }
13944
- // Initialize session recording with rrweb
13945
- if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
13946
- // Use RRWebRecorder for complete DOM recording
13947
- this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
13948
- enabled: true,
13949
- sampleRate: this.config.sessionRecording.sampling || 0.5,
13950
- blockClass: 'rr-block',
13951
- ignoreClass: this.config.sessionRecording.ignoreClass || 'rr-ignore',
13952
- maskAllInputs: this.config.sessionRecording.maskAllInputs !== undefined
13953
- ? this.config.sessionRecording.maskAllInputs
13954
- : true,
13955
- maskInputOptions: {
13956
- password: true,
13957
- email: true,
13958
- tel: true,
13959
- },
13960
- recordCanvas: this.config.sessionRecording.recordCanvas || false,
13961
- collectFonts: true,
13962
- inlineStylesheet: true,
13963
- checkoutEveryNms: 5 * 60 * 1000, // Every 5 minutes
13964
- checkoutEveryNth: 200, // Every 200 events
13965
- }, (events) => {
13966
- var _a;
13967
- // Send rrweb events to backend
13968
- (_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
13969
- });
13970
- // Wait 500ms before starting recording to ensure session is created in backend
13971
- // This prevents race condition where FullSnapshot is sent before session exists
13972
- setTimeout(() => {
13973
- var _a, _b;
13974
- (_a = this.rrwebRecorder) === null || _a === void 0 ? void 0 : _a.start();
13900
+ // Wait for session creation to complete before starting collectors
13901
+ this.startSession().then(() => {
13902
+ // Session created, now safe to start collectors that send data
13903
+ var _a, _b;
13904
+ if (this.config.captureWebVitals) {
13905
+ this.performanceCollector = new PerformanceCollector(this.config, this.transport);
13906
+ this.performanceCollector.start();
13907
+ }
13908
+ if (this.config.captureErrors) {
13909
+ this.errorCollector = new ErrorCollector(this.config, this.transport);
13910
+ this.errorCollector.start();
13911
+ }
13912
+ if (this.config.captureNetworkRequests) {
13913
+ this.networkCollector = new NetworkCollector(this.config, this.transport);
13914
+ this.networkCollector.start();
13915
+ }
13916
+ // Initialize heatmap collector - SEMPRE habilitado
13917
+ // Merge default heatmap config with user config
13918
+ const heatmapConfig = Object.assign({ enabled: true, trackClicks: true, trackScroll: true, trackMouseMovement: true, mouseMoveSampling: 0.1 }, this.config.heatmapOptions);
13919
+ this.config.heatmapOptions = heatmapConfig;
13920
+ this.heatmapCollector = new HeatmapCollector(this.config, this.transport);
13921
+ this.heatmapCollector.start();
13922
+ // Initialize screenshot collector and capture page
13923
+ this.screenshotCollector = new ScreenshotCollector(this.config, this.transport);
13924
+ this.screenshotCollector.captureAndSend(this.sessionId, window.location.href);
13925
+ if (this.config.debug) {
13926
+ console.log('[DevSkin] Heatmap collection enabled (always on)');
13927
+ }
13928
+ // Initialize session recording with rrweb
13929
+ if ((_a = this.config.sessionRecording) === null || _a === void 0 ? void 0 : _a.enabled) {
13930
+ // Use RRWebRecorder for complete DOM recording
13931
+ this.rrwebRecorder = new RRWebRecorder(this.sessionId, {
13932
+ enabled: true,
13933
+ sampleRate: this.config.sessionRecording.sampling || 0.5,
13934
+ blockClass: 'rr-block',
13935
+ ignoreClass: this.config.sessionRecording.ignoreClass || 'rr-ignore',
13936
+ maskAllInputs: this.config.sessionRecording.maskAllInputs !== undefined
13937
+ ? this.config.sessionRecording.maskAllInputs
13938
+ : true,
13939
+ maskInputOptions: {
13940
+ password: true,
13941
+ email: true,
13942
+ tel: true,
13943
+ },
13944
+ recordCanvas: this.config.sessionRecording.recordCanvas || false,
13945
+ collectFonts: true,
13946
+ inlineStylesheet: true,
13947
+ checkoutEveryNms: 5 * 60 * 1000, // Every 5 minutes
13948
+ checkoutEveryNth: 200, // Every 200 events
13949
+ }, (events) => {
13950
+ var _a;
13951
+ // Send rrweb events to backend
13952
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.sendRecordingEvents(this.sessionId, events);
13953
+ });
13954
+ // Start recording immediately (session already created)
13955
+ this.rrwebRecorder.start();
13975
13956
  if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
13976
13957
  console.log('[DevSkin] RRWeb recording started for session:', this.sessionId);
13977
13958
  }
13978
- }, 500);
13979
- }
13980
- // Track initial page view
13981
- this.trackPageView();
13959
+ }
13960
+ // Track initial page view
13961
+ this.trackPageView();
13962
+ }).catch((err) => {
13963
+ console.error('[DevSkin] Failed to create session:', err);
13964
+ });
13982
13965
  // Track page visibility changes
13983
13966
  this.setupVisibilityTracking();
13984
13967
  // Track page unload
@@ -14103,32 +14086,39 @@ class DevSkinSDK {
14103
14086
  * Private methods
14104
14087
  */
14105
14088
  startSession() {
14106
- var _a, _b, _c;
14107
- // Check if there's an active session (stored in sessionStorage to persist across page navigations)
14108
- const existingSessionId = sessionStorage.getItem('devskin_session_id');
14109
- const existingSessionStart = sessionStorage.getItem('devskin_session_start');
14110
- if (existingSessionId && existingSessionStart) {
14111
- // Resume existing session
14112
- this.sessionId = existingSessionId;
14113
- this.sessionStartTime = parseInt(existingSessionStart, 10);
14114
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.debug) {
14115
- console.log('[DevSkin] Resuming existing session:', this.sessionId);
14089
+ return __awaiter$1(this, void 0, void 0, function* () {
14090
+ var _a, _b, _c, _d, _e;
14091
+ // Check if there's an active session (stored in sessionStorage to persist across page navigations)
14092
+ const existingSessionId = sessionStorage.getItem('devskin_session_id');
14093
+ const existingSessionStart = sessionStorage.getItem('devskin_session_start');
14094
+ if (existingSessionId && existingSessionStart) {
14095
+ // Resume existing session
14096
+ this.sessionId = existingSessionId;
14097
+ this.sessionStartTime = parseInt(existingSessionStart, 10);
14098
+ // Set sessionId in transport so it can be added to network/performance requests
14099
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.setSessionId(this.sessionId);
14100
+ if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debug) {
14101
+ console.log('[DevSkin] Resuming existing session:', this.sessionId);
14102
+ }
14103
+ // Send page view but DON'T create a new session
14104
+ // The session is already created, just continue it
14105
+ return;
14116
14106
  }
14117
- // Send page view but DON'T create a new session
14118
- // The session is already created, just continue it
14119
- return;
14120
- }
14121
- // Create new session
14122
- this.sessionId = this.generateId();
14123
- this.sessionStartTime = Date.now();
14124
- // Store in sessionStorage (persists across page navigations in same tab)
14125
- sessionStorage.setItem('devskin_session_id', this.sessionId);
14126
- sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
14127
- const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
14128
- (_b = this.transport) === null || _b === void 0 ? void 0 : _b.startSession(sessionData);
14129
- if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.debug) {
14130
- console.log('[DevSkin] New session created:', this.sessionId);
14131
- }
14107
+ // Create new session
14108
+ this.sessionId = this.generateId();
14109
+ this.sessionStartTime = Date.now();
14110
+ // Store in sessionStorage (persists across page navigations in same tab)
14111
+ sessionStorage.setItem('devskin_session_id', this.sessionId);
14112
+ sessionStorage.setItem('devskin_session_start', this.sessionStartTime.toString());
14113
+ // Set sessionId in transport so it can be added to network/performance requests
14114
+ (_c = this.transport) === null || _c === void 0 ? void 0 : _c.setSessionId(this.sessionId);
14115
+ const sessionData = Object.assign({ sessionId: this.sessionId, userId: this.userId || undefined, anonymousId: this.anonymousId, startedAt: new Date().toISOString(), platform: 'web' }, this.getContextData());
14116
+ // CRITICAL: Await session creation to ensure it exists before sending metrics/requests
14117
+ yield ((_d = this.transport) === null || _d === void 0 ? void 0 : _d.startSession(sessionData));
14118
+ if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.debug) {
14119
+ console.log('[DevSkin] New session created:', this.sessionId);
14120
+ }
14121
+ });
14132
14122
  }
14133
14123
  getContextData() {
14134
14124
  var _a, _b, _c, _d;