@openreplay/tracker 16.4.2 → 16.4.3
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 +167 -166
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +167 -166
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/index.d.ts +5 -5
- package/dist/lib/entry.js +167 -166
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +167 -166
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/index.d.ts +5 -5
- package/dist/types/main/app/index.d.ts +5 -5
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -5094,15 +5094,16 @@ class Session {
|
|
|
5094
5094
|
this.userInfo = userInfo;
|
|
5095
5095
|
}
|
|
5096
5096
|
getSessionToken(projectKey) {
|
|
5097
|
-
const
|
|
5098
|
-
if (projectKey &&
|
|
5099
|
-
const savedProject =
|
|
5097
|
+
const tokenWithProject = this.token || this.app.sessionStorage.getItem(this.options.session_token_key);
|
|
5098
|
+
if (projectKey && tokenWithProject) {
|
|
5099
|
+
const savedProject = tokenWithProject.split('_&_')[1];
|
|
5100
5100
|
if (!savedProject || savedProject !== projectKey) {
|
|
5101
5101
|
this.app.sessionStorage.removeItem(this.options.session_token_key);
|
|
5102
5102
|
this.token = undefined;
|
|
5103
5103
|
return undefined;
|
|
5104
5104
|
}
|
|
5105
5105
|
}
|
|
5106
|
+
const token = tokenWithProject ? tokenWithProject.split('_&_')[0] : null;
|
|
5106
5107
|
return token || undefined;
|
|
5107
5108
|
}
|
|
5108
5109
|
setSessionToken(token, projectKey) {
|
|
@@ -5271,7 +5272,7 @@ class App {
|
|
|
5271
5272
|
this.stopCallbacks = [];
|
|
5272
5273
|
this.commitCallbacks = [];
|
|
5273
5274
|
this.activityState = ActivityState.NotActive;
|
|
5274
|
-
this.version = '16.4.
|
|
5275
|
+
this.version = '16.4.3'; // TODO: version compatability check inside each plugin.
|
|
5275
5276
|
this.socketMode = false;
|
|
5276
5277
|
this.compressionThreshold = 24 * 1000;
|
|
5277
5278
|
this.bc = null;
|
|
@@ -5559,9 +5560,170 @@ class App {
|
|
|
5559
5560
|
this.orderNumber = 0;
|
|
5560
5561
|
this.coldStartTs = 0;
|
|
5561
5562
|
this.singleBuffer = false;
|
|
5563
|
+
/**
|
|
5564
|
+
* start buffering messages without starting the actual session, which gives
|
|
5565
|
+
* user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
|
|
5566
|
+
* and we will then send buffered batch, so it won't get lost
|
|
5567
|
+
* */
|
|
5568
|
+
this.coldStart = async (startOpts = {}, conditional) => {
|
|
5569
|
+
this.singleBuffer = false;
|
|
5570
|
+
const second = 1000;
|
|
5571
|
+
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
5572
|
+
if (conditional) {
|
|
5573
|
+
await this.setupConditionalStart(startOpts);
|
|
5574
|
+
}
|
|
5575
|
+
const cycle = () => {
|
|
5576
|
+
this.orderNumber += 1;
|
|
5577
|
+
adjustTimeOrigin();
|
|
5578
|
+
this.coldStartTs = now();
|
|
5579
|
+
if (this.orderNumber % 2 === 0) {
|
|
5580
|
+
this.bufferedMessages1.length = 0;
|
|
5581
|
+
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
5582
|
+
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
5583
|
+
}
|
|
5584
|
+
else {
|
|
5585
|
+
this.bufferedMessages2.length = 0;
|
|
5586
|
+
this.bufferedMessages2.push(Timestamp(this.timestamp()));
|
|
5587
|
+
this.bufferedMessages2.push(TabData(this.session.getTabId()));
|
|
5588
|
+
}
|
|
5589
|
+
this.stop(false);
|
|
5590
|
+
this.activityState = ActivityState.ColdStart;
|
|
5591
|
+
if (startOpts.sessionHash) {
|
|
5592
|
+
this.session.applySessionHash(startOpts.sessionHash);
|
|
5593
|
+
}
|
|
5594
|
+
if (startOpts.forceNew) {
|
|
5595
|
+
this.session.reset();
|
|
5596
|
+
}
|
|
5597
|
+
this.session.assign({
|
|
5598
|
+
userID: startOpts.userID,
|
|
5599
|
+
metadata: startOpts.metadata,
|
|
5600
|
+
});
|
|
5601
|
+
if (!isNewSession) {
|
|
5602
|
+
this.debug.log('continuing session on new tab', this.session.getTabId());
|
|
5603
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
5604
|
+
this.send(TabChange(this.session.getTabId()));
|
|
5605
|
+
}
|
|
5606
|
+
this.observer.observe();
|
|
5607
|
+
this.ticker.start();
|
|
5608
|
+
};
|
|
5609
|
+
this.coldInterval = setInterval(() => {
|
|
5610
|
+
cycle();
|
|
5611
|
+
}, 30 * second);
|
|
5612
|
+
cycle();
|
|
5613
|
+
};
|
|
5614
|
+
this.setupConditionalStart = async (startOpts) => {
|
|
5615
|
+
this.conditionsManager = new ConditionsManager(this, startOpts);
|
|
5616
|
+
const r = await fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
5617
|
+
method: 'POST',
|
|
5618
|
+
headers: {
|
|
5619
|
+
'Content-Type': 'application/json',
|
|
5620
|
+
},
|
|
5621
|
+
body: JSON.stringify({
|
|
5622
|
+
...this.getTrackerInfo(),
|
|
5623
|
+
timestamp: now(),
|
|
5624
|
+
doNotRecord: true,
|
|
5625
|
+
bufferDiff: 0,
|
|
5626
|
+
userID: this.session.getInfo().userID,
|
|
5627
|
+
token: undefined,
|
|
5628
|
+
deviceMemory,
|
|
5629
|
+
jsHeapSizeLimit,
|
|
5630
|
+
timezone: getTimezone(),
|
|
5631
|
+
width: window.screen.width,
|
|
5632
|
+
height: window.screen.height,
|
|
5633
|
+
}),
|
|
5634
|
+
});
|
|
5635
|
+
const {
|
|
5636
|
+
// this token is needed to fetch conditions and flags,
|
|
5637
|
+
// but it can't be used to record a session
|
|
5638
|
+
token, userBrowser, userCity, userCountry, userDevice, userOS, userState, projectID, features, } = await r.json();
|
|
5639
|
+
this.features = features ? features : this.features;
|
|
5640
|
+
this.session.assign({ projectID });
|
|
5641
|
+
this.session.setUserInfo({
|
|
5642
|
+
userBrowser,
|
|
5643
|
+
userCity,
|
|
5644
|
+
userCountry,
|
|
5645
|
+
userDevice,
|
|
5646
|
+
userOS,
|
|
5647
|
+
userState,
|
|
5648
|
+
});
|
|
5649
|
+
const onStartInfo = { sessionToken: token, userUUID: '', sessionID: '' };
|
|
5650
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
5651
|
+
await this.conditionsManager?.fetchConditions(projectID, token);
|
|
5652
|
+
if (this.features['feature-flags']) {
|
|
5653
|
+
await this.featureFlags.reloadFlags(token);
|
|
5654
|
+
this.conditionsManager?.processFlags(this.featureFlags.flags);
|
|
5655
|
+
}
|
|
5656
|
+
await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5657
|
+
};
|
|
5562
5658
|
this.onSessionSent = () => {
|
|
5563
5659
|
return;
|
|
5564
5660
|
};
|
|
5661
|
+
/**
|
|
5662
|
+
* Starts offline session recording
|
|
5663
|
+
* @param {Object} startOpts - options for session start, same as .start()
|
|
5664
|
+
* @param {Function} onSessionSent - callback that will be called once session is fully sent
|
|
5665
|
+
* */
|
|
5666
|
+
this.offlineRecording = (startOpts = {}, onSessionSent) => {
|
|
5667
|
+
this.onSessionSent = onSessionSent;
|
|
5668
|
+
this.singleBuffer = true;
|
|
5669
|
+
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
5670
|
+
adjustTimeOrigin();
|
|
5671
|
+
this.coldStartTs = now();
|
|
5672
|
+
const saverBuffer = this.localStorage.getItem(bufferStorageKey);
|
|
5673
|
+
if (saverBuffer) {
|
|
5674
|
+
const data = JSON.parse(saverBuffer);
|
|
5675
|
+
this.bufferedMessages1 = Array.isArray(data) ? data : this.bufferedMessages1;
|
|
5676
|
+
this.localStorage.removeItem(bufferStorageKey);
|
|
5677
|
+
}
|
|
5678
|
+
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
5679
|
+
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
5680
|
+
this.activityState = ActivityState.ColdStart;
|
|
5681
|
+
if (startOpts.sessionHash) {
|
|
5682
|
+
this.session.applySessionHash(startOpts.sessionHash);
|
|
5683
|
+
}
|
|
5684
|
+
if (startOpts.forceNew) {
|
|
5685
|
+
this.session.reset();
|
|
5686
|
+
}
|
|
5687
|
+
this.session.assign({
|
|
5688
|
+
userID: startOpts.userID,
|
|
5689
|
+
metadata: startOpts.metadata,
|
|
5690
|
+
});
|
|
5691
|
+
const onStartInfo = { sessionToken: '', userUUID: '', sessionID: '' };
|
|
5692
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
5693
|
+
if (!isNewSession) {
|
|
5694
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
5695
|
+
this.send(TabChange(this.session.getTabId()));
|
|
5696
|
+
}
|
|
5697
|
+
this.observer.observe();
|
|
5698
|
+
this.ticker.start();
|
|
5699
|
+
return {
|
|
5700
|
+
saveBuffer: this.saveBuffer,
|
|
5701
|
+
getBuffer: this.getBuffer,
|
|
5702
|
+
setBuffer: this.setBuffer,
|
|
5703
|
+
};
|
|
5704
|
+
};
|
|
5705
|
+
/**
|
|
5706
|
+
* Saves the captured messages in localStorage (or whatever is used in its place)
|
|
5707
|
+
*
|
|
5708
|
+
* Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
|
|
5709
|
+
*
|
|
5710
|
+
* Keeping the size of local storage reasonable is up to the end users of this library
|
|
5711
|
+
* */
|
|
5712
|
+
this.saveBuffer = () => {
|
|
5713
|
+
this.localStorage.setItem(bufferStorageKey, JSON.stringify(this.bufferedMessages1));
|
|
5714
|
+
};
|
|
5715
|
+
/**
|
|
5716
|
+
* @returns buffer with stored messages for offline recording
|
|
5717
|
+
* */
|
|
5718
|
+
this.getBuffer = () => {
|
|
5719
|
+
return this.bufferedMessages1;
|
|
5720
|
+
};
|
|
5721
|
+
/**
|
|
5722
|
+
* Used to set a buffer with messages array
|
|
5723
|
+
* */
|
|
5724
|
+
this.setBuffer = (buffer) => {
|
|
5725
|
+
this.bufferedMessages1 = buffer;
|
|
5726
|
+
};
|
|
5565
5727
|
this.prevOpts = {};
|
|
5566
5728
|
this.restartCanvasTracking = () => {
|
|
5567
5729
|
this.canvasRecorder?.restartTracking();
|
|
@@ -6068,167 +6230,6 @@ class App {
|
|
|
6068
6230
|
const sessionToken = this.session.getSessionToken(this.projectKey);
|
|
6069
6231
|
return needNewSessionID || !sessionToken;
|
|
6070
6232
|
}
|
|
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
6233
|
/**
|
|
6233
6234
|
* Uploads the stored session buffer to backend
|
|
6234
6235
|
* @returns promise that resolves once messages are loaded, it has to be awaited
|
|
@@ -9651,7 +9652,7 @@ class API {
|
|
|
9651
9652
|
this.signalStartIssue = (reason, missingApi) => {
|
|
9652
9653
|
const doNotTrack = this.checkDoNotTrack();
|
|
9653
9654
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
9654
|
-
trackerVersion: '16.4.
|
|
9655
|
+
trackerVersion: '16.4.3',
|
|
9655
9656
|
projectKey: this.options.projectKey,
|
|
9656
9657
|
doNotTrack,
|
|
9657
9658
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|