@devskin/browser-sdk 1.0.14 → 1.0.16

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.
@@ -5565,24 +5565,12 @@ class RRWebRecorder {
5565
5565
  return;
5566
5566
  }
5567
5567
  try {
5568
- console.log('[RRWeb] Starting session recording:', this.sessionId);
5569
- console.log('[RRWeb] SDK Version: 1.0.14');
5570
5568
  this.stopFn = record({
5571
5569
  emit: (event) => {
5572
- // DEBUG: Log ALL event types to diagnose issue
5573
- if (!this.hasFullSnapshot) {
5574
- console.log('[RRWeb] Event captured:', {
5575
- type: event.type,
5576
- timestamp: event.timestamp,
5577
- hasData: !!event.data
5578
- });
5579
- }
5580
5570
  this.events.push(event);
5581
5571
  // Check if this is a FullSnapshot (type 2)
5582
5572
  if (event.type === 2) {
5583
5573
  this.hasFullSnapshot = true;
5584
- console.log('[RRWeb] ✅ FullSnapshot captured! Sending immediately...');
5585
- console.log('[RRWeb] FullSnapshot data keys:', Object.keys(event.data || {}));
5586
5574
  // Send immediately to ensure FullSnapshot reaches backend first
5587
5575
  this.flush();
5588
5576
  }
@@ -5636,29 +5624,19 @@ class RRWebRecorder {
5636
5624
  // Safety check: After 2 seconds, force a full snapshot if none captured
5637
5625
  setTimeout(() => {
5638
5626
  if (!this.hasFullSnapshot) {
5639
- console.warn('[RRWeb] ⚠️ No FullSnapshot captured after 2 seconds!');
5640
- console.warn('[RRWeb] Events captured so far:', this.events.length);
5641
- console.warn('[RRWeb] Event types:', this.events.map(e => e.type));
5642
- console.warn('[RRWeb] Forcing a full snapshot via record.takeFullSnapshot()...');
5643
5627
  // Try to force a full snapshot using rrweb's API
5644
5628
  try {
5645
- // Call record.takeFullSnapshot() to force a full snapshot
5646
5629
  record.takeFullSnapshot();
5647
- console.log('[RRWeb] ✅ Manual FullSnapshot triggered!');
5648
5630
  }
5649
5631
  catch (error) {
5650
- console.error('[RRWeb] Failed to force snapshot:', error);
5651
5632
  // If we have events but no FullSnapshot, flush anyway to not lose data
5652
- // But warn that replay may not work correctly
5653
5633
  if (this.events.length > 0) {
5654
- console.warn('[RRWeb] Flushing existing events WITHOUT FullSnapshot...');
5655
5634
  this.hasFullSnapshot = true; // Set to true to allow flushing
5656
5635
  this.flush();
5657
5636
  }
5658
5637
  }
5659
5638
  }
5660
5639
  }, 2000);
5661
- console.log('[RRWeb] Recording started successfully');
5662
5640
  }
5663
5641
  catch (error) {
5664
5642
  console.error('[RRWeb] Failed to start recording:', error);
@@ -5668,17 +5646,13 @@ class RRWebRecorder {
5668
5646
  if (this.stopFn) {
5669
5647
  this.stopFn();
5670
5648
  this.stopFn = null;
5671
- console.log('[RRWeb] Recording stopped');
5672
5649
  }
5673
5650
  if (this.flushInterval) {
5674
5651
  clearInterval(this.flushInterval);
5675
5652
  this.flushInterval = null;
5676
5653
  }
5677
- // Flush remaining events (even without FullSnapshot, to not lose data)
5654
+ // Flush remaining events
5678
5655
  if (this.events.length > 0) {
5679
- if (!this.hasFullSnapshot) {
5680
- console.warn('[RRWeb] Flushing events without FullSnapshot - recording may not replay correctly');
5681
- }
5682
5656
  this.flush();
5683
5657
  }
5684
5658
  }
@@ -5687,12 +5661,6 @@ class RRWebRecorder {
5687
5661
  return;
5688
5662
  const eventsToSend = [...this.events];
5689
5663
  this.events = [];
5690
- // Log event types being sent
5691
- const typeCounts = {};
5692
- eventsToSend.forEach(e => {
5693
- typeCounts[e.type] = (typeCounts[e.type] || 0) + 1;
5694
- });
5695
- console.log('[RRWeb] Flushing events:', typeCounts);
5696
5664
  if (this.onEventsReady) {
5697
5665
  this.onEventsReady(eventsToSend);
5698
5666
  }
@@ -5750,11 +5718,6 @@ class Transport {
5750
5718
  }
5751
5719
  sendRecordingEvents(sessionId, events) {
5752
5720
  return __awaiter$1(this, void 0, void 0, function* () {
5753
- // DEBUG: Log event types being sent
5754
- const eventTypes = events.reduce((acc, e) => {
5755
- acc[e.type] = (acc[e.type] || 0) + 1;
5756
- return acc;
5757
- }, {});
5758
5721
  // Calculate payload size
5759
5722
  const payload = {
5760
5723
  session_id: sessionId,
@@ -5764,10 +5727,6 @@ class Transport {
5764
5727
  appId: this.config.appId,
5765
5728
  };
5766
5729
  const payloadSize = new Blob([JSON.stringify(payload)]).size;
5767
- const payloadSizeMB = (payloadSize / 1024 / 1024).toFixed(2);
5768
- console.log(`[DevSkin SDK] Sending ${events.length} recording events:`, eventTypes);
5769
- console.log(`[DevSkin SDK] Payload size: ${payloadSizeMB} MB (${payloadSize} bytes)`);
5770
- console.log(`[DevSkin SDK] First 3 events:`, events.slice(0, 3).map(e => ({ type: e.type, timestamp: e.timestamp })));
5771
5730
  // Check if this batch contains FullSnapshot (type 2)
5772
5731
  const hasFullSnapshot = events.some(e => e.type === 2);
5773
5732
  const maxRetries = hasFullSnapshot ? 3 : 1; // Retry FullSnapshot batches up to 3 times
@@ -5775,25 +5734,35 @@ class Transport {
5775
5734
  let lastError = null;
5776
5735
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
5777
5736
  try {
5778
- yield this.sendToBackend('/v1/rum/recordings', {
5779
- session_id: sessionId,
5780
- events,
5781
- timestamp: new Date().toISOString(),
5782
- });
5783
- console.log(`[DevSkin SDK] ✅ Recording events sent successfully${attempt > 1 ? ` (attempt ${attempt})` : ''}`);
5737
+ // Use XMLHttpRequest for large payloads (more reliable than fetch for large data)
5738
+ if (payloadSize > 100000) { // > 100KB
5739
+ yield this.sendToBackendXHR('/v1/rum/recordings', {
5740
+ session_id: sessionId,
5741
+ events,
5742
+ timestamp: new Date().toISOString(),
5743
+ });
5744
+ }
5745
+ else {
5746
+ yield this.sendToBackend('/v1/rum/recordings', {
5747
+ session_id: sessionId,
5748
+ events,
5749
+ timestamp: new Date().toISOString(),
5750
+ });
5751
+ }
5784
5752
  return; // Success, exit
5785
5753
  }
5786
5754
  catch (error) {
5787
5755
  lastError = error;
5788
5756
  if (attempt < maxRetries) {
5789
5757
  const delay = attempt * 1000; // 1s, 2s, 3s...
5790
- console.warn(`[DevSkin SDK] ⚠️ Failed to send recording events (attempt ${attempt}/${maxRetries}), retrying in ${delay}ms...`);
5791
5758
  yield new Promise(resolve => setTimeout(resolve, delay));
5792
5759
  }
5793
5760
  }
5794
5761
  }
5795
5762
  // All retries failed
5796
- console.error(`[DevSkin SDK] ❌ Failed to send recording events after ${maxRetries} attempts:`, lastError);
5763
+ if (this.config.debug) {
5764
+ console.error(`[DevSkin SDK] Failed to send recording events after ${maxRetries} attempts:`, lastError);
5765
+ }
5797
5766
  });
5798
5767
  }
5799
5768
  sendHeatmapData(heatmapData) {
@@ -5854,6 +5823,56 @@ class Transport {
5854
5823
  return '/v1/analytics/events';
5855
5824
  }
5856
5825
  }
5826
+ sendToBackendXHR(endpoint, data) {
5827
+ return __awaiter$1(this, void 0, void 0, function* () {
5828
+ const url = `${this.apiUrl}${endpoint}`;
5829
+ const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey, appId: this.config.appId, environment: this.config.environment, release: this.config.release });
5830
+ // Apply beforeSend hook if provided
5831
+ if (this.config.beforeSend) {
5832
+ const processed = this.config.beforeSend(payload);
5833
+ if (!processed) {
5834
+ // Hook returned null, don't send
5835
+ return;
5836
+ }
5837
+ }
5838
+ return new Promise((resolve, reject) => {
5839
+ const xhr = new XMLHttpRequest();
5840
+ xhr.open('POST', url, true);
5841
+ xhr.setRequestHeader('Content-Type', 'application/json');
5842
+ xhr.setRequestHeader('Authorization', `Bearer ${this.config.apiKey}`);
5843
+ xhr.onload = () => {
5844
+ if (xhr.status >= 200 && xhr.status < 300) {
5845
+ if (this.config.debug) {
5846
+ console.log('[DevSkin] Data sent successfully via XHR:', endpoint);
5847
+ }
5848
+ resolve();
5849
+ }
5850
+ else {
5851
+ console.error('[DevSkin] XHR HTTP Error:', xhr.status, xhr.responseText);
5852
+ reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
5853
+ }
5854
+ };
5855
+ xhr.onerror = () => {
5856
+ console.error('[DevSkin] XHR network error:', endpoint);
5857
+ reject(new Error('Network error'));
5858
+ };
5859
+ xhr.ontimeout = () => {
5860
+ console.error('[DevSkin] XHR timeout:', endpoint);
5861
+ reject(new Error('Request timeout'));
5862
+ };
5863
+ // Set a generous timeout for large payloads (30 seconds)
5864
+ xhr.timeout = 30000;
5865
+ try {
5866
+ const body = JSON.stringify(payload);
5867
+ xhr.send(body);
5868
+ }
5869
+ catch (error) {
5870
+ console.error('[DevSkin] Failed to send XHR request:', error);
5871
+ reject(error);
5872
+ }
5873
+ });
5874
+ });
5875
+ }
5857
5876
  sendToBackend(endpoint_1, data_1) {
5858
5877
  return __awaiter$1(this, arguments, void 0, function* (endpoint, data, useBeacon = false) {
5859
5878
  const url = `${this.apiUrl}${endpoint}`;