@openreplay/tracker 17.2.3 → 17.2.5
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 +112 -92
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +112 -92
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/cjs/main/modules/analytics/index.d.ts +5 -0
- package/dist/lib/entry.js +112 -92
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +112 -92
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/lib/main/modules/analytics/index.d.ts +5 -0
- package/dist/types/main/modules/analytics/batcher.d.ts +6 -1
- package/dist/types/main/modules/analytics/index.d.ts +5 -0
- package/package.json +1 -1
package/dist/cjs/entry.js
CHANGED
|
@@ -1746,7 +1746,7 @@ class CanvasRecorder {
|
|
|
1746
1746
|
setTimeout(() => {
|
|
1747
1747
|
this.app.nodes.scanTree(this.captureCanvas);
|
|
1748
1748
|
this.app.nodes.attachNodeCallback(this.captureCanvas);
|
|
1749
|
-
},
|
|
1749
|
+
}, 125);
|
|
1750
1750
|
}
|
|
1751
1751
|
sendSnaps(images, canvasId, createdAt) {
|
|
1752
1752
|
if (Object.keys(this.snapshots).length === 0) {
|
|
@@ -1777,14 +1777,20 @@ class CanvasRecorder {
|
|
|
1777
1777
|
}
|
|
1778
1778
|
async uploadBatch(images, canvasId, createdAt) {
|
|
1779
1779
|
if (this.options.isDebug) {
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1780
|
+
const packed = await packFrames(images);
|
|
1781
|
+
if (packed) {
|
|
1782
|
+
const fileName = `${createdAt}_${canvasId}.${this.fileExt}.frames`;
|
|
1783
|
+
const url = URL.createObjectURL(new Blob([packed]));
|
|
1784
|
+
const link = document.createElement('a');
|
|
1785
|
+
link.href = url;
|
|
1786
|
+
link.download = fileName;
|
|
1787
|
+
link.style.display = 'none';
|
|
1788
|
+
document.body.appendChild(link);
|
|
1789
|
+
link.click();
|
|
1790
|
+
document.body.removeChild(link);
|
|
1791
|
+
URL.revokeObjectURL(url);
|
|
1792
|
+
}
|
|
1793
|
+
// fall through to also send to backend
|
|
1788
1794
|
}
|
|
1789
1795
|
let formData;
|
|
1790
1796
|
if (this.options.framesSupport) {
|
|
@@ -1929,80 +1935,36 @@ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false
|
|
|
1929
1935
|
canvas.toBlob(onBlob, imageFormat, qualityInt[quality]);
|
|
1930
1936
|
}
|
|
1931
1937
|
}
|
|
1932
|
-
async function
|
|
1933
|
-
const
|
|
1934
|
-
|
|
1935
|
-
const
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
const
|
|
1946
|
-
const
|
|
1938
|
+
async function packFrames(images) {
|
|
1939
|
+
const buffers = [];
|
|
1940
|
+
let totalSize = 0;
|
|
1941
|
+
for (const snapshot of images) {
|
|
1942
|
+
if (!snapshot.data)
|
|
1943
|
+
continue;
|
|
1944
|
+
const ab = await snapshot.data.arrayBuffer();
|
|
1945
|
+
buffers.push(ab);
|
|
1946
|
+
totalSize += 8 + 4 + ab.byteLength;
|
|
1947
|
+
}
|
|
1948
|
+
if (totalSize === 0)
|
|
1949
|
+
return null;
|
|
1950
|
+
const packed = new ArrayBuffer(totalSize);
|
|
1951
|
+
const view = new DataView(packed);
|
|
1952
|
+
const bytes = new Uint8Array(packed);
|
|
1947
1953
|
let offset = 0;
|
|
1948
|
-
for (
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
local.set(nameBytes, 30);
|
|
1963
|
-
// Central directory entry (46 bytes + filename)
|
|
1964
|
-
const cd = new Uint8Array(46 + nameBytes.length);
|
|
1965
|
-
const cv = new DataView(cd.buffer);
|
|
1966
|
-
cv.setUint32(0, 0x02014b50, true);
|
|
1967
|
-
cv.setUint16(4, 20, true);
|
|
1968
|
-
cv.setUint16(6, 20, true);
|
|
1969
|
-
cv.setUint32(16, crc, true);
|
|
1970
|
-
cv.setUint32(20, dataBytes.length, true);
|
|
1971
|
-
cv.setUint32(24, dataBytes.length, true);
|
|
1972
|
-
cv.setUint16(28, nameBytes.length, true);
|
|
1973
|
-
cv.setUint32(42, offset, true);
|
|
1974
|
-
cd.set(nameBytes, 46);
|
|
1975
|
-
parts.push(local);
|
|
1976
|
-
parts.push(dataBytes);
|
|
1977
|
-
centralDir.push(cd);
|
|
1978
|
-
offset += local.length + dataBytes.length;
|
|
1979
|
-
}
|
|
1980
|
-
const cdOffset = offset;
|
|
1981
|
-
let cdSize = 0;
|
|
1982
|
-
for (const entry of centralDir) {
|
|
1983
|
-
parts.push(entry);
|
|
1984
|
-
cdSize += entry.length;
|
|
1985
|
-
}
|
|
1986
|
-
// End of central directory (22 bytes)
|
|
1987
|
-
const eocd = new Uint8Array(22);
|
|
1988
|
-
const ev = new DataView(eocd.buffer);
|
|
1989
|
-
ev.setUint32(0, 0x06054b50, true);
|
|
1990
|
-
ev.setUint16(8, files.length, true);
|
|
1991
|
-
ev.setUint16(10, files.length, true);
|
|
1992
|
-
ev.setUint32(12, cdSize, true);
|
|
1993
|
-
ev.setUint32(16, cdOffset, true);
|
|
1994
|
-
parts.push(eocd);
|
|
1995
|
-
return new Blob(parts, { type: 'application/zip' });
|
|
1996
|
-
}
|
|
1997
|
-
function crc32(data) {
|
|
1998
|
-
let crc = 0xffffffff;
|
|
1999
|
-
for (let i = 0; i < data.length; i++) {
|
|
2000
|
-
crc ^= data[i];
|
|
2001
|
-
for (let j = 0; j < 8; j++) {
|
|
2002
|
-
crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
return (crc ^ 0xffffffff) >>> 0;
|
|
1954
|
+
for (let i = 0; i < images.length; i++) {
|
|
1955
|
+
if (!images[i].data)
|
|
1956
|
+
continue;
|
|
1957
|
+
const ab = buffers.shift();
|
|
1958
|
+
const ts = images[i].id;
|
|
1959
|
+
view.setUint32(offset, ts % 0x100000000, true);
|
|
1960
|
+
view.setUint32(offset + 4, Math.floor(ts / 0x100000000), true);
|
|
1961
|
+
offset += 8;
|
|
1962
|
+
view.setUint32(offset, ab.byteLength, true);
|
|
1963
|
+
offset += 4;
|
|
1964
|
+
bytes.set(new Uint8Array(ab), offset);
|
|
1965
|
+
offset += ab.byteLength;
|
|
1966
|
+
}
|
|
1967
|
+
return packed;
|
|
2006
1968
|
}
|
|
2007
1969
|
|
|
2008
1970
|
const LogLevel = {
|
|
@@ -3852,7 +3814,7 @@ class App {
|
|
|
3852
3814
|
this.stopCallbacks = [];
|
|
3853
3815
|
this.commitCallbacks = [];
|
|
3854
3816
|
this.activityState = ActivityState.NotActive;
|
|
3855
|
-
this.version = '17.2.
|
|
3817
|
+
this.version = '17.2.5'; // TODO: version compatability check inside each plugin.
|
|
3856
3818
|
this.socketMode = false;
|
|
3857
3819
|
this.compressionThreshold = 24 * 1000;
|
|
3858
3820
|
this.bc = null;
|
|
@@ -5036,7 +4998,6 @@ class App {
|
|
|
5036
4998
|
if (startOpts.startCallback) {
|
|
5037
4999
|
startOpts.startCallback(SuccessfulStart(onStartInfo));
|
|
5038
5000
|
}
|
|
5039
|
-
await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5040
5001
|
this.activityState = ActivityState.Active;
|
|
5041
5002
|
if (this.options.crossdomain?.enabled) {
|
|
5042
5003
|
void this.bootChildrenFrames();
|
|
@@ -5073,6 +5034,7 @@ class App {
|
|
|
5073
5034
|
}
|
|
5074
5035
|
this.ticker.start();
|
|
5075
5036
|
this.canvasRecorder?.startTracking();
|
|
5037
|
+
void this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5076
5038
|
return SuccessfulStart(onStartInfo);
|
|
5077
5039
|
}
|
|
5078
5040
|
catch (reason) {
|
|
@@ -8294,6 +8256,8 @@ function webAnimations(app, options = {}) {
|
|
|
8294
8256
|
const lastKF = anim.effect.getKeyframes().at(-1);
|
|
8295
8257
|
if (!lastKF)
|
|
8296
8258
|
return;
|
|
8259
|
+
if (!el || !(el instanceof Element) || !el.isConnected)
|
|
8260
|
+
return;
|
|
8297
8261
|
const computedStyle = getComputedStyle(el);
|
|
8298
8262
|
const keys = Object.keys(lastKF).filter((p) => !toIgnore.includes(p));
|
|
8299
8263
|
// @ts-ignore
|
|
@@ -8705,7 +8669,7 @@ class ConstantProperties {
|
|
|
8705
8669
|
user_id: this.user_id,
|
|
8706
8670
|
distinct_id: this.deviceId,
|
|
8707
8671
|
sdk_edition: 'web',
|
|
8708
|
-
sdk_version: '17.2.
|
|
8672
|
+
sdk_version: '17.2.5',
|
|
8709
8673
|
timezone: getUTCOffsetString(),
|
|
8710
8674
|
search_engine: this.searchEngine,
|
|
8711
8675
|
};
|
|
@@ -9038,10 +9002,11 @@ class People {
|
|
|
9038
9002
|
* Creates batches of events, then sends them at intervals.
|
|
9039
9003
|
*/
|
|
9040
9004
|
class Batcher {
|
|
9041
|
-
constructor(backendUrl, getToken, init) {
|
|
9005
|
+
constructor(backendUrl, getToken, init, standalone) {
|
|
9042
9006
|
this.backendUrl = backendUrl;
|
|
9043
9007
|
this.getToken = getToken;
|
|
9044
9008
|
this.init = init;
|
|
9009
|
+
this.standalone = standalone;
|
|
9045
9010
|
this.autosendInterval = 5 * 1000;
|
|
9046
9011
|
this.retryTimeout = 3 * 1000;
|
|
9047
9012
|
this.retryLimit = 3;
|
|
@@ -9051,10 +9016,20 @@ class Batcher {
|
|
|
9051
9016
|
[categories.events]: [],
|
|
9052
9017
|
};
|
|
9053
9018
|
this.intervalId = null;
|
|
9019
|
+
this.stopped = false;
|
|
9020
|
+
this.paused = false;
|
|
9021
|
+
this.onVisibilityChange = () => {
|
|
9022
|
+
this.paused = document.hidden;
|
|
9023
|
+
};
|
|
9054
9024
|
}
|
|
9055
9025
|
getBatches() {
|
|
9056
9026
|
this.batch[categories.people] = this.dedupePeopleEvents();
|
|
9057
|
-
const finalData = {
|
|
9027
|
+
const finalData = {
|
|
9028
|
+
data: {
|
|
9029
|
+
[categories.people]: [...this.batch[categories.people]],
|
|
9030
|
+
[categories.events]: [...this.batch[categories.events]],
|
|
9031
|
+
},
|
|
9032
|
+
};
|
|
9058
9033
|
return finalData;
|
|
9059
9034
|
}
|
|
9060
9035
|
addEvent(event) {
|
|
@@ -9130,6 +9105,9 @@ class Batcher {
|
|
|
9130
9105
|
return Array.from(uniqueEventsByType.values());
|
|
9131
9106
|
}
|
|
9132
9107
|
sendBatch(batch) {
|
|
9108
|
+
if (this.stopped) {
|
|
9109
|
+
return;
|
|
9110
|
+
}
|
|
9133
9111
|
const sentBatch = batch;
|
|
9134
9112
|
let attempts = 0;
|
|
9135
9113
|
const send = () => {
|
|
@@ -9146,8 +9124,21 @@ class Batcher {
|
|
|
9146
9124
|
},
|
|
9147
9125
|
body: JSON.stringify(sentBatch),
|
|
9148
9126
|
})
|
|
9149
|
-
.then((response) => {
|
|
9150
|
-
if (
|
|
9127
|
+
.then(async (response) => {
|
|
9128
|
+
if (response.status === 401) {
|
|
9129
|
+
const body = await response.json().catch(() => null);
|
|
9130
|
+
if (!this.standalone && body?.error === 'token expired') {
|
|
9131
|
+
this.stop();
|
|
9132
|
+
return;
|
|
9133
|
+
}
|
|
9134
|
+
if (attempts < this.retryLimit) {
|
|
9135
|
+
return this.init().then(() => {
|
|
9136
|
+
send();
|
|
9137
|
+
});
|
|
9138
|
+
}
|
|
9139
|
+
return;
|
|
9140
|
+
}
|
|
9141
|
+
if (response.status === 403) {
|
|
9151
9142
|
if (attempts < this.retryLimit) {
|
|
9152
9143
|
return this.init().then(() => {
|
|
9153
9144
|
send();
|
|
@@ -9171,8 +9162,12 @@ class Batcher {
|
|
|
9171
9162
|
if (this.intervalId) {
|
|
9172
9163
|
clearInterval(this.intervalId);
|
|
9173
9164
|
}
|
|
9165
|
+
this.paused = document.hidden;
|
|
9166
|
+
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
|
9174
9167
|
this.intervalId = setInterval(() => {
|
|
9175
|
-
this.
|
|
9168
|
+
if (!this.paused) {
|
|
9169
|
+
this.flush();
|
|
9170
|
+
}
|
|
9176
9171
|
}, this.autosendInterval);
|
|
9177
9172
|
}
|
|
9178
9173
|
flush() {
|
|
@@ -9192,6 +9187,12 @@ class Batcher {
|
|
|
9192
9187
|
clearInterval(this.intervalId);
|
|
9193
9188
|
this.intervalId = null;
|
|
9194
9189
|
}
|
|
9190
|
+
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
9191
|
+
this.stopped = true;
|
|
9192
|
+
}
|
|
9193
|
+
restart() {
|
|
9194
|
+
this.stopped = false;
|
|
9195
|
+
this.startAutosend();
|
|
9195
9196
|
}
|
|
9196
9197
|
}
|
|
9197
9198
|
|
|
@@ -9258,6 +9259,19 @@ class Analytics {
|
|
|
9258
9259
|
}
|
|
9259
9260
|
}
|
|
9260
9261
|
};
|
|
9262
|
+
/**
|
|
9263
|
+
* Used by tracker when running in blundled mode
|
|
9264
|
+
*/
|
|
9265
|
+
this.onStart = () => {
|
|
9266
|
+
if (!this.standalone) {
|
|
9267
|
+
this.batcher.restart();
|
|
9268
|
+
}
|
|
9269
|
+
};
|
|
9270
|
+
this.onStop = () => {
|
|
9271
|
+
if (!this.standalone) {
|
|
9272
|
+
this.batcher.stop();
|
|
9273
|
+
}
|
|
9274
|
+
};
|
|
9261
9275
|
this.reset = () => {
|
|
9262
9276
|
this.people.reset(true);
|
|
9263
9277
|
this.events.reset();
|
|
@@ -9296,7 +9310,7 @@ class Analytics {
|
|
|
9296
9310
|
this.standalone = !options.notStandalone;
|
|
9297
9311
|
this.token = this.sessionStorage.getItem(STORAGEKEY);
|
|
9298
9312
|
this.constantProperties = new ConstantProperties(this.localStorage, this.sessionStorage);
|
|
9299
|
-
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init);
|
|
9313
|
+
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init, this.standalone);
|
|
9300
9314
|
this.events = new Events(this.constantProperties, this._getTimestamp, this.batcher);
|
|
9301
9315
|
this.people = new People(this.constantProperties, this._getTimestamp, this.setUserId, this.batcher);
|
|
9302
9316
|
if (options.notStandalone) {
|
|
@@ -9357,7 +9371,7 @@ class API {
|
|
|
9357
9371
|
this.signalStartIssue = (reason, missingApi) => {
|
|
9358
9372
|
const doNotTrack = this.checkDoNotTrack();
|
|
9359
9373
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
9360
|
-
trackerVersion: '17.2.
|
|
9374
|
+
trackerVersion: '17.2.5',
|
|
9361
9375
|
projectKey: this.options.projectKey,
|
|
9362
9376
|
doNotTrack,
|
|
9363
9377
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
|
@@ -9509,6 +9523,12 @@ class API {
|
|
|
9509
9523
|
: (options.analytics?.ingestPoint ?? options.ingestPoint ?? defaultEdp),
|
|
9510
9524
|
projectKey: options.projectKey,
|
|
9511
9525
|
});
|
|
9526
|
+
app.attachStartCallback(() => {
|
|
9527
|
+
this.analytics?.onStart();
|
|
9528
|
+
});
|
|
9529
|
+
app.attachStopCallback(() => {
|
|
9530
|
+
this.analytics?.onStop();
|
|
9531
|
+
});
|
|
9512
9532
|
}
|
|
9513
9533
|
if (!this.crossdomainMode) {
|
|
9514
9534
|
// no need to send iframe viewport data since its a node for us
|