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