@openreplay/tracker 16.4.2 → 16.4.3-beta.0

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/lib/index.js CHANGED
@@ -5271,7 +5271,7 @@ class App {
5271
5271
  this.stopCallbacks = [];
5272
5272
  this.commitCallbacks = [];
5273
5273
  this.activityState = ActivityState.NotActive;
5274
- this.version = '16.4.2'; // TODO: version compatability check inside each plugin.
5274
+ this.version = '16.4.3-beta.0'; // TODO: version compatability check inside each plugin.
5275
5275
  this.socketMode = false;
5276
5276
  this.compressionThreshold = 24 * 1000;
5277
5277
  this.bc = null;
@@ -5559,9 +5559,170 @@ class App {
5559
5559
  this.orderNumber = 0;
5560
5560
  this.coldStartTs = 0;
5561
5561
  this.singleBuffer = false;
5562
+ /**
5563
+ * start buffering messages without starting the actual session, which gives
5564
+ * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
5565
+ * and we will then send buffered batch, so it won't get lost
5566
+ * */
5567
+ this.coldStart = async (startOpts = {}, conditional) => {
5568
+ this.singleBuffer = false;
5569
+ const second = 1000;
5570
+ const isNewSession = this.checkSessionToken(startOpts.forceNew);
5571
+ if (conditional) {
5572
+ await this.setupConditionalStart(startOpts);
5573
+ }
5574
+ const cycle = () => {
5575
+ this.orderNumber += 1;
5576
+ adjustTimeOrigin();
5577
+ this.coldStartTs = now();
5578
+ if (this.orderNumber % 2 === 0) {
5579
+ this.bufferedMessages1.length = 0;
5580
+ this.bufferedMessages1.push(Timestamp(this.timestamp()));
5581
+ this.bufferedMessages1.push(TabData(this.session.getTabId()));
5582
+ }
5583
+ else {
5584
+ this.bufferedMessages2.length = 0;
5585
+ this.bufferedMessages2.push(Timestamp(this.timestamp()));
5586
+ this.bufferedMessages2.push(TabData(this.session.getTabId()));
5587
+ }
5588
+ this.stop(false);
5589
+ this.activityState = ActivityState.ColdStart;
5590
+ if (startOpts.sessionHash) {
5591
+ this.session.applySessionHash(startOpts.sessionHash);
5592
+ }
5593
+ if (startOpts.forceNew) {
5594
+ this.session.reset();
5595
+ }
5596
+ this.session.assign({
5597
+ userID: startOpts.userID,
5598
+ metadata: startOpts.metadata,
5599
+ });
5600
+ if (!isNewSession) {
5601
+ this.debug.log('continuing session on new tab', this.session.getTabId());
5602
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
5603
+ this.send(TabChange(this.session.getTabId()));
5604
+ }
5605
+ this.observer.observe();
5606
+ this.ticker.start();
5607
+ };
5608
+ this.coldInterval = setInterval(() => {
5609
+ cycle();
5610
+ }, 30 * second);
5611
+ cycle();
5612
+ };
5613
+ this.setupConditionalStart = async (startOpts) => {
5614
+ this.conditionsManager = new ConditionsManager(this, startOpts);
5615
+ const r = await fetch(this.options.ingestPoint + '/v1/web/start', {
5616
+ method: 'POST',
5617
+ headers: {
5618
+ 'Content-Type': 'application/json',
5619
+ },
5620
+ body: JSON.stringify({
5621
+ ...this.getTrackerInfo(),
5622
+ timestamp: now(),
5623
+ doNotRecord: true,
5624
+ bufferDiff: 0,
5625
+ userID: this.session.getInfo().userID,
5626
+ token: undefined,
5627
+ deviceMemory,
5628
+ jsHeapSizeLimit,
5629
+ timezone: getTimezone(),
5630
+ width: window.screen.width,
5631
+ height: window.screen.height,
5632
+ }),
5633
+ });
5634
+ const {
5635
+ // this token is needed to fetch conditions and flags,
5636
+ // but it can't be used to record a session
5637
+ token, userBrowser, userCity, userCountry, userDevice, userOS, userState, projectID, features, } = await r.json();
5638
+ this.features = features ? features : this.features;
5639
+ this.session.assign({ projectID });
5640
+ this.session.setUserInfo({
5641
+ userBrowser,
5642
+ userCity,
5643
+ userCountry,
5644
+ userDevice,
5645
+ userOS,
5646
+ userState,
5647
+ });
5648
+ const onStartInfo = { sessionToken: token, userUUID: '', sessionID: '' };
5649
+ this.startCallbacks.forEach((cb) => cb(onStartInfo));
5650
+ await this.conditionsManager?.fetchConditions(projectID, token);
5651
+ if (this.features['feature-flags']) {
5652
+ await this.featureFlags.reloadFlags(token);
5653
+ this.conditionsManager?.processFlags(this.featureFlags.flags);
5654
+ }
5655
+ await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
5656
+ };
5562
5657
  this.onSessionSent = () => {
5563
5658
  return;
5564
5659
  };
5660
+ /**
5661
+ * Starts offline session recording
5662
+ * @param {Object} startOpts - options for session start, same as .start()
5663
+ * @param {Function} onSessionSent - callback that will be called once session is fully sent
5664
+ * */
5665
+ this.offlineRecording = (startOpts = {}, onSessionSent) => {
5666
+ this.onSessionSent = onSessionSent;
5667
+ this.singleBuffer = true;
5668
+ const isNewSession = this.checkSessionToken(startOpts.forceNew);
5669
+ adjustTimeOrigin();
5670
+ this.coldStartTs = now();
5671
+ const saverBuffer = this.localStorage.getItem(bufferStorageKey);
5672
+ if (saverBuffer) {
5673
+ const data = JSON.parse(saverBuffer);
5674
+ this.bufferedMessages1 = Array.isArray(data) ? data : this.bufferedMessages1;
5675
+ this.localStorage.removeItem(bufferStorageKey);
5676
+ }
5677
+ this.bufferedMessages1.push(Timestamp(this.timestamp()));
5678
+ this.bufferedMessages1.push(TabData(this.session.getTabId()));
5679
+ this.activityState = ActivityState.ColdStart;
5680
+ if (startOpts.sessionHash) {
5681
+ this.session.applySessionHash(startOpts.sessionHash);
5682
+ }
5683
+ if (startOpts.forceNew) {
5684
+ this.session.reset();
5685
+ }
5686
+ this.session.assign({
5687
+ userID: startOpts.userID,
5688
+ metadata: startOpts.metadata,
5689
+ });
5690
+ const onStartInfo = { sessionToken: '', userUUID: '', sessionID: '' };
5691
+ this.startCallbacks.forEach((cb) => cb(onStartInfo));
5692
+ if (!isNewSession) {
5693
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
5694
+ this.send(TabChange(this.session.getTabId()));
5695
+ }
5696
+ this.observer.observe();
5697
+ this.ticker.start();
5698
+ return {
5699
+ saveBuffer: this.saveBuffer,
5700
+ getBuffer: this.getBuffer,
5701
+ setBuffer: this.setBuffer,
5702
+ };
5703
+ };
5704
+ /**
5705
+ * Saves the captured messages in localStorage (or whatever is used in its place)
5706
+ *
5707
+ * Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
5708
+ *
5709
+ * Keeping the size of local storage reasonable is up to the end users of this library
5710
+ * */
5711
+ this.saveBuffer = () => {
5712
+ this.localStorage.setItem(bufferStorageKey, JSON.stringify(this.bufferedMessages1));
5713
+ };
5714
+ /**
5715
+ * @returns buffer with stored messages for offline recording
5716
+ * */
5717
+ this.getBuffer = () => {
5718
+ return this.bufferedMessages1;
5719
+ };
5720
+ /**
5721
+ * Used to set a buffer with messages array
5722
+ * */
5723
+ this.setBuffer = (buffer) => {
5724
+ this.bufferedMessages1 = buffer;
5725
+ };
5565
5726
  this.prevOpts = {};
5566
5727
  this.restartCanvasTracking = () => {
5567
5728
  this.canvasRecorder?.restartTracking();
@@ -6068,167 +6229,6 @@ class App {
6068
6229
  const sessionToken = this.session.getSessionToken(this.projectKey);
6069
6230
  return needNewSessionID || !sessionToken;
6070
6231
  }
6071
- /**
6072
- * start buffering messages without starting the actual session, which gives
6073
- * user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
6074
- * and we will then send buffered batch, so it won't get lost
6075
- * */
6076
- async coldStart(startOpts = {}, conditional) {
6077
- this.singleBuffer = false;
6078
- const second = 1000;
6079
- const isNewSession = this.checkSessionToken(startOpts.forceNew);
6080
- if (conditional) {
6081
- await this.setupConditionalStart(startOpts);
6082
- }
6083
- const cycle = () => {
6084
- this.orderNumber += 1;
6085
- adjustTimeOrigin();
6086
- this.coldStartTs = now();
6087
- if (this.orderNumber % 2 === 0) {
6088
- this.bufferedMessages1.length = 0;
6089
- this.bufferedMessages1.push(Timestamp(this.timestamp()));
6090
- this.bufferedMessages1.push(TabData(this.session.getTabId()));
6091
- }
6092
- else {
6093
- this.bufferedMessages2.length = 0;
6094
- this.bufferedMessages2.push(Timestamp(this.timestamp()));
6095
- this.bufferedMessages2.push(TabData(this.session.getTabId()));
6096
- }
6097
- this.stop(false);
6098
- this.activityState = ActivityState.ColdStart;
6099
- if (startOpts.sessionHash) {
6100
- this.session.applySessionHash(startOpts.sessionHash);
6101
- }
6102
- if (startOpts.forceNew) {
6103
- this.session.reset();
6104
- }
6105
- this.session.assign({
6106
- userID: startOpts.userID,
6107
- metadata: startOpts.metadata,
6108
- });
6109
- if (!isNewSession) {
6110
- this.debug.log('continuing session on new tab', this.session.getTabId());
6111
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
6112
- this.send(TabChange(this.session.getTabId()));
6113
- }
6114
- this.observer.observe();
6115
- this.ticker.start();
6116
- };
6117
- this.coldInterval = setInterval(() => {
6118
- cycle();
6119
- }, 30 * second);
6120
- cycle();
6121
- }
6122
- async setupConditionalStart(startOpts) {
6123
- this.conditionsManager = new ConditionsManager(this, startOpts);
6124
- const r = await fetch(this.options.ingestPoint + '/v1/web/start', {
6125
- method: 'POST',
6126
- headers: {
6127
- 'Content-Type': 'application/json',
6128
- },
6129
- body: JSON.stringify({
6130
- ...this.getTrackerInfo(),
6131
- timestamp: now(),
6132
- doNotRecord: true,
6133
- bufferDiff: 0,
6134
- userID: this.session.getInfo().userID,
6135
- token: undefined,
6136
- deviceMemory,
6137
- jsHeapSizeLimit,
6138
- timezone: getTimezone(),
6139
- width: window.screen.width,
6140
- height: window.screen.height,
6141
- }),
6142
- });
6143
- const {
6144
- // this token is needed to fetch conditions and flags,
6145
- // but it can't be used to record a session
6146
- token, userBrowser, userCity, userCountry, userDevice, userOS, userState, projectID, features, } = await r.json();
6147
- this.features = features ? features : this.features;
6148
- this.session.assign({ projectID });
6149
- this.session.setUserInfo({
6150
- userBrowser,
6151
- userCity,
6152
- userCountry,
6153
- userDevice,
6154
- userOS,
6155
- userState,
6156
- });
6157
- const onStartInfo = { sessionToken: token, userUUID: '', sessionID: '' };
6158
- this.startCallbacks.forEach((cb) => cb(onStartInfo));
6159
- await this.conditionsManager?.fetchConditions(projectID, token);
6160
- if (this.features['feature-flags']) {
6161
- await this.featureFlags.reloadFlags(token);
6162
- this.conditionsManager?.processFlags(this.featureFlags.flags);
6163
- }
6164
- await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
6165
- }
6166
- /**
6167
- * Starts offline session recording
6168
- * @param {Object} startOpts - options for session start, same as .start()
6169
- * @param {Function} onSessionSent - callback that will be called once session is fully sent
6170
- * */
6171
- offlineRecording(startOpts = {}, onSessionSent) {
6172
- this.onSessionSent = onSessionSent;
6173
- this.singleBuffer = true;
6174
- const isNewSession = this.checkSessionToken(startOpts.forceNew);
6175
- adjustTimeOrigin();
6176
- this.coldStartTs = now();
6177
- const saverBuffer = this.localStorage.getItem(bufferStorageKey);
6178
- if (saverBuffer) {
6179
- const data = JSON.parse(saverBuffer);
6180
- this.bufferedMessages1 = Array.isArray(data) ? data : this.bufferedMessages1;
6181
- this.localStorage.removeItem(bufferStorageKey);
6182
- }
6183
- this.bufferedMessages1.push(Timestamp(this.timestamp()));
6184
- this.bufferedMessages1.push(TabData(this.session.getTabId()));
6185
- this.activityState = ActivityState.ColdStart;
6186
- if (startOpts.sessionHash) {
6187
- this.session.applySessionHash(startOpts.sessionHash);
6188
- }
6189
- if (startOpts.forceNew) {
6190
- this.session.reset();
6191
- }
6192
- this.session.assign({
6193
- userID: startOpts.userID,
6194
- metadata: startOpts.metadata,
6195
- });
6196
- const onStartInfo = { sessionToken: '', userUUID: '', sessionID: '' };
6197
- this.startCallbacks.forEach((cb) => cb(onStartInfo));
6198
- if (!isNewSession) {
6199
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
6200
- this.send(TabChange(this.session.getTabId()));
6201
- }
6202
- this.observer.observe();
6203
- this.ticker.start();
6204
- return {
6205
- saveBuffer: this.saveBuffer,
6206
- getBuffer: this.getBuffer,
6207
- setBuffer: this.setBuffer,
6208
- };
6209
- }
6210
- /**
6211
- * Saves the captured messages in localStorage (or whatever is used in its place)
6212
- *
6213
- * Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
6214
- *
6215
- * Keeping the size of local storage reasonable is up to the end users of this library
6216
- * */
6217
- saveBuffer() {
6218
- this.localStorage.setItem(bufferStorageKey, JSON.stringify(this.bufferedMessages1));
6219
- }
6220
- /**
6221
- * @returns buffer with stored messages for offline recording
6222
- * */
6223
- getBuffer() {
6224
- return this.bufferedMessages1;
6225
- }
6226
- /**
6227
- * Used to set a buffer with messages array
6228
- * */
6229
- setBuffer(buffer) {
6230
- this.bufferedMessages1 = buffer;
6231
- }
6232
6232
  /**
6233
6233
  * Uploads the stored session buffer to backend
6234
6234
  * @returns promise that resolves once messages are loaded, it has to be awaited
@@ -9651,7 +9651,7 @@ class API {
9651
9651
  this.signalStartIssue = (reason, missingApi) => {
9652
9652
  const doNotTrack = this.checkDoNotTrack();
9653
9653
  console.log("Tracker couldn't start due to:", JSON.stringify({
9654
- trackerVersion: '16.4.2',
9654
+ trackerVersion: '16.4.3-beta.0',
9655
9655
  projectKey: this.options.projectKey,
9656
9656
  doNotTrack,
9657
9657
  reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,