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