@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
|
@@ -15,13 +15,15 @@ declare class Batcher {
|
|
|
15
15
|
private readonly backendUrl;
|
|
16
16
|
private readonly getToken;
|
|
17
17
|
private readonly init;
|
|
18
|
+
private readonly standalone;
|
|
18
19
|
private readonly autosendInterval;
|
|
19
20
|
private readonly retryTimeout;
|
|
20
21
|
private readonly retryLimit;
|
|
21
22
|
private readonly apiEdp;
|
|
22
23
|
private batch;
|
|
23
24
|
private intervalId;
|
|
24
|
-
|
|
25
|
+
private stopped;
|
|
26
|
+
constructor(backendUrl: string, getToken: () => string | null, init: () => Promise<void>, standalone: boolean);
|
|
25
27
|
getBatches(): {
|
|
26
28
|
data: {
|
|
27
29
|
user_actions: PeopleEvent[];
|
|
@@ -38,8 +40,11 @@ declare class Batcher {
|
|
|
38
40
|
dedupePeopleEvents(): PeopleEvent[];
|
|
39
41
|
private squashPeopleEvents;
|
|
40
42
|
private sendBatch;
|
|
43
|
+
private paused;
|
|
44
|
+
private onVisibilityChange;
|
|
41
45
|
startAutosend(): void;
|
|
42
46
|
flush(): void;
|
|
43
47
|
stop(): void;
|
|
48
|
+
restart(): void;
|
|
44
49
|
}
|
|
45
50
|
export default Batcher;
|
|
@@ -51,6 +51,11 @@ export default class Analytics {
|
|
|
51
51
|
_getToken: () => string | null;
|
|
52
52
|
_getTimestamp: () => number;
|
|
53
53
|
init: () => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Used by tracker when running in blundled mode
|
|
56
|
+
*/
|
|
57
|
+
onStart: () => void;
|
|
58
|
+
onStop: () => void;
|
|
54
59
|
reset: () => void;
|
|
55
60
|
/**
|
|
56
61
|
* COMPATIBILITY LAYER
|
package/dist/lib/entry.js
CHANGED
|
@@ -1742,7 +1742,7 @@ class CanvasRecorder {
|
|
|
1742
1742
|
setTimeout(() => {
|
|
1743
1743
|
this.app.nodes.scanTree(this.captureCanvas);
|
|
1744
1744
|
this.app.nodes.attachNodeCallback(this.captureCanvas);
|
|
1745
|
-
},
|
|
1745
|
+
}, 125);
|
|
1746
1746
|
}
|
|
1747
1747
|
sendSnaps(images, canvasId, createdAt) {
|
|
1748
1748
|
if (Object.keys(this.snapshots).length === 0) {
|
|
@@ -1773,14 +1773,20 @@ class CanvasRecorder {
|
|
|
1773
1773
|
}
|
|
1774
1774
|
async uploadBatch(images, canvasId, createdAt) {
|
|
1775
1775
|
if (this.options.isDebug) {
|
|
1776
|
-
const
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1776
|
+
const packed = await packFrames(images);
|
|
1777
|
+
if (packed) {
|
|
1778
|
+
const fileName = `${createdAt}_${canvasId}.${this.fileExt}.frames`;
|
|
1779
|
+
const url = URL.createObjectURL(new Blob([packed]));
|
|
1780
|
+
const link = document.createElement('a');
|
|
1781
|
+
link.href = url;
|
|
1782
|
+
link.download = fileName;
|
|
1783
|
+
link.style.display = 'none';
|
|
1784
|
+
document.body.appendChild(link);
|
|
1785
|
+
link.click();
|
|
1786
|
+
document.body.removeChild(link);
|
|
1787
|
+
URL.revokeObjectURL(url);
|
|
1788
|
+
}
|
|
1789
|
+
// fall through to also send to backend
|
|
1784
1790
|
}
|
|
1785
1791
|
let formData;
|
|
1786
1792
|
if (this.options.framesSupport) {
|
|
@@ -1925,80 +1931,36 @@ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false
|
|
|
1925
1931
|
canvas.toBlob(onBlob, imageFormat, qualityInt[quality]);
|
|
1926
1932
|
}
|
|
1927
1933
|
}
|
|
1928
|
-
async function
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
const
|
|
1942
|
-
const
|
|
1934
|
+
async function packFrames(images) {
|
|
1935
|
+
const buffers = [];
|
|
1936
|
+
let totalSize = 0;
|
|
1937
|
+
for (const snapshot of images) {
|
|
1938
|
+
if (!snapshot.data)
|
|
1939
|
+
continue;
|
|
1940
|
+
const ab = await snapshot.data.arrayBuffer();
|
|
1941
|
+
buffers.push(ab);
|
|
1942
|
+
totalSize += 8 + 4 + ab.byteLength;
|
|
1943
|
+
}
|
|
1944
|
+
if (totalSize === 0)
|
|
1945
|
+
return null;
|
|
1946
|
+
const packed = new ArrayBuffer(totalSize);
|
|
1947
|
+
const view = new DataView(packed);
|
|
1948
|
+
const bytes = new Uint8Array(packed);
|
|
1943
1949
|
let offset = 0;
|
|
1944
|
-
for (
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
const
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
local.set(nameBytes, 30);
|
|
1959
|
-
// Central directory entry (46 bytes + filename)
|
|
1960
|
-
const cd = new Uint8Array(46 + nameBytes.length);
|
|
1961
|
-
const cv = new DataView(cd.buffer);
|
|
1962
|
-
cv.setUint32(0, 0x02014b50, true);
|
|
1963
|
-
cv.setUint16(4, 20, true);
|
|
1964
|
-
cv.setUint16(6, 20, true);
|
|
1965
|
-
cv.setUint32(16, crc, true);
|
|
1966
|
-
cv.setUint32(20, dataBytes.length, true);
|
|
1967
|
-
cv.setUint32(24, dataBytes.length, true);
|
|
1968
|
-
cv.setUint16(28, nameBytes.length, true);
|
|
1969
|
-
cv.setUint32(42, offset, true);
|
|
1970
|
-
cd.set(nameBytes, 46);
|
|
1971
|
-
parts.push(local);
|
|
1972
|
-
parts.push(dataBytes);
|
|
1973
|
-
centralDir.push(cd);
|
|
1974
|
-
offset += local.length + dataBytes.length;
|
|
1975
|
-
}
|
|
1976
|
-
const cdOffset = offset;
|
|
1977
|
-
let cdSize = 0;
|
|
1978
|
-
for (const entry of centralDir) {
|
|
1979
|
-
parts.push(entry);
|
|
1980
|
-
cdSize += entry.length;
|
|
1981
|
-
}
|
|
1982
|
-
// End of central directory (22 bytes)
|
|
1983
|
-
const eocd = new Uint8Array(22);
|
|
1984
|
-
const ev = new DataView(eocd.buffer);
|
|
1985
|
-
ev.setUint32(0, 0x06054b50, true);
|
|
1986
|
-
ev.setUint16(8, files.length, true);
|
|
1987
|
-
ev.setUint16(10, files.length, true);
|
|
1988
|
-
ev.setUint32(12, cdSize, true);
|
|
1989
|
-
ev.setUint32(16, cdOffset, true);
|
|
1990
|
-
parts.push(eocd);
|
|
1991
|
-
return new Blob(parts, { type: 'application/zip' });
|
|
1992
|
-
}
|
|
1993
|
-
function crc32(data) {
|
|
1994
|
-
let crc = 0xffffffff;
|
|
1995
|
-
for (let i = 0; i < data.length; i++) {
|
|
1996
|
-
crc ^= data[i];
|
|
1997
|
-
for (let j = 0; j < 8; j++) {
|
|
1998
|
-
crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
return (crc ^ 0xffffffff) >>> 0;
|
|
1950
|
+
for (let i = 0; i < images.length; i++) {
|
|
1951
|
+
if (!images[i].data)
|
|
1952
|
+
continue;
|
|
1953
|
+
const ab = buffers.shift();
|
|
1954
|
+
const ts = images[i].id;
|
|
1955
|
+
view.setUint32(offset, ts % 0x100000000, true);
|
|
1956
|
+
view.setUint32(offset + 4, Math.floor(ts / 0x100000000), true);
|
|
1957
|
+
offset += 8;
|
|
1958
|
+
view.setUint32(offset, ab.byteLength, true);
|
|
1959
|
+
offset += 4;
|
|
1960
|
+
bytes.set(new Uint8Array(ab), offset);
|
|
1961
|
+
offset += ab.byteLength;
|
|
1962
|
+
}
|
|
1963
|
+
return packed;
|
|
2002
1964
|
}
|
|
2003
1965
|
|
|
2004
1966
|
const LogLevel = {
|
|
@@ -3848,7 +3810,7 @@ class App {
|
|
|
3848
3810
|
this.stopCallbacks = [];
|
|
3849
3811
|
this.commitCallbacks = [];
|
|
3850
3812
|
this.activityState = ActivityState.NotActive;
|
|
3851
|
-
this.version = '17.2.
|
|
3813
|
+
this.version = '17.2.5'; // TODO: version compatability check inside each plugin.
|
|
3852
3814
|
this.socketMode = false;
|
|
3853
3815
|
this.compressionThreshold = 24 * 1000;
|
|
3854
3816
|
this.bc = null;
|
|
@@ -5032,7 +4994,6 @@ class App {
|
|
|
5032
4994
|
if (startOpts.startCallback) {
|
|
5033
4995
|
startOpts.startCallback(SuccessfulStart(onStartInfo));
|
|
5034
4996
|
}
|
|
5035
|
-
await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5036
4997
|
this.activityState = ActivityState.Active;
|
|
5037
4998
|
if (this.options.crossdomain?.enabled) {
|
|
5038
4999
|
void this.bootChildrenFrames();
|
|
@@ -5069,6 +5030,7 @@ class App {
|
|
|
5069
5030
|
}
|
|
5070
5031
|
this.ticker.start();
|
|
5071
5032
|
this.canvasRecorder?.startTracking();
|
|
5033
|
+
void this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5072
5034
|
return SuccessfulStart(onStartInfo);
|
|
5073
5035
|
}
|
|
5074
5036
|
catch (reason) {
|
|
@@ -8290,6 +8252,8 @@ function webAnimations(app, options = {}) {
|
|
|
8290
8252
|
const lastKF = anim.effect.getKeyframes().at(-1);
|
|
8291
8253
|
if (!lastKF)
|
|
8292
8254
|
return;
|
|
8255
|
+
if (!el || !(el instanceof Element) || !el.isConnected)
|
|
8256
|
+
return;
|
|
8293
8257
|
const computedStyle = getComputedStyle(el);
|
|
8294
8258
|
const keys = Object.keys(lastKF).filter((p) => !toIgnore.includes(p));
|
|
8295
8259
|
// @ts-ignore
|
|
@@ -8701,7 +8665,7 @@ class ConstantProperties {
|
|
|
8701
8665
|
user_id: this.user_id,
|
|
8702
8666
|
distinct_id: this.deviceId,
|
|
8703
8667
|
sdk_edition: 'web',
|
|
8704
|
-
sdk_version: '17.2.
|
|
8668
|
+
sdk_version: '17.2.5',
|
|
8705
8669
|
timezone: getUTCOffsetString(),
|
|
8706
8670
|
search_engine: this.searchEngine,
|
|
8707
8671
|
};
|
|
@@ -9034,10 +8998,11 @@ class People {
|
|
|
9034
8998
|
* Creates batches of events, then sends them at intervals.
|
|
9035
8999
|
*/
|
|
9036
9000
|
class Batcher {
|
|
9037
|
-
constructor(backendUrl, getToken, init) {
|
|
9001
|
+
constructor(backendUrl, getToken, init, standalone) {
|
|
9038
9002
|
this.backendUrl = backendUrl;
|
|
9039
9003
|
this.getToken = getToken;
|
|
9040
9004
|
this.init = init;
|
|
9005
|
+
this.standalone = standalone;
|
|
9041
9006
|
this.autosendInterval = 5 * 1000;
|
|
9042
9007
|
this.retryTimeout = 3 * 1000;
|
|
9043
9008
|
this.retryLimit = 3;
|
|
@@ -9047,10 +9012,20 @@ class Batcher {
|
|
|
9047
9012
|
[categories.events]: [],
|
|
9048
9013
|
};
|
|
9049
9014
|
this.intervalId = null;
|
|
9015
|
+
this.stopped = false;
|
|
9016
|
+
this.paused = false;
|
|
9017
|
+
this.onVisibilityChange = () => {
|
|
9018
|
+
this.paused = document.hidden;
|
|
9019
|
+
};
|
|
9050
9020
|
}
|
|
9051
9021
|
getBatches() {
|
|
9052
9022
|
this.batch[categories.people] = this.dedupePeopleEvents();
|
|
9053
|
-
const finalData = {
|
|
9023
|
+
const finalData = {
|
|
9024
|
+
data: {
|
|
9025
|
+
[categories.people]: [...this.batch[categories.people]],
|
|
9026
|
+
[categories.events]: [...this.batch[categories.events]],
|
|
9027
|
+
},
|
|
9028
|
+
};
|
|
9054
9029
|
return finalData;
|
|
9055
9030
|
}
|
|
9056
9031
|
addEvent(event) {
|
|
@@ -9126,6 +9101,9 @@ class Batcher {
|
|
|
9126
9101
|
return Array.from(uniqueEventsByType.values());
|
|
9127
9102
|
}
|
|
9128
9103
|
sendBatch(batch) {
|
|
9104
|
+
if (this.stopped) {
|
|
9105
|
+
return;
|
|
9106
|
+
}
|
|
9129
9107
|
const sentBatch = batch;
|
|
9130
9108
|
let attempts = 0;
|
|
9131
9109
|
const send = () => {
|
|
@@ -9142,8 +9120,21 @@ class Batcher {
|
|
|
9142
9120
|
},
|
|
9143
9121
|
body: JSON.stringify(sentBatch),
|
|
9144
9122
|
})
|
|
9145
|
-
.then((response) => {
|
|
9146
|
-
if (
|
|
9123
|
+
.then(async (response) => {
|
|
9124
|
+
if (response.status === 401) {
|
|
9125
|
+
const body = await response.json().catch(() => null);
|
|
9126
|
+
if (!this.standalone && body?.error === 'token expired') {
|
|
9127
|
+
this.stop();
|
|
9128
|
+
return;
|
|
9129
|
+
}
|
|
9130
|
+
if (attempts < this.retryLimit) {
|
|
9131
|
+
return this.init().then(() => {
|
|
9132
|
+
send();
|
|
9133
|
+
});
|
|
9134
|
+
}
|
|
9135
|
+
return;
|
|
9136
|
+
}
|
|
9137
|
+
if (response.status === 403) {
|
|
9147
9138
|
if (attempts < this.retryLimit) {
|
|
9148
9139
|
return this.init().then(() => {
|
|
9149
9140
|
send();
|
|
@@ -9167,8 +9158,12 @@ class Batcher {
|
|
|
9167
9158
|
if (this.intervalId) {
|
|
9168
9159
|
clearInterval(this.intervalId);
|
|
9169
9160
|
}
|
|
9161
|
+
this.paused = document.hidden;
|
|
9162
|
+
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
|
9170
9163
|
this.intervalId = setInterval(() => {
|
|
9171
|
-
this.
|
|
9164
|
+
if (!this.paused) {
|
|
9165
|
+
this.flush();
|
|
9166
|
+
}
|
|
9172
9167
|
}, this.autosendInterval);
|
|
9173
9168
|
}
|
|
9174
9169
|
flush() {
|
|
@@ -9188,6 +9183,12 @@ class Batcher {
|
|
|
9188
9183
|
clearInterval(this.intervalId);
|
|
9189
9184
|
this.intervalId = null;
|
|
9190
9185
|
}
|
|
9186
|
+
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
9187
|
+
this.stopped = true;
|
|
9188
|
+
}
|
|
9189
|
+
restart() {
|
|
9190
|
+
this.stopped = false;
|
|
9191
|
+
this.startAutosend();
|
|
9191
9192
|
}
|
|
9192
9193
|
}
|
|
9193
9194
|
|
|
@@ -9254,6 +9255,19 @@ class Analytics {
|
|
|
9254
9255
|
}
|
|
9255
9256
|
}
|
|
9256
9257
|
};
|
|
9258
|
+
/**
|
|
9259
|
+
* Used by tracker when running in blundled mode
|
|
9260
|
+
*/
|
|
9261
|
+
this.onStart = () => {
|
|
9262
|
+
if (!this.standalone) {
|
|
9263
|
+
this.batcher.restart();
|
|
9264
|
+
}
|
|
9265
|
+
};
|
|
9266
|
+
this.onStop = () => {
|
|
9267
|
+
if (!this.standalone) {
|
|
9268
|
+
this.batcher.stop();
|
|
9269
|
+
}
|
|
9270
|
+
};
|
|
9257
9271
|
this.reset = () => {
|
|
9258
9272
|
this.people.reset(true);
|
|
9259
9273
|
this.events.reset();
|
|
@@ -9292,7 +9306,7 @@ class Analytics {
|
|
|
9292
9306
|
this.standalone = !options.notStandalone;
|
|
9293
9307
|
this.token = this.sessionStorage.getItem(STORAGEKEY);
|
|
9294
9308
|
this.constantProperties = new ConstantProperties(this.localStorage, this.sessionStorage);
|
|
9295
|
-
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init);
|
|
9309
|
+
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init, this.standalone);
|
|
9296
9310
|
this.events = new Events(this.constantProperties, this._getTimestamp, this.batcher);
|
|
9297
9311
|
this.people = new People(this.constantProperties, this._getTimestamp, this.setUserId, this.batcher);
|
|
9298
9312
|
if (options.notStandalone) {
|
|
@@ -9353,7 +9367,7 @@ class API {
|
|
|
9353
9367
|
this.signalStartIssue = (reason, missingApi) => {
|
|
9354
9368
|
const doNotTrack = this.checkDoNotTrack();
|
|
9355
9369
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
9356
|
-
trackerVersion: '17.2.
|
|
9370
|
+
trackerVersion: '17.2.5',
|
|
9357
9371
|
projectKey: this.options.projectKey,
|
|
9358
9372
|
doNotTrack,
|
|
9359
9373
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
|
@@ -9505,6 +9519,12 @@ class API {
|
|
|
9505
9519
|
: (options.analytics?.ingestPoint ?? options.ingestPoint ?? defaultEdp),
|
|
9506
9520
|
projectKey: options.projectKey,
|
|
9507
9521
|
});
|
|
9522
|
+
app.attachStartCallback(() => {
|
|
9523
|
+
this.analytics?.onStart();
|
|
9524
|
+
});
|
|
9525
|
+
app.attachStopCallback(() => {
|
|
9526
|
+
this.analytics?.onStop();
|
|
9527
|
+
});
|
|
9508
9528
|
}
|
|
9509
9529
|
if (!this.crossdomainMode) {
|
|
9510
9530
|
// no need to send iframe viewport data since its a node for us
|