userlens-session-recorder 1.1.0 → 1.2.1

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/index.cjs.js CHANGED
@@ -20650,94 +20650,133 @@ const uploadSessionEvents = async (userId, sessionUuid, events, chunkTimestamp)
20650
20650
  return "ok";
20651
20651
  };
20652
20652
 
20653
- var _SessionRecorder_instances, _SessionRecorder_trackEventsThrottled, _SessionRecorder_initRecorder, _SessionRecorder_isUserInteraction, _SessionRecorder_handleEvent, _SessionRecorder_resetSession, _SessionRecorder_createSession, _SessionRecorder_handleVisibilityChange, _SessionRecorder_initFocusListener, _SessionRecorder_throttle, _SessionRecorder_trackEvents, _SessionRecorder_clearEvents, _SessionRecorder_removeLocalSessionData;
20653
+ var _SessionRecorder_instances, _SessionRecorder_trackEventsThrottled, _SessionRecorder_log, _SessionRecorder_initRecorder, _SessionRecorder_isUserInteraction, _SessionRecorder_handleEvent, _SessionRecorder_resetSession, _SessionRecorder_createSession, _SessionRecorder_handleVisibilityChange, _SessionRecorder_initFocusListener, _SessionRecorder_throttle, _SessionRecorder_trackEvents, _SessionRecorder_clearEvents, _SessionRecorder_removeLocalSessionData;
20654
20654
  class SessionRecorder {
20655
20655
  constructor(config) {
20656
- var _a, _b;
20656
+ var _a, _b, _c;
20657
20657
  _SessionRecorder_instances.add(this);
20658
20658
  this.sessionEvents = [];
20659
20659
  this.rrwebStop = null;
20660
+ this.debug = false;
20660
20661
  _SessionRecorder_trackEventsThrottled.set(this, void 0);
20661
20662
  _SessionRecorder_handleVisibilityChange.set(this, () => {
20662
- if (document.visibilityState === "visible") {
20663
- if (!this.rrwebStop)
20664
- return;
20665
- const now = Date.now();
20666
- const lastActive = Number(localStorage.getItem("userlensSessionLastActive"));
20667
- if (lastActive && now - lastActive > this.TIMEOUT) {
20668
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_resetSession).call(this);
20663
+ try {
20664
+ if (document.visibilityState === "visible") {
20665
+ if (!this.rrwebStop)
20666
+ return;
20667
+ const now = Date.now();
20668
+ const lastActive = Number(localStorage.getItem("userlensSessionLastActive"));
20669
+ if (lastActive && now - lastActive > this.TIMEOUT) {
20670
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_resetSession).call(this);
20671
+ }
20672
+ takeFullSnapshot(true);
20669
20673
  }
20670
- takeFullSnapshot(true);
20674
+ }
20675
+ catch (err) {
20676
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Visibility change handling failed", err);
20671
20677
  }
20672
20678
  });
20673
- if (typeof window === "undefined") {
20674
- return;
20675
- }
20676
- if (config.mode === "manual") {
20677
- // Manual mode
20678
- this.mode = "manual";
20679
- if (!config.onEvents || typeof config.onEvents !== "function") {
20680
- console.error("Userlens SDK Error: onEvents callback is required in manual mode");
20679
+ try {
20680
+ // Check for browser environment
20681
+ if (typeof window === "undefined")
20681
20682
  return;
20682
- }
20683
- this.onEvents = config.onEvents;
20684
- }
20685
- else {
20686
- // Auto mode (default)
20687
- this.mode = "auto";
20688
- if (!((_a = config.WRITE_CODE) === null || _a === void 0 ? void 0 : _a.trim())) {
20689
- console.error("Userlens SDK Error: WRITE_CODE is required and must be a string");
20683
+ if (typeof document === "undefined")
20690
20684
  return;
20691
- }
20692
- if (!((_b = config.userId) === null || _b === void 0 ? void 0 : _b.trim())) {
20693
- console.error("Userlens SDK Error: userId is required to identify session user.");
20685
+ if (typeof localStorage === "undefined")
20686
+ return;
20687
+ // Check for required APIs
20688
+ if (typeof CompressionStream === "undefined")
20689
+ return;
20690
+ if (typeof MutationObserver === "undefined")
20691
+ return;
20692
+ if (typeof TextEncoder === "undefined")
20694
20693
  return;
20694
+ if (typeof fetch === "undefined")
20695
+ return;
20696
+ if (typeof Blob === "undefined")
20697
+ return;
20698
+ if (typeof crypto === "undefined" || !crypto.getRandomValues)
20699
+ return;
20700
+ // Check localStorage actually works (can be blocked even if defined)
20701
+ const testKey = "__userlens_test__";
20702
+ localStorage.setItem(testKey, "1");
20703
+ localStorage.removeItem(testKey);
20704
+ // Set debug mode early so it's available for error logging
20705
+ this.debug = (_a = config.debug) !== null && _a !== void 0 ? _a : false;
20706
+ if (config.mode === "manual") {
20707
+ this.mode = "manual";
20708
+ if (!config.onEvents || typeof config.onEvents !== "function") {
20709
+ return;
20710
+ }
20711
+ this.onEvents = config.onEvents;
20695
20712
  }
20696
- saveWriteCode(config.WRITE_CODE);
20697
- this.userId = config.userId;
20698
- }
20699
- const { recordingOptions = {} } = config;
20700
- const { TIMEOUT = 30 * 60 * 1000, BUFFER_SIZE = 10, maskingOptions = ["passwords"], } = recordingOptions;
20701
- this.TIMEOUT = TIMEOUT;
20702
- this.BUFFER_SIZE = BUFFER_SIZE;
20703
- this.maskingOptions = maskingOptions;
20704
- this.sessionEvents = [];
20705
- __classPrivateFieldSet(this, _SessionRecorder_trackEventsThrottled, __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_throttle).call(this, () => {
20706
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_trackEvents).call(this);
20707
- }, 5000), "f");
20708
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_initRecorder).call(this);
20713
+ else {
20714
+ this.mode = "auto";
20715
+ if (!((_b = config.WRITE_CODE) === null || _b === void 0 ? void 0 : _b.trim()) || !((_c = config.userId) === null || _c === void 0 ? void 0 : _c.trim())) {
20716
+ return;
20717
+ }
20718
+ saveWriteCode(config.WRITE_CODE);
20719
+ this.userId = config.userId;
20720
+ }
20721
+ const { recordingOptions = {} } = config;
20722
+ const { TIMEOUT = 30 * 60 * 1000, BUFFER_SIZE = 10, maskingOptions = ["passwords"], } = recordingOptions;
20723
+ this.TIMEOUT = TIMEOUT;
20724
+ this.BUFFER_SIZE = BUFFER_SIZE;
20725
+ this.maskingOptions = maskingOptions;
20726
+ this.sessionEvents = [];
20727
+ __classPrivateFieldSet(this, _SessionRecorder_trackEventsThrottled, __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_throttle).call(this, () => {
20728
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_trackEvents).call(this);
20729
+ }, 5000), "f");
20730
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_initRecorder).call(this);
20731
+ }
20732
+ catch (err) {
20733
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Initialization failed", err);
20734
+ return;
20735
+ }
20709
20736
  }
