@checksum-ai/runtime 1.1.50-beta → 1.1.52

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/checksumlib.js CHANGED
@@ -7598,9 +7598,9 @@
7598
7598
  case Node.TEXT_NODE:
7599
7599
  return node2.nodeValue;
7600
7600
  case Node.CDATA_SECTION_NODE:
7601
- return includeCDATA ? `<![CDATA[${node2.nodeValue}]]>` : "";
7601
+ return includeCDATA && node2.nodeValue.trim().length > 0 ? `<![CDATA[${node2.nodeValue}]]>` : "";
7602
7602
  case Node.COMMENT_NODE:
7603
- return includeComments ? `<!--${node2.nodeValue}-->` : "";
7603
+ return includeComments && node2.nodeValue.trim().length > 0 ? `<!--${node2.nodeValue}-->` : "";
7604
7604
  default:
7605
7605
  return "";
7606
7606
  }
@@ -29412,52 +29412,14 @@
29412
29412
 
29413
29413
  // ../browser-lib/src/session-record-replay/session-replayer.ts
29414
29414
  var import_await_sleep3 = __toESM(require_await_sleep());
29415
+ var DEBUG_MODE = false;
29415
29416
  var SessionReplayer = class {
29416
29417
  constructor(config = {}) {
29417
- this.events = [];
29418
- this.numberOfCastedEvents = 0;
29419
- this.isLive = true;
29420
- this.liveEvents = [];
29421
- // private currentTraveledTimestamp: number = undefined;
29422
- this.currentTraveledNumberOfEvents = void 0;
29418
+ // array of events to init replayer
29419
+ this.eventsBuffer = [];
29423
29420
  this.config = {
29424
29421
  enableInteract: false
29425
29422
  };
29426
- this.useTimestampCompression = true;
29427
- // getCurrentTraveledTimestamp = () => {
29428
- // return this.isLive ? undefined : this.currentTraveledTimestamp;
29429
- // };
29430
- this.fastForward = /* @__PURE__ */ __name(async (newEvents, force = false) => {
29431
- let sortedNewEvents = newEvents.sort(
29432
- (e1, e2) => this.getOriginalTimestamp(e1) - this.getOriginalTimestamp(e2)
29433
- );
29434
- if (this.useTimestampCompression) {
29435
- const timestamp = Date.now();
29436
- sortedNewEvents = sortedNewEvents.map((event, eventIndex) => ({
29437
- ...event,
29438
- timestamp: timestamp + eventIndex,
29439
- originalTimestamp: this.getOriginalTimestamp(event)
29440
- }));
29441
- }
29442
- if (!force && !this.isLive) {
29443
- this.liveEvents.push(...sortedNewEvents);
29444
- return;
29445
- }
29446
- this.events = [...this.events, ...sortedNewEvents];
29447
- const promise = new Promise((resolve2) => {
29448
- this.onEventCast = (event) => {
29449
- this.numberOfCastedEvents++;
29450
- if (this.numberOfCastedEvents === this.events.length) {
29451
- this.onEventCast = void 0;
29452
- resolve2();
29453
- }
29454
- };
29455
- });
29456
- for (const event of sortedNewEvents) {
29457
- this.replayer.addEvent(event);
29458
- }
29459
- return promise;
29460
- }, "fastForward");
29461
29423
  this.stop = /* @__PURE__ */ __name(() => {
29462
29424
  try {
29463
29425
  if (this.replayer) {
@@ -29467,234 +29429,146 @@
29467
29429
  console.warn("Error destroying replayer", e2);
29468
29430
  }
29469
29431
  }, "stop");
29470
- this.getOriginalTimestamp = /* @__PURE__ */ __name((event) => {
29471
- return event.originalTimestamp ?? event.timestamp;
29472
- }, "getOriginalTimestamp");
29473
- this.trimEventsToLastCheckout = /* @__PURE__ */ __name((events) => {
29474
- const lastCheckoutEventIndex = events.reduce(
29475
- (lastCheckoutEventIndex2, event, index2) => {
29476
- return event.isCheckout && event.type === EventType.Meta ? index2 : lastCheckoutEventIndex2;
29477
- },
29478
- void 0
29479
- );
29480
- let trimmedEvents = events;
29481
- if (lastCheckoutEventIndex !== void 0) {
29482
- trimmedEvents = events.slice(lastCheckoutEventIndex);
29483
- }
29484
- const castedEvents = lastCheckoutEventIndex !== void 0 ? this.liveEvents.slice(0, lastCheckoutEventIndex) : [];
29485
- return { trimmedEvents, castedEvents, lastCheckoutEventIndex };
29486
- }, "trimEventsToLastCheckout");
29487
29432
  this.getNodeById = /* @__PURE__ */ __name((id) => {
29488
29433
  return this.replayer.getMirror().getNode(id);
29489
29434
  }, "getNodeById");
29490
29435
  this.getMeta = /* @__PURE__ */ __name((node2) => {
29491
- return this.replayer.getMirror().getMeta(node2);
29436
+ return this.replayer?.getMirror()?.getMeta(node2);
29492
29437
  }, "getMeta");
29438
+ // store each event for debug and check ids of events and timestamps, if one exists
29439
+ this.debugData = {
29440
+ active: false,
29441
+ events: [],
29442
+ castedEvents: []
29443
+ };
29493
29444
  this.config = { ...this.config, ...config };
29494
- this.goBackWithEvents = this.goBackWithEvents_native;
29495
29445
  }
29496
29446
  static {
29497
29447
  __name(this, "SessionReplayer");
29498
29448
  }
29499
- makeReplayerConfig(live, { speed = 8 } = {}) {
29449
+ makeReplayerConfig() {
29500
29450
  const playerConfig = {
29501
29451
  mouseTail: false,
29502
29452
  pauseAnimation: false,
29503
- speed,
29453
+ speed: 64,
29504
29454
  triggerFocus: true,
29505
29455
  UNSAFE_replayCanvas: true,
29506
- liveMode: live,
29456
+ liveMode: true,
29507
29457
  showDebug: false,
29508
- skipInactive: true,
29509
- inactivePeriodThreshold: 100
29458
+ skipInactive: true
29459
+ // inactivePeriodThreshold: 100,
29510
29460
  };
29511
29461
  if (this.config.root) {
29512
29462
  playerConfig.root = this.config.root;
29513
29463
  }
29514
29464
  return playerConfig;
29515
29465
  }
29516
- makeReplayer(events, live, { speed = 8 } = {}) {
29517
- this.replayer = new Replayer(
29518
- events,
29519
- this.makeReplayerConfig(live, { speed })
29520
- );
29466
+ // function to create replayer (should be called once)
29467
+ makeReplayer(events = [], { baselineTime = Date.now() } = {}) {
29468
+ this.replayer = new Replayer(events, this.makeReplayerConfig());
29521
29469
  if (this.config.enableInteract) {
29522
29470
  this.replayer.enableInteract();
29523
29471
  } else {
29524
- this.replayer.disableInteract();
29472
+ this.replayer?.disableInteract();
29525
29473
  }
29526
- }
29527
- start(options, castedEvents = []) {
29528
- this.startOptions = options;
29529
- const {
29530
- firstEventTimestamp,
29531
- speed = 8,
29532
- useTimestampCompression = true
29533
- } = options;
29534
- this.events = castedEvents;
29535
- this.numberOfCastedEvents = castedEvents.length;
29536
- this.makeReplayer([], true, { speed });
29537
- this.useTimestampCompression = useTimestampCompression;
29538
- this.replayer.startLive(
29539
- this.useTimestampCompression ? Date.now() : firstEventTimestamp
29540
- );
29541
- this.replayer.on("event-cast", (event) => {
29474
+ if (this.config.onlyLive) {
29475
+ this.replayer.startLive(baselineTime);
29476
+ } else {
29477
+ this.replayer.play();
29478
+ }
29479
+ this.firstEvent = events[0];
29480
+ if (DEBUG_MODE) {
29481
+ this.setupDebugMode();
29482
+ }
29483
+ this.replayer.on(ReplayerEvents.EventCast, (event) => {
29484
+ this.storeCastedEvent(event);
29542
29485
  if (this.onEventCast) {
29543
29486
  this.onEventCast(event);
29544
29487
  }
29545
29488
  });
29546
29489
  }
29547
- async goLive(sleepAfter = 1e3) {
29548
- if (this.isLive) {
29549
- console.log("Already live, nothing to do.");
29550
- return;
29551
- }
29552
- console.log("Going live...");
29553
- this.stop();
29554
- this.currentTraveledNumberOfEvents = void 0;
29555
- const { trimmedEvents, castedEvents } = this.trimEventsToLastCheckout(
29556
- this.liveEvents
29557
- );
29558
- this.start(
29559
- {
29560
- ...this.startOptions,
29561
- firstEventTimestamp: castedEvents.length ? castedEvents[0].timestamp : trimmedEvents[0].timestamp
29562
- },
29563
- castedEvents
29564
- );
29565
- this.isLive = true;
29566
- await this.fastForward(trimmedEvents);
29567
- if (sleepAfter) {
29568
- await (0, import_await_sleep3.default)(sleepAfter);
29569
- }
29490
+ seek(ts, pause = true) {
29491
+ return new Promise((resolve2) => {
29492
+ const delta = ts - this.firstEvent.timestamp;
29493
+ this.replayer.play(delta);
29494
+ if (pause) {
29495
+ setTimeout(() => {
29496
+ this.replayer?.pause();
29497
+ resolve2();
29498
+ }, 0);
29499
+ } else {
29500
+ resolve2();
29501
+ }
29502
+ });
29570
29503
  }
29571
- async goBackWithEvents_native(getEvents2, { sleepAfter = 1e3 }) {
29572
- if (this.isLive) {
29573
- this.liveEvents = this.events;
29574
- }
29575
- const events = getEvents2();
29576
- if (events.length === this.currentTraveledNumberOfEvents || events.length < 2) {
29577
- return;
29578
- }
29579
- this.stop();
29580
- this.events = [];
29581
- this.numberOfCastedEvents = 0;
29582
- this.isLive = false;
29583
- this.currentTraveledNumberOfEvents = events.length;
29584
- const { trimmedEvents } = this.trimEventsToLastCheckout(events);
29585
- if (trimmedEvents.length < 2) {
29586
- console.log("trimmedEvents.length is less than 2");
29587
- return;
29588
- }
29589
- this.makeReplayer(trimmedEvents, false, { speed: 360 });
29590
- this.replayer.play(trimmedEvents[trimmedEvents.length - 1].timestamp);
29591
- if (sleepAfter) {
29592
- await (0, import_await_sleep3.default)(sleepAfter);
29593
- }
29504
+ start(options, castedEvents = []) {
29594
29505
  }
29595
- async goBackWithEvents_native2(getEvents2, { sleepAfter = 1e3 }) {
29596
- try {
29597
- const events = getEvents2();
29598
- const targetTimestamp = events[events.length - 1]?.timestamp ?? 0;
29599
- const getTimeForPause = /* @__PURE__ */ __name(() => {
29600
- return targetTimestamp - (this.events[0].timestamp ?? 0);
29601
- }, "getTimeForPause");
29602
- if (!this.isLive && targetTimestamp <= this.events[this.events.length - 1].timestamp) {
29603
- const timeForPause2 = getTimeForPause();
29604
- this.replayer.pause(timeForPause2);
29605
- return;
29606
- }
29607
- if (this.isLive) {
29608
- this.liveEvents = this.events;
29506
+ // receives new events, and adds them to replayer
29507
+ async fastForward(events) {
29508
+ if (!this.replayer) {
29509
+ if (this.config.onlyLive) {
29510
+ this.makeReplayer([], { baselineTime: events[0].timestamp });
29511
+ } else {
29512
+ this.eventsBuffer.push(...events);
29513
+ if (this.eventsBuffer.length > 2) {
29514
+ this.makeReplayer(this.eventsBuffer);
29515
+ } else {
29516
+ return;
29517
+ }
29609
29518
  }
29610
- this.stop();
29611
- this.events = this.liveEvents;
29612
- this.numberOfCastedEvents = this.liveEvents.length;
29613
- this.isLive = false;
29614
- this.makeReplayer(this.events, false, { speed: 360 });
29615
- const timeForPause = getTimeForPause();
29616
- this.replayer.pause(timeForPause);
29617
- } finally {
29618
- if (sleepAfter) {
29619
- await (0, import_await_sleep3.default)(sleepAfter);
29519
+ }
29520
+ let numberOfCastedEvents = 0;
29521
+ const promise = new Promise((resolve2) => {
29522
+ this.onEventCast = () => {
29523
+ numberOfCastedEvents++;
29524
+ if (numberOfCastedEvents === events.length) {
29525
+ this.onEventCast = void 0;
29526
+ resolve2();
29527
+ }
29528
+ };
29529
+ });
29530
+ for (const event of events) {
29531
+ if (event.type === EventType.FullSnapshot) {
29532
+ this.lastSnapshot = event;
29620
29533
  }
29534
+ this.replayer.addEvent(event);
29535
+ this.lastEvent = event;
29536
+ this.storeEvent(event);
29621
29537
  }
29538
+ return promise;
29622
29539
  }
29623
- async goBackWithEvents_FFwd(getEvents2, { sleepAfter = 1e3 }) {
29624
- if (this.isLive) {
29625
- this.liveEvents = this.events;
29626
- }
29627
- const events = getEvents2();
29628
- if (events.length === this.currentTraveledNumberOfEvents) {
29629
- return;
29630
- }
29631
- this.currentTraveledNumberOfEvents = events.length;
29632
- this.stop();
29633
- const { trimmedEvents, castedEvents } = this.trimEventsToLastCheckout(
29634
- this.liveEvents
29635
- );
29636
- this.start(this.startOptions, castedEvents);
29637
- this.isLive = false;
29638
- await this.fastForward(trimmedEvents, true);
29639
- if (sleepAfter) {
29640
- await (0, import_await_sleep3.default)(sleepAfter);
29641
- }
29540
+ async goLive() {
29541
+ await this.seek(this.lastEvent.timestamp, false);
29542
+ await (0, import_await_sleep3.default)(1e3);
29642
29543
  }
29643
29544
  async goBack(timestamp, {
29644
29545
  sleepAfter = 1e3,
29645
29546
  beforeTimestamp = false,
29646
29547
  includeAllMatchingTimestamps = false
29647
29548
  } = {}) {
29648
- const getEvents2 = /* @__PURE__ */ __name(() => {
29649
- const indexOfFirstEventWithLargerOrEqualTimestamp = this.liveEvents.findIndex(
29650
- (e2) => this.getOriginalTimestamp(e2) >= timestamp
29651
- );
29652
- const firstEventWithLargerOrEqualTimestamp = this.liveEvents[indexOfFirstEventWithLargerOrEqualTimestamp];
29653
- if (indexOfFirstEventWithLargerOrEqualTimestamp === -1) {
29654
- return this.liveEvents;
29655
- }
29656
- if (beforeTimestamp || this.getOriginalTimestamp(firstEventWithLargerOrEqualTimestamp) > timestamp) {
29657
- return this.liveEvents.slice(
29658
- 0,
29659
- indexOfFirstEventWithLargerOrEqualTimestamp
29660
- );
29661
- }
29662
- if (!includeAllMatchingTimestamps) {
29663
- return this.liveEvents.slice(
29664
- 0,
29665
- indexOfFirstEventWithLargerOrEqualTimestamp + 1
29666
- );
29667
- }
29668
- let sliceIndex = indexOfFirstEventWithLargerOrEqualTimestamp + 1;
29669
- while (sliceIndex < this.liveEvents.length && this.getOriginalTimestamp(this.liveEvents[sliceIndex]) === timestamp) {
29670
- sliceIndex++;
29671
- }
29672
- return this.liveEvents.slice(
29673
- 0,
29674
- indexOfFirstEventWithLargerOrEqualTimestamp
29675
- );
29676
- }, "getEvents");
29677
- return this.goBackWithEvents(getEvents2, {
29678
- sleepAfter
29679
- });
29549
+ await this.seek(timestamp, true);
29550
+ await (0, import_await_sleep3.default)(1e3);
29680
29551
  }
29681
- async getLastEventTimestamps(snapshot2 = false) {
29682
- const lastEvent = snapshot2 ? await this.findLastFullSnapshotEvent() : this.events[this.events.length - 1];
29683
- return {
29684
- timestamp: lastEvent?.timestamp,
29685
- originalTimestamp: lastEvent?.originalTimestamp
29686
- };
29552
+ storeEvent(event) {
29553
+ if (!this.debugData.active) {
29554
+ return;
29555
+ }
29556
+ this.debugData.events.push(event);
29687
29557
  }
29688
- async findLastFullSnapshotEvent() {
29689
- const event = this.events.reduce((snapshotEvent, event2) => {
29690
- return event2.type === EventType.FullSnapshot ? event2 : snapshotEvent;
29691
- }, void 0);
29692
- if (event) {
29693
- return event;
29558
+ storeCastedEvent(event) {
29559
+ if (!this.debugData.active) {
29560
+ return;
29694
29561
  }
29695
- console.log("waiting for full snapshot event...");
29696
- await (0, import_await_sleep3.default)(1e3);
29697
- return this.findLastFullSnapshotEvent();
29562
+ this.debugData.castedEvents.push(event);
29563
+ }
29564
+ setupDebugMode() {
29565
+ this.debugData.active = true;
29566
+ window.__chkreplayer = {
29567
+ events: /* @__PURE__ */ __name(() => this.debugData.events, "events"),
29568
+ back: /* @__PURE__ */ __name((ts) => this.goBack(ts, {}), "back"),
29569
+ currentTime: /* @__PURE__ */ __name(() => this.replayer.getCurrentTime(), "currentTime"),
29570
+ castedEvents: /* @__PURE__ */ __name(() => this.debugData.castedEvents, "castedEvents")
29571
+ };
29698
29572
  }
29699
29573
  };
29700
29574
 
@@ -31758,204 +31632,6 @@
31758
31632
  };
31759
31633
  var elementHighlighter = new ElementHighlighter();
31760
31634
 
31761
- // ../browser-lib/src/storage/indexedDB.ts
31762
- var IndexedDBClient = class {
31763
- constructor(rawDbName, storeName) {
31764
- this.rawDbName = rawDbName;
31765
- this.storeName = storeName;
31766
- this.db = null;
31767
- }
31768
- static {
31769
- __name(this, "IndexedDBClient");
31770
- }
31771
- getDBName() {
31772
- if (!this._dbName) {
31773
- if (!window.name) {
31774
- const tabIndex = window.sessionStorage.getItem("nextTabIndex") ?? "0";
31775
- window.name = tabIndex;
31776
- window.sessionStorage.setItem(
31777
- "nextTabIndex",
31778
- `${parseInt(tabIndex) + 1}`
31779
- );
31780
- }
31781
- this._dbName = `${this.rawDbName}-${window.name}`;
31782
- }
31783
- return this._dbName;
31784
- }
31785
- open(version = 1) {
31786
- return new Promise((resolve2, reject) => {
31787
- const request = indexedDB.open(this.getDBName(), version);
31788
- request.onupgradeneeded = (event) => {
31789
- this.db = request.result;
31790
- if (!this.db.objectStoreNames.contains(this.storeName)) {
31791
- this.db.createObjectStore(this.storeName);
31792
- }
31793
- };
31794
- request.onsuccess = (event) => {
31795
- this.db = request.result;
31796
- resolve2(this.db);
31797
- };
31798
- request.onerror = (event) => {
31799
- console.log("IndexedDBClient.open() error", event, request.error);
31800
- reject(request.error);
31801
- };
31802
- });
31803
- }
31804
- count() {
31805
- return new Promise((resolve2, reject) => {
31806
- if (!this.db) {
31807
- reject("Database has not been initialized");
31808
- return;
31809
- }
31810
- const transaction = this.db.transaction([this.storeName]);
31811
- const store = transaction.objectStore(this.storeName);
31812
- const request = store.count();
31813
- request.onsuccess = () => resolve2(request.result);
31814
- request.onerror = () => {
31815
- return reject(request.error);
31816
- };
31817
- });
31818
- }
31819
- set(data, key) {
31820
- return new Promise((resolve2, reject) => {
31821
- if (!this.db) {
31822
- reject("Database has not been initialized");
31823
- return;
31824
- }
31825
- const transaction = this.db.transaction([this.storeName], "readwrite");
31826
- const store = transaction.objectStore(this.storeName);
31827
- const request = store.add(data, key);
31828
- request.onsuccess = () => resolve2();
31829
- request.onerror = () => {
31830
- return reject(request.error);
31831
- };
31832
- });
31833
- }
31834
- get(multiple, query, count) {
31835
- return new Promise((resolve2, reject) => {
31836
- if (!this.db) {
31837
- reject("Database has not been initialized");
31838
- return;
31839
- }
31840
- const transaction = this.db.transaction([this.storeName]);
31841
- const store = transaction.objectStore(this.storeName);
31842
- const request = multiple ? store.getAll(query, count) : store.get(query);
31843
- request.onsuccess = () => resolve2(request.result);
31844
- request.onerror = () => {
31845
- return reject(request.error);
31846
- };
31847
- });
31848
- }
31849
- getOne(query) {
31850
- return this.get(false, query);
31851
- }
31852
- getAll(query, count) {
31853
- return this.get(true, query, count);
31854
- }
31855
- };
31856
-
31857
- // ../browser-lib/src/rrweb-events-storage-manager/rrweb-events-storage-manager.ts
31858
- var RrwebEventsStorageManager = class {
31859
- constructor() {
31860
- this.initialized = false;
31861
- this.rrwebEventsLoaded = false;
31862
- this.loadRRwebEvents = [];
31863
- this.rrwebCrossFrameEventIdCounter = 0;
31864
- this.firstRequestedIndex = void 0;
31865
- }
31866
- static {
31867
- __name(this, "RrwebEventsStorageManager");
31868
- }
31869
- async initRRwebEvents() {
31870
- try {
31871
- if (this.initialized) {
31872
- console.warn(
31873
- "[RrwebEventsStorageManager] initRRwebEvents called more than once"
31874
- );
31875
- return;
31876
- }
31877
- this.initialized = true;
31878
- this.rrwebEventsIndexedDB = new IndexedDBClient(
31879
- "checksum",
31880
- "rrwebEvents"
31881
- );
31882
- try {
31883
- await this.rrwebEventsIndexedDB.open();
31884
- } catch (e2) {
31885
- return;
31886
- }
31887
- this.rrwebCrossFrameEventIdCounter = await this.rrwebEventsIndexedDB.count();
31888
- this.loadRRwebEvents.forEach((event) => {
31889
- this.rrwebEventsIndexedDB.set(
31890
- event,
31891
- this.rrwebCrossFrameEventIdCounter++
31892
- );
31893
- });
31894
- this.rrwebEventsLoaded = true;
31895
- } catch (e2) {
31896
- console.log(e2);
31897
- }
31898
- }
31899
- onRRwebEvent(event) {
31900
- if (this.rrwebEventsLoaded) {
31901
- this.rrwebEventsIndexedDB.set(
31902
- event,
31903
- this.rrwebCrossFrameEventIdCounter++
31904
- );
31905
- } else {
31906
- this.loadRRwebEvents.push(event);
31907
- }
31908
- }
31909
- isInitialized() {
31910
- return this.initialized;
31911
- }
31912
- getLastRRwebEventKey() {
31913
- return this.rrwebCrossFrameEventIdCounter - 1;
31914
- }
31915
- /**
31916
- * Performs an HTTP post with the JSON of the rrweb events array to a given URL.
31917
- */
31918
- async postRRwebEvents(url) {
31919
- if (!this.rrwebEventsLoaded) {
31920
- return [];
31921
- }
31922
- const rrwebEvents = await this.rrwebEventsIndexedDB.getAll();
31923
- return fetch(url, {
31924
- method: "PUT",
31925
- headers: {
31926
- "Content-Type": "application/json"
31927
- },
31928
- body: JSON.stringify(rrwebEvents)
31929
- });
31930
- }
31931
- async getRRwebEvents(lowerBoundKey, size) {
31932
- try {
31933
- if (this.firstRequestedIndex === void 0) {
31934
- this.firstRequestedIndex = lowerBoundKey;
31935
- }
31936
- lowerBoundKey -= this.firstRequestedIndex;
31937
- if (!this.rrwebEventsLoaded) {
31938
- return [];
31939
- }
31940
- const bound = size ? IDBKeyRange.bound(lowerBoundKey, lowerBoundKey + size) : IDBKeyRange.lowerBound(lowerBoundKey);
31941
- const events = await this.rrwebEventsIndexedDB.getAll(
31942
- bound
31943
- );
31944
- return events;
31945
- } catch (e2) {
31946
- console.log(e2);
31947
- return [];
31948
- }
31949
- }
31950
- async getRRwebEvent(key) {
31951
- if (!this.rrwebEventsLoaded) {
31952
- return null;
31953
- }
31954
- return this.rrwebEventsIndexedDB.getOne(key);
31955
- }
31956
- };
31957
- var rrwebEventsStorageManager = new RrwebEventsStorageManager();
31958
-
31959
31635
  // src/lib/test-generator/selectors/pw-injected-script-functions.js
31960
31636
  function escapeForTextSelector(text, exact) {
31961
31637
  if (typeof text !== "string") return escapeRegexForSelector(text);
@@ -32026,11 +31702,6 @@
32026
31702
  return selector.trim().replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1");
32027
31703
  }
32028
31704
  __name(escapeSelector, "escapeSelector");
32029
- function replaceLocatorQuotesWithTicks(str) {
32030
- const firstParantheses = str.indexOf("(");
32031
- return str.substring(0, firstParantheses + 1) + "`" + str.substring(firstParantheses + 2, str.length - 2) + "`)";
32032
- }
32033
- __name(replaceLocatorQuotesWithTicks, "replaceLocatorQuotesWithTicks");
32034
31705
  function getElementWindowPlaywright(node2) {
32035
31706
  const elementWindow = node2.ownerDocument.defaultView;
32036
31707
  if (elementWindow !== window && !elementWindow.playwright) {
@@ -32755,7 +32426,7 @@
32755
32426
  }, "guardReturn");
32756
32427
 
32757
32428
  // src/lib/test-generator/selectors/pw-custom-locator-generator.ts
32758
- var DEBUG_MODE = false;
32429
+ var DEBUG_MODE2 = false;
32759
32430
  var LocatorChain = class _LocatorChain {
32760
32431
  constructor(locators) {
32761
32432
  this.locators = [];
@@ -32924,7 +32595,7 @@
32924
32595
  }
32925
32596
  } catch (error) {
32926
32597
  if (error instanceof TimeoutError) {
32927
- console.log("Timeout error");
32598
+ console.warn("[PlaywrightCustomLocatorGenerator] Timeout error");
32928
32599
  }
32929
32600
  }
32930
32601
  if (!filteredCandidates?.length) {
@@ -32972,11 +32643,12 @@
32972
32643
  *
32973
32644
  * @param selector selector to test
32974
32645
  * @param element element to test the selector on
32975
- * @param testVariables object containing variables information to test the selector with
32646
+ * @param testVariables object containing variables information to test the locator with
32976
32647
  * @param testUniqueness test if selector returns only one element
32977
32648
  * @returns object with valid flag and locator candidate if valid
32978
32649
  */
32979
- testSelector(selector, element, testVariables, testUniqueness = true) {
32650
+ testSelector(locator, element, testVariables, testUniqueness = true) {
32651
+ const selector = getElementWindowPlaywright(element).selector(element);
32980
32652
  const locatorResult = this.getLocatorBase(element).locator(selector);
32981
32653
  console.log("Locator result", locatorResult);
32982
32654
  const testResult = /* @__PURE__ */ __name((locatorResult2) => {
@@ -32991,10 +32663,10 @@
32991
32663
  return { valid: false };
32992
32664
  }
32993
32665
  let variableSelectionData = {};
32994
- if (testVariables?.selectorWithVars?.length) {
32666
+ if (testVariables?.locatorWithVars?.length) {
32995
32667
  try {
32996
32668
  const func = new Function(
32997
- `{ return function(element) { ${testVariables.variablesCode}; return this.getLocatorBase(element).locator(\`${testVariables.selectorWithVars}\`); } }`
32669
+ `{ return function(element) { ${testVariables.variablesCode}; return this.getLocatorBase(element).locator(\`${testVariables.locatorWithVars}\`); } }`
32998
32670
  );
32999
32671
  const res = func().call(this, element);
33000
32672
  console.log("Locator with vars result", res);
@@ -33002,10 +32674,12 @@
33002
32674
  return { valid: false };
33003
32675
  }
33004
32676
  variableSelectionData = {
33005
- selectorWithVars: testVariables.selectorWithVars,
33006
- locatorWithVars: replaceLocatorQuotesWithTicks(
33007
- this.getSelectorLocator(testVariables.selectorWithVars, element)
33008
- )
32677
+ selectorWithVars: selector,
32678
+ // TODO: selector with vars is similar to selector, should be different
32679
+ locatorWithVars: testVariables.locatorWithVars
32680
+ // locatorWithVars: replaceLocatorQuotesWithTicks(
32681
+ // this.getSelectorLocator(testVariables.selectorWithVars, element)
32682
+ // ),
33009
32683
  };
33010
32684
  } catch (error) {
33011
32685
  console.error("Error testing selector with variables", error.message);
@@ -33015,7 +32689,7 @@
33015
32689
  return {
33016
32690
  valid: true,
33017
32691
  selector,
33018
- locator: this.getSelectorLocator(selector, element),
32692
+ locator,
33019
32693
  ...variableSelectionData
33020
32694
  };
33021
32695
  }
@@ -33430,7 +33104,7 @@
33430
33104
  const selector = tag + innerFeatures.map((feature) => `:has(${feature})`).join("");
33431
33105
  return {
33432
33106
  selector,
33433
- locator: `locator('${tag}', {has: page.locator('${selector}')})`
33107
+ locator: this.getSelectorLocator(selector)
33434
33108
  };
33435
33109
  }
33436
33110
  getByRoleLocator(element, options = {}) {
@@ -33498,9 +33172,10 @@
33498
33172
  props.push(["name", escapeForAttributeSelector(name, exact)]);
33499
33173
  }
33500
33174
  const getSelection = /* @__PURE__ */ __name(() => {
33175
+ const selector = `internal:role=${role}${props.map(([n2, v2]) => `[${n2}=${v2}]`).join("")}`;
33501
33176
  return {
33502
- locator: `getByRole('${role}', { ${props.join(", ")} })`,
33503
- selector: `internal:role=${role}${props.map(([n2, v2]) => `[${n2}=${v2}]`).join("")}`,
33177
+ locator: this.getSelectorLocator(selector),
33178
+ selector,
33504
33179
  options: usedFilters
33505
33180
  };
33506
33181
  }, "getSelection");
@@ -33553,7 +33228,6 @@
33553
33228
  let selection = getSelection(options.exact);
33554
33229
  if (options.exact && !this.getLocatorBase(element).locator(selection.selector).elements.includes(element)) {
33555
33230
  selection = getSelection(false);
33556
- 4;
33557
33231
  }
33558
33232
  return selection;
33559
33233
  } catch (error) {
@@ -33657,7 +33331,7 @@
33657
33331
  return { text, exact };
33658
33332
  }
33659
33333
  checkTimeout(throwError = true) {
33660
- if (DEBUG_MODE) {
33334
+ if (DEBUG_MODE2) {
33661
33335
  return false;
33662
33336
  }
33663
33337
  if (this.MAX_PROCESSING_TIME && Date.now() - this.startTimestamp > this.MAX_PROCESSING_TIME) {
@@ -33677,6 +33351,68 @@
33677
33351
  }
33678
33352
  __name(isInstanceOfHTMLElement, "isInstanceOfHTMLElement");
33679
33353
 
33354
+ // ../browser-lib/src/helpers/dom/xpath.ts
33355
+ function getRelativeXPath(element = document, child) {
33356
+ try {
33357
+ let getNodeIdentifier2 = function(node3) {
33358
+ let identifier = node3.nodeName.toLowerCase();
33359
+ let foundAttributeIdentifier = false;
33360
+ ["name", "label", "aria-label", "data-testid", "role"].forEach((attr) => {
33361
+ if (node3.hasAttribute(attr)) {
33362
+ identifier += `[@${attr}="${node3.getAttribute(attr)}"]`;
33363
+ foundAttributeIdentifier = true;
33364
+ }
33365
+ });
33366
+ if (!foundAttributeIdentifier) {
33367
+ let index2 = 1;
33368
+ let sibling = node3.previousSibling;
33369
+ while (sibling) {
33370
+ if (sibling.nodeType === Node.ELEMENT_NODE && sibling.nodeName === node3.nodeName) {
33371
+ index2++;
33372
+ }
33373
+ sibling = sibling.previousSibling;
33374
+ }
33375
+ if (index2 > 1) {
33376
+ identifier += `[${index2}]`;
33377
+ }
33378
+ }
33379
+ return identifier;
33380
+ };
33381
+ var getNodeIdentifier = getNodeIdentifier2;
33382
+ __name(getNodeIdentifier2, "getNodeIdentifier");
33383
+ if (!element || !child || !element.contains(child)) {
33384
+ throw new Error("Child is not a descendant of the given element.");
33385
+ }
33386
+ let path = [];
33387
+ let node2 = child;
33388
+ while (node2 !== element) {
33389
+ if (node2.nodeType === Node.ELEMENT_NODE) {
33390
+ path.unshift(getNodeIdentifier2(node2));
33391
+ }
33392
+ node2 = node2.parentElement;
33393
+ }
33394
+ return path.join("/");
33395
+ } catch (error) {
33396
+ console.error("Failed to get relative xpath", error);
33397
+ return;
33398
+ }
33399
+ }
33400
+ __name(getRelativeXPath, "getRelativeXPath");
33401
+ function findElementsByXPath(parentElement2, xpath) {
33402
+ let evaluator = new XPathEvaluator();
33403
+ let result2 = evaluator.evaluate(
33404
+ xpath,
33405
+ parentElement2,
33406
+ null,
33407
+ XPathResult.FIRST_ORDERED_NODE_TYPE,
33408
+ null
33409
+ );
33410
+ return [result2.singleNodeValue].filter(
33411
+ (node2) => node2 instanceof HTMLElement
33412
+ );
33413
+ }
33414
+ __name(findElementsByXPath, "findElementsByXPath");
33415
+
33680
33416
  // src/lib/test-generator/selectors/compound-selector.ts
33681
33417
  var CLASS_IGNORE_LIST = [
33682
33418
  ":hover",
@@ -33767,7 +33503,7 @@
33767
33503
  const compoundSelector = {
33768
33504
  // generate selectors from the common root to the target element
33769
33505
  targetSelection: {
33770
- xpath: this.getRelativeXPath(commonRoot, targetElement.element),
33506
+ xpath: getRelativeXPath(commonRoot, targetElement.element),
33771
33507
  cssSelectors: this.generateAllContextualSelectors(
33772
33508
  commonRoot,
33773
33509
  targetElement.element
@@ -33861,7 +33597,7 @@
33861
33597
  if (targetSelection.xpath) {
33862
33598
  try {
33863
33599
  addElementstoHistogram(
33864
- this.findElementsByXPath(commonParent, targetSelection.xpath)
33600
+ findElementsByXPath(commonParent, targetSelection.xpath)
33865
33601
  );
33866
33602
  } catch (error) {
33867
33603
  }
@@ -34025,68 +33761,6 @@
34025
33761
  });
34026
33762
  return [...new Set(selectors)];
34027
33763
  }
34028
- /**
34029
- * Builds relative xpath from an element to its child
34030
- */
34031
- getRelativeXPath(element, child) {
34032
- try {
34033
- let getNodeIdentifier = function(node3) {
34034
- let identifier = node3.nodeName.toLowerCase();
34035
- let foundAttributeIdentifier = false;
34036
- ["name", "label", "aria-label", "data-testid", "role"].forEach(
34037
- (attr) => {
34038
- if (node3.hasAttribute(attr)) {
34039
- identifier += `[@${attr}="${node3.getAttribute(attr)}"]`;
34040
- foundAttributeIdentifier = true;
34041
- }
34042
- }
34043
- );
34044
- if (!foundAttributeIdentifier) {
34045
- let index2 = 1;
34046
- let sibling = node3.previousSibling;
34047
- while (sibling) {
34048
- if (sibling.nodeType === Node.ELEMENT_NODE && sibling.nodeName === node3.nodeName) {
34049
- index2++;
34050
- }
34051
- sibling = sibling.previousSibling;
34052
- }
34053
- if (index2 > 1) {
34054
- identifier += `[${index2}]`;
34055
- }
34056
- }
34057
- return identifier;
34058
- };
34059
- __name(getNodeIdentifier, "getNodeIdentifier");
34060
- if (!element || !child || !element.contains(child)) {
34061
- throw new Error("Child is not a descendant of the given element.");
34062
- }
34063
- let path = [];
34064
- let node2 = child;
34065
- while (node2 !== element) {
34066
- if (node2.nodeType === Node.ELEMENT_NODE) {
34067
- path.unshift(getNodeIdentifier(node2));
34068
- }
34069
- node2 = node2.parentElement;
34070
- }
34071
- return path.join("/");
34072
- } catch (error) {
34073
- console.error("Failed to get relative xpath", error);
34074
- return;
34075
- }
34076
- }
34077
- findElementsByXPath(parentElement2, xpath) {
34078
- let evaluator = new XPathEvaluator();
34079
- let result2 = evaluator.evaluate(
34080
- xpath,
34081
- parentElement2,
34082
- null,
34083
- XPathResult.FIRST_ORDERED_NODE_TYPE,
34084
- null
34085
- );
34086
- return [result2.singleNodeValue].filter(
34087
- (node2) => node2 instanceof HTMLElement
34088
- );
34089
- }
34090
33764
  /**
34091
33765
  * Create a contextual selector from the common root to the target element
34092
33766
  * We can play with the options to build various types of selectors which we could
@@ -34284,8 +33958,6 @@
34284
33958
  );
34285
33959
  attributeMaxSize = Math.max(attributeMaxSize - 10, 0);
34286
33960
  } while (rootClone.outerHTML.length > this.MAX_SNIPPET_SIZE && attributeMaxSize > 0);
34287
- rootClone.querySelectorAll("*").forEach((el) => {
34288
- });
34289
33961
  let htmlSnippet = serializeElement(rootClone, {
34290
33962
  limitAttributeLength: true
34291
33963
  });
@@ -34872,14 +34544,14 @@ ${data.locator}`
34872
34544
  /**
34873
34545
  * Tests a selector for a given element.
34874
34546
  */
34875
- testElementSelector(selector, element, testVariables, testUniqueness = true) {
34547
+ testElementSelector(locator, element, testVariables, testUniqueness = true) {
34876
34548
  const testElement = typeof element === "string" ? this.htmlReducer.getElementForChecksumId(element) : element;
34877
34549
  if (!testElement) {
34878
34550
  console.error("Element not found", element);
34879
34551
  return { valid: false, error: "Element not found" };
34880
34552
  }
34881
34553
  return new PlaywrightCustomLocatorGenerator().testSelector(
34882
- selector,
34554
+ locator,
34883
34555
  testElement,
34884
34556
  testVariables,
34885
34557
  testUniqueness
@@ -34925,9 +34597,9 @@ ${data.locator}`
34925
34597
  this.sessionMirror = new SessionRecorder((event, isCheckout) => {
34926
34598
  event.isCheckout = isCheckout;
34927
34599
  window.checksumSendBroadcastMessage?.("rrweb", [event]);
34928
- rrwebEventsStorageManager.onRRwebEvent(event);
34600
+ this.lastRrwebEventTimestamp = event.timestamp;
34601
+ console.log(event.timestamp);
34929
34602
  }, config.recordOptions);
34930
- rrwebEventsStorageManager.initRRwebEvents();
34931
34603
  }
34932
34604
  if (initFilesObserver) {
34933
34605
  this.filesObserver = new FilesObserver(this.sessionMirror);
@@ -35131,12 +34803,12 @@ ${data.locator}`
35131
34803
  /**
35132
34804
  * Performs an HTTP post with the JSON of the rrweb events array to a given URL.
35133
34805
  */
35134
- async postRRwebEvents(url) {
35135
- return rrwebEventsStorageManager.postRRwebEvents(url);
35136
- }
35137
- async getRRwebEvents(id) {
35138
- return rrwebEventsStorageManager.getRRwebEvents(id);
35139
- }
34806
+ // async postRRwebEvents(url) {
34807
+ // return rrwebEventsStorageManager.postRRwebEvents(url);
34808
+ // }
34809
+ // async getRRwebEvents(id: number) {
34810
+ // return rrwebEventsStorageManager.getRRwebEvents(id);
34811
+ // }
35140
34812
  /**
35141
34813
  * Function used to reduce the HTML of the page to a minimal set of elements that are required
35142
34814
  * to produce a prompt for the LLM agent.
@@ -35150,17 +34822,10 @@ ${data.locator}`
35150
34822
  { ...this.appSpecificRules, ...appSpecificRules },
35151
34823
  options
35152
34824
  );
35153
- const rrwebEventKey = rrwebEventsStorageManager.isInitialized() ? rrwebEventsStorageManager.getLastRRwebEventKey() : void 0;
35154
- if (rrwebEventKey) {
35155
- const rrwebEvent = await rrwebEventsStorageManager.getRRwebEvent(
35156
- rrwebEventKey
35157
- );
35158
- if (rrwebEvent) {
35159
- reducedHTMLData.lastRRwebEvent = {
35160
- key: rrwebEventKey,
35161
- timestamp: rrwebEvent.timestamp
35162
- };
35163
- }
34825
+ if (this.lastRrwebEventTimestamp) {
34826
+ reducedHTMLData.lastRRwebEvent = {
34827
+ timestamp: this.lastRrwebEventTimestamp
34828
+ };
35164
34829
  }
35165
34830
  if (options.extractESRAForInterpretationRequiredElements) {
35166
34831
  console.log("Extracting ESRA for interpretation required elements...");
@@ -35798,9 +35463,6 @@ ${data.locator}`
35798
35463
  goLive() {
35799
35464
  return this.sessionReplayer.goLive();
35800
35465
  }
35801
- getLastEventTimestamps(snapshot2 = false) {
35802
- return this.sessionReplayer.getLastEventTimestamps(snapshot2);
35803
- }
35804
35466
  };
35805
35467
 
35806
35468
  // ../browser-lib/src/visual-test-generator/time-machine-event-handlers.ts
@@ -35833,7 +35495,6 @@ ${data.locator}`
35833
35495
  }
35834
35496
  }
35835
35497
  if (extractPlaywrightSelector) {
35836
- console.log("extracting playwright selector...");
35837
35498
  const {
35838
35499
  selector: playwrightSelector,
35839
35500
  locator,
@@ -35844,7 +35505,6 @@ ${data.locator}`
35844
35505
  selector.playwrightSelector = playwrightSelector;
35845
35506
  selector.playwrightLocator = locator;
35846
35507
  selector.playwrightParentFramesSelectors = parentFramesSelectors;
35847
- console.log("Playwright selector extraction complete");
35848
35508
  }
35849
35509
  return selector;
35850
35510
  }
@@ -36088,7 +35748,8 @@ ${data.locator}`
36088
35748
  selector: dropzoneSelector.playwrightSelector,
36089
35749
  locator: dropzoneSelector.playwrightLocator,
36090
35750
  parentFramesSelectors: dropzoneSelector.playwrightParentFramesSelectors,
36091
- esraMetadata: dropzoneSelector.esraMetadata
35751
+ esraMetadata: dropzoneSelector.esraMetadata,
35752
+ rrwebId: dropzoneNodeId
36092
35753
  }
36093
35754
  }
36094
35755
  )
@@ -36109,7 +35770,8 @@ ${data.locator}`
36109
35770
  window.parent.document.body.appendChild(liveTMDiv);
36110
35771
  this.sessionReplayer = new SessionReplayer({
36111
35772
  enableInteract: false,
36112
- root: liveTMDiv
35773
+ root: liveTMDiv,
35774
+ onlyLive: true
36113
35775
  });
36114
35776
  this.sessionReplayer.start({ firstEventTimestamp: Date.now() });
36115
35777
  }
@@ -36355,6 +36017,9 @@ ${data.locator}`
36355
36017
  pageId: void 0,
36356
36018
  timestamp: event.timestamp,
36357
36019
  id: data?.id || Date.now().toString(),
36020
+ // @ts-ignore
36021
+ rrwebId: event.data?.id,
36022
+ // add rrwebId for services caching
36358
36023
  ...data
36359
36024
  };
36360
36025
  }
@@ -36401,7 +36066,10 @@ ${data.locator}`
36401
36066
  if (!node2) {
36402
36067
  return {};
36403
36068
  }
36404
- const selector = await this.elementSelector.getSelector(node2);
36069
+ const selector = await this.elementSelector.getSelector(node2, {
36070
+ extractEsraMetadata: false
36071
+ // For now, don't produce ESRA metadata for VTG steps recording
36072
+ });
36405
36073
  if (!selector) {
36406
36074
  return { node: node2 };
36407
36075
  }