20710
20737
  getSessionId() {
20711
20738
  return this.sessionUuid;
20712
20739
  }
20713
20740
  stop() {
20714
- if (!this.rrwebStop) {
20715
- return;
20741
+ try {
20742
+ if (!this.rrwebStop) {
20743
+ return;
20744
+ }
20745
+ this.rrwebStop();
20746
+ this.rrwebStop = null;
20747
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
20748
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_removeLocalSessionData).call(this);
20749
+ window.removeEventListener("visibilitychange", __classPrivateFieldGet(this, _SessionRecorder_handleVisibilityChange, "f"));
20750
+ }
20751
+ catch (err) {
20752
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Stop failed", err);
20716
20753
  }
20717
- this.rrwebStop();
20718
- this.rrwebStop = null;
20719
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
20720
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_removeLocalSessionData).call(this);
20721
- window.removeEventListener("visibilitychange", __classPrivateFieldGet(this, _SessionRecorder_handleVisibilityChange, "f"));
20722
20754
  }
20723
20755
  }
20724
- _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_handleVisibilityChange = new WeakMap(), _SessionRecorder_instances = new WeakSet(), _SessionRecorder_initRecorder = function _SessionRecorder_initRecorder() {
20756
+ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_handleVisibilityChange = new WeakMap(), _SessionRecorder_instances = new WeakSet(), _SessionRecorder_log = function _SessionRecorder_log(message, error) {
20757
+ if (!this.debug)
20758
+ return;
20759
+ if (error) {
20760
+ console.error(`[Userlens Session] ${message}`, error);
20761
+ }
20762
+ else {
20763
+ console.log(`[Userlens Session] ${message}`);
20764
+ }
20765
+ }, _SessionRecorder_initRecorder = function _SessionRecorder_initRecorder() {
20725
20766
  if (this.rrwebStop)
20726
20767
  return;
20727
20768
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_createSession).call(this);
20728
- setTimeout(() => {
20729
- this.rrwebStop = record({
20730
- emit: (event, isCheckout) => {
20731
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_handleEvent).call(this, event, isCheckout);
20732
- },
20733
- maskAllInputs: this.maskingOptions.includes("all"),
20734
- maskInputOptions: {
20735
- password: this.maskingOptions.includes("passwords"),
20736
- },
20737
- plugins: [getRecordConsolePlugin()],
20738
- checkoutEveryNth: 100,
20739
- });
20740
- }, 100);
20769
+ this.rrwebStop = record({
20770
+ emit: (event, isCheckout) => {
20771
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_handleEvent).call(this, event, isCheckout);
20772
+ },
20773
+ maskAllInputs: this.maskingOptions.includes("all"),
20774
+ maskInputOptions: {
20775
+ password: this.maskingOptions.includes("passwords"),
20776
+ },
20777
+ plugins: [getRecordConsolePlugin()],
20778
+ checkoutEveryNth: 100,
20779
+ });
20741
20780
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_initFocusListener).call(this);
20742
20781
  }, _SessionRecorder_isUserInteraction = function _SessionRecorder_isUserInteraction(event) {
20743
20782
  var _a;
@@ -20748,29 +20787,34 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_handleVi
20748
20787
  return false;
20749
20788
  }, _SessionRecorder_handleEvent = function _SessionRecorder_handleEvent(event, _isCheckout) {
20750
20789
  var _a;
20751
- const now = Date.now();
20752
- const lastActive = Number(localStorage.getItem("userlensSessionLastActive"));
20753
- // check inactivity timeout
20754
- if (lastActive && now - lastActive > this.TIMEOUT) {
20755
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_resetSession).call(this);
20756
- takeFullSnapshot(true);
20757
- }
20758
- // only update lastActive on actual user interactions, not DOM mutations
20759
- if (__classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_isUserInteraction).call(this, event)) {
20760
- localStorage.setItem("userlensSessionLastActive", now.toString());
20790
+ try {
20791
+ const now = Date.now();
20792
+ const lastActive = Number(localStorage.getItem("userlensSessionLastActive"));
20793
+ // check inactivity timeout
20794
+ if (lastActive && now - lastActive > this.TIMEOUT) {
20795
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_resetSession).call(this);
20796
+ takeFullSnapshot(true);
20797
+ }
20798
+ // only update lastActive on actual user interactions, not DOM mutations
20799
+ if (__classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_isUserInteraction).call(this, event)) {
20800
+ localStorage.setItem("userlensSessionLastActive", now.toString());
20801
+ }
20802
+ this.sessionEvents.push(event);
20803
+ if (this.sessionEvents.length >= this.BUFFER_SIZE) {
20804
+ (_a = __classPrivateFieldGet(this, _SessionRecorder_trackEventsThrottled, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
20805
+ }
20761
20806
  }
20762
- this.sessionEvents.push(event);
20763
- if (this.sessionEvents.length >= this.BUFFER_SIZE) {
20764
- (_a = __classPrivateFieldGet(this, _SessionRecorder_trackEventsThrottled, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
20807
+ catch (err) {
20808
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Event handling failed", err);
20765
20809
  }
20766
20810
  }, _SessionRecorder_resetSession = function _SessionRecorder_resetSession() {
20767
20811
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_removeLocalSessionData).call(this);
20768
20812
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
20769
20813
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_createSession).call(this);
20770
20814
  }, _SessionRecorder_createSession = function _SessionRecorder_createSession() {
20815
+ const now = Date.now();
20771
20816
  const lastActive = Number(localStorage.getItem("userlensSessionLastActive"));
20772
20817
  const storedUuid = localStorage.getItem("userlensSessionUuid");
20773
- const now = Date.now();
20774
20818
  const isExpired = !lastActive || now - lastActive > this.TIMEOUT;
20775
20819
  if (!storedUuid || isExpired) {
20776
20820
  this.sessionUuid = generateUuid();
@@ -20792,35 +20836,28 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_handleVi
20792
20836
  }
20793
20837
  };
20794
20838
  }, _SessionRecorder_trackEvents = async function _SessionRecorder_trackEvents() {
20795
- if (this.sessionEvents.length === 0) {
20796
- return;
20797
- }
20798
- const chunkTimestamp = this.sessionEvents[this.sessionEvents.length - 1].timestamp;
20799
- const events = [...this.sessionEvents];
20800
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
20801
- if (this.mode === "manual") {
20802
- // Manual mode - push events to callback
20803
- if (this.onEvents) {
20804
- try {
20839
+ try {
20840
+ if (this.sessionEvents.length === 0) {
20841
+ return;
20842
+ }
20843
+ const chunkTimestamp = this.sessionEvents[this.sessionEvents.length - 1].timestamp;
20844
+ const events = [...this.sessionEvents];
20845
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
20846
+ if (this.mode === "manual") {
20847
+ if (this.onEvents) {
20805
20848
  this.onEvents({
20806
20849
  sessionId: this.sessionUuid,
20807
20850
  events,
20808
20851
  chunkTimestamp,
20809
20852
  });
20810
20853
  }
20811
- catch (_) {
20812
- // Don't stop on callback errors in manual mode
20813
- }
20814
20854
  }
20815
- }
20816
- else {
20817
- // Auto mode - upload to Userlens backend
20818
- try {
20855
+ else {
20819
20856
  await uploadSessionEvents(this.userId, this.sessionUuid, events, chunkTimestamp);
20820
20857
  }
20821
- catch (_) {
20822
- this.stop();
20823
- }
20858
+ }
20859
+ catch (err) {
20860
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Event tracking failed", err);
20824
20861
  }
20825
20862
  }, _SessionRecorder_clearEvents = function _SessionRecorder_clearEvents() {
20826
20863
  this.sessionEvents = [];