@openreplay/tracker 7.0.2 → 8.0.0-beta.1
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/CHANGELOG.md +8 -0
- package/cjs/app/index.d.ts +8 -0
- package/cjs/app/index.js +53 -5
- package/cjs/app/messages.gen.d.ts +2 -0
- package/cjs/app/messages.gen.js +15 -1
- package/cjs/app/sanitizer.d.ts +1 -0
- package/cjs/app/sanitizer.js +6 -4
- package/cjs/app/session.d.ts +4 -0
- package/cjs/app/session.js +18 -0
- package/cjs/common/interaction.d.ts +1 -0
- package/cjs/common/messages.gen.d.ts +12 -2
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +9 -1
- package/cjs/modules/network.js +1 -1
- package/cjs/modules/tabs.d.ts +2 -0
- package/cjs/modules/tabs.js +13 -0
- package/cjs/utils.d.ts +1 -1
- package/cjs/utils.js +13 -11
- package/coverage/clover.xml +2461 -0
- package/coverage/coverage-final.json +38 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +176 -0
- package/coverage/lcov-report/main/app/guards.ts.html +229 -0
- package/coverage/lcov-report/main/app/index.html +206 -0
- package/coverage/lcov-report/main/app/index.ts.html +2053 -0
- package/coverage/lcov-report/main/app/logger.ts.html +277 -0
- package/coverage/lcov-report/main/app/messages.gen.ts.html +2752 -0
- package/coverage/lcov-report/main/app/nodes.ts.html +367 -0
- package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +148 -0
- package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +289 -0
- package/coverage/lcov-report/main/app/observer/index.html +161 -0
- package/coverage/lcov-report/main/app/observer/observer.ts.html +1282 -0
- package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +142 -0
- package/coverage/lcov-report/main/app/observer/top_observer.ts.html +535 -0
- package/coverage/lcov-report/main/app/sanitizer.ts.html +394 -0
- package/coverage/lcov-report/main/app/session.ts.html +559 -0
- package/coverage/lcov-report/main/app/ticker.ts.html +250 -0
- package/coverage/lcov-report/main/index.html +131 -0
- package/coverage/lcov-report/main/index.ts.html +1012 -0
- package/coverage/lcov-report/main/modules/axiosSpy.ts.html +700 -0
- package/coverage/lcov-report/main/modules/connection.ts.html +160 -0
- package/coverage/lcov-report/main/modules/console.ts.html +508 -0
- package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +559 -0
- package/coverage/lcov-report/main/modules/cssrules.ts.html +418 -0
- package/coverage/lcov-report/main/modules/exception.ts.html +385 -0
- package/coverage/lcov-report/main/modules/focus.ts.html +220 -0
- package/coverage/lcov-report/main/modules/fonts.ts.html +289 -0
- package/coverage/lcov-report/main/modules/img.ts.html +433 -0
- package/coverage/lcov-report/main/modules/index.html +371 -0
- package/coverage/lcov-report/main/modules/input.ts.html +811 -0
- package/coverage/lcov-report/main/modules/mouse.ts.html +826 -0
- package/coverage/lcov-report/main/modules/network.ts.html +1129 -0
- package/coverage/lcov-report/main/modules/performance.ts.html +367 -0
- package/coverage/lcov-report/main/modules/scroll.ts.html +364 -0
- package/coverage/lcov-report/main/modules/selection.ts.html +202 -0
- package/coverage/lcov-report/main/modules/tabs.ts.html +124 -0
- package/coverage/lcov-report/main/modules/timing.ts.html +841 -0
- package/coverage/lcov-report/main/modules/viewport.ts.html +250 -0
- package/coverage/lcov-report/main/utils.ts.html +406 -0
- package/coverage/lcov-report/main/vendors/finder/finder.ts.html +1381 -0
- package/coverage/lcov-report/main/vendors/finder/index.html +116 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/webworker/BatchWriter.ts.html +532 -0
- package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +949 -0
- package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +436 -0
- package/coverage/lcov-report/webworker/QueueSender.ts.html +475 -0
- package/coverage/lcov-report/webworker/StringDictionary.ts.html +124 -0
- package/coverage/lcov-report/webworker/index.html +191 -0
- package/coverage/lcov-report/webworker/index.ts.html +592 -0
- package/coverage/lcov.info +4882 -0
- package/jest.config.js +2 -0
- package/lib/app/index.d.ts +8 -0
- package/lib/app/index.js +54 -6
- package/lib/app/messages.gen.d.ts +2 -0
- package/lib/app/messages.gen.js +12 -0
- package/lib/app/sanitizer.d.ts +1 -0
- package/lib/app/sanitizer.js +4 -3
- package/lib/app/session.d.ts +4 -0
- package/lib/app/session.js +18 -0
- package/lib/common/interaction.d.ts +1 -0
- package/lib/common/messages.gen.d.ts +12 -2
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +9 -1
- package/lib/modules/network.js +1 -1
- package/lib/modules/tabs.d.ts +2 -0
- package/lib/modules/tabs.js +10 -0
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +11 -9
- package/package.json +4 -2
- package/cjs/vendors/finder/finder.d.ts +0 -12
- package/cjs/vendors/finder/finder.js +0 -352
- package/lib/vendors/finder/finder.d.ts +0 -12
- package/lib/vendors/finder/finder.js +0 -348
package/CHANGELOG.md
CHANGED
package/cjs/app/index.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ type AppOptions = {
|
|
|
41
41
|
session_reset_key: string;
|
|
42
42
|
session_token_key: string;
|
|
43
43
|
session_pageno_key: string;
|
|
44
|
+
session_tabid_key: string;
|
|
44
45
|
local_uuid_key: string;
|
|
45
46
|
ingestPoint: string;
|
|
46
47
|
resourceBaseHref: string | null;
|
|
@@ -50,6 +51,7 @@ type AppOptions = {
|
|
|
50
51
|
__debug__?: LoggerOptions;
|
|
51
52
|
localStorage: Storage | null;
|
|
52
53
|
sessionStorage: Storage | null;
|
|
54
|
+
forceSingleTab?: boolean;
|
|
53
55
|
onStart?: StartCallback;
|
|
54
56
|
network?: NetworkOptions;
|
|
55
57
|
} & WebworkerOptions & SessOptions;
|
|
@@ -78,6 +80,7 @@ export default class App {
|
|
|
78
80
|
private readonly worker?;
|
|
79
81
|
private compressionThreshold;
|
|
80
82
|
private restartAttempts;
|
|
83
|
+
private readonly bc;
|
|
81
84
|
constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>);
|
|
82
85
|
private _debug;
|
|
83
86
|
private _usingOldFetchPlugin;
|
|
@@ -117,7 +120,12 @@ export default class App {
|
|
|
117
120
|
active(): boolean;
|
|
118
121
|
resetNextPageSession(flag: boolean): void;
|
|
119
122
|
private _start;
|
|
123
|
+
/**
|
|
124
|
+
* basically we ask other tabs during constructor
|
|
125
|
+
* and here we just apply 10ms delay just in case
|
|
126
|
+
* */
|
|
120
127
|
start(...args: Parameters<App['_start']>): Promise<StartPromiseReturn>;
|
|
128
|
+
getTabId(): string;
|
|
121
129
|
stop(stopWorker?: boolean): void;
|
|
122
130
|
}
|
|
123
131
|
export {};
|
package/cjs/app/index.js
CHANGED
|
@@ -34,9 +34,10 @@ class App {
|
|
|
34
34
|
this.stopCallbacks = [];
|
|
35
35
|
this.commitCallbacks = [];
|
|
36
36
|
this.activityState = ActivityState.NotActive;
|
|
37
|
-
this.version = '
|
|
37
|
+
this.version = '8.0.0-beta.1'; // TODO: version compatability check inside each plugin.
|
|
38
38
|
this.compressionThreshold = 24 * 1000;
|
|
39
39
|
this.restartAttempts = 0;
|
|
40
|
+
this.bc = new BroadcastChannel('rick');
|
|
40
41
|
this._usingOldFetchPlugin = false;
|
|
41
42
|
this.delay = 0;
|
|
42
43
|
this.projectKey = projectKey;
|
|
@@ -47,6 +48,7 @@ class App {
|
|
|
47
48
|
session_token_key: '__openreplay_token',
|
|
48
49
|
session_pageno_key: '__openreplay_pageno',
|
|
49
50
|
session_reset_key: '__openreplay_reset',
|
|
51
|
+
session_tabid_key: '__openreplay_tabid',
|
|
50
52
|
local_uuid_key: '__openreplay_uuid',
|
|
51
53
|
ingestPoint: exports.DEFAULT_INGEST_POINT,
|
|
52
54
|
resourceBaseHref: null,
|
|
@@ -55,6 +57,7 @@ class App {
|
|
|
55
57
|
__debug_report_edp: null,
|
|
56
58
|
localStorage: null,
|
|
57
59
|
sessionStorage: null,
|
|
60
|
+
forceSingleTab: false,
|
|
58
61
|
}, options);
|
|
59
62
|
this.revID = this.options.revID;
|
|
60
63
|
this.localStorage = (_a = this.options.localStorage) !== null && _a !== void 0 ? _a : window.localStorage;
|
|
@@ -81,7 +84,7 @@ class App {
|
|
|
81
84
|
this.session.applySessionHash(sessionToken);
|
|
82
85
|
}
|
|
83
86
|
try {
|
|
84
|
-
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3,h){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.isCompressing=!1,this.ingestURL=t+"/v1/web/i",void 0!==h&&(this.isCompressing=!0)}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){this.busy||!this.token?this.queue.push(t):(this.busy=!0,this.isCompressing&&this.onCompress?this.onCompress(t):this.sendBatch(t))}sendNext(){const t=this.queue.shift();t?(this.busy=!0,this.isCompressing&&this.onCompress?this.onCompress(t):this.sendBatch(t)):this.busy=!1}retry(t,i){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout(()=>this.sendBatch(t,i),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t,i){this.busy=!0;const s={Authorization:"Bearer "+this.token};i&&(s["Content-Encoding"]="gzip"),null!==this.token?fetch(this.ingestURL,{body:t,method:"POST",headers:s,keepalive:t.length<65536}).then(s=>{if(401===s.status)return this.busy=!1,void this.onUnauthorised();s.status>=400?this.retry(t,i):(this.attemptsCount=0,this.sendNext())}).catch(s=>{console.warn("OpenReplay:",s),this.retry(t,i)}):setTimeout(()=>{this.sendBatch(t,i)},500)}sendCompressed(t){this.sendBatch(t,!0)}sendUncompressed(t){this.sendBatch(t,!1)}clean(){this.queue.length=0,this.token=null}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,h=0,r=0;r!==i;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 50:return this.uint(t[1])&&this.string(t[2]);case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 79:return this.string(t[1])&&this.string(t[2]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 114:case 115:return this.uint(t[1]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10])}}}class e{constructor(){this.idx=1,this.backDict={}}getKey(t){let i=!1;return this.backDict[t]||(i=!0,this.backDict[t]=this.idx++),[this.backDict[t],i]}}class n{constructor(t,i,n,h){this.pageNo=t,this.timestamp=i,this.url=n,this.onBatch=h,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.strDict=new e,this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}applyDict(t){const[i,s]=this.strDict.getKey(t);return s&&this.writeMessage([50,i,t]),i}writeMessage(t){0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),12===t[0]&&(t=[51,t[1],this.applyDict(t[2]),this.applyDict(t[3])]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new s(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new s(this.beaconSize),this.prepare()))}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var h;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(h||(h={}));let r=null,u=null;function a(){u&&u.finaliseBatch()}function o(){h.Stopping,null!==p&&(clearInterval(p),p=null),u&&(u.clean(),u=null),r&&(r.clean(),r=null),h.NotActive}function c(){postMessage("restart"),o()}h.NotActive;let g,p=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return a(),void o();if(!Array.isArray(i)){if("compressed"===i.type){if(!r)return console.debug("WebWorker: sender not initialised. Compressed batch."),void c();r.sendCompressed(i.batch)}if("uncompressed"===i.type){if(!r)return console.debug("WebWorker: sender not initialised. Uncompressed batch."),void c();r.sendUncompressed(i.batch)}return"start"===i.type?(h.Starting,r=new t(i.ingestPoint,()=>{c()},t=>{!function(t){postMessage({type:"failure",reason:t}),o()}(t)},i.connAttemptCount,i.connAttemptGap,t=>{postMessage({type:"compress",batch:t},[t.buffer])}),u=new n(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===p&&(p=setInterval(a,1e4)),h.Active):"auth"===i.type?r?u?(r.authorise(i.token),void(i.beaconSizeLimit&&u.setBeaconSizeLimit(i.beaconSizeLimit))):(console.debug("WebWorker: writer not initialised. Received auth."),void c()):(console.debug("WebWorker: sender not initialised. Received auth."),void c()):void 0}if(null!==u){const t=u;i.forEach(i=>{55===i[0]&&(i[1]?g=setTimeout(()=>c(),18e5):clearTimeout(g)),t.writeMessage(i)})}u||(postMessage("not_init"),c())}else a()};'], { type: 'text/javascript' })));
|
|
87
|
+
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3,h){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i",this.isCompressing=void 0!==h}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){this.busy||!this.token?this.queue.push(t):(this.busy=!0,this.isCompressing&&this.onCompress?this.onCompress(t):this.sendBatch(t))}sendNext(){const t=this.queue.shift();t?(this.busy=!0,this.isCompressing&&this.onCompress?this.onCompress(t):this.sendBatch(t)):this.busy=!1}retry(t,i){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout(()=>this.sendBatch(t,i),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t,i){this.busy=!0;const s={Authorization:"Bearer "+this.token};i&&(s["Content-Encoding"]="gzip"),null!==this.token?fetch(this.ingestURL,{body:t,method:"POST",headers:s,keepalive:t.length<65536}).then(s=>{if(401===s.status)return this.busy=!1,void this.onUnauthorised();s.status>=400?this.retry(t,i):(this.attemptsCount=0,this.sendNext())}).catch(s=>{console.warn("OpenReplay:",s),this.retry(t,i)}):setTimeout(()=>{this.sendBatch(t,i)},500)}sendCompressed(t){this.sendBatch(t,!0)}sendUncompressed(t){this.sendBatch(t,!1)}clean(){this.sendNext(),setTimeout(()=>{this.token=null,this.queue.length=0},10)}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,h=0,r=0;r!==i;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 50:return this.uint(t[1])&&this.string(t[2]);case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 79:return this.string(t[1])&&this.string(t[2]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 114:case 115:return this.uint(t[1]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10]);case 117:case 118:return this.string(t[1])}}}class e{constructor(){this.idx=1,this.backDict={}}getKey(t){let i=!1;return this.backDict[t]||(i=!0,this.backDict[t]=this.idx++),[this.backDict[t],i]}}class n{constructor(t,i,n,h,r){this.pageNo=t,this.timestamp=i,this.url=n,this.onBatch=h,this.tabId=r,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.strDict=new e,this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url],i=[118,this.tabId];this.writeType(t),this.writeFields(t),this.writeWithSize(i),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}applyDict(t){const[i,s]=this.strDict.getKey(t);return s&&this.writeMessage([50,i,t]),i}writeMessage(t){0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),12===t[0]&&(t=[51,t[1],this.applyDict(t[2]),this.applyDict(t[3])]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new s(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new s(this.beaconSize),this.prepare()))}finaliseBatch(){if(this.isEmpty)return;const t=this.encoder.flush();this.onBatch(t),this.prepare()}clean(){this.encoder.reset()}}var h;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active",t[t.Stopped=4]="Stopped"}(h||(h={}));let r=null,u=null,a=h.NotActive;function o(){u&&u.finaliseBatch()}function c(){a=h.Stopping,null!==l&&(clearInterval(l),l=null),u&&(u.clean(),u=null),r&&(r.clean(),setTimeout(()=>{r=null},20)),setTimeout(()=>{a=h.NotActive},100)}function g(){a!==h.Stopped&&(postMessage("restart"),c())}let p,l=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return o(),c(),a=h.Stopped;if(!Array.isArray(i)){if("compressed"===i.type){if(!r)return console.debug("WebWorker: sender not initialised. Compressed batch."),void g();r.sendCompressed(i.batch)}if("uncompressed"===i.type){if(!r)return console.debug("WebWorker: sender not initialised. Uncompressed batch."),void g();r.sendUncompressed(i.batch)}return"start"===i.type?(a=h.Starting,r=new t(i.ingestPoint,()=>{g()},t=>{!function(t){postMessage({type:"failure",reason:t}),c()}(t)},i.connAttemptCount,i.connAttemptGap,t=>{postMessage({type:"compress",batch:t},[t.buffer])}),u=new n(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t),i.tabId),null===l&&(l=setInterval(o,1e4)),a=h.Active):"auth"===i.type?r?u?(r.authorise(i.token),void(i.beaconSizeLimit&&u.setBeaconSizeLimit(i.beaconSizeLimit))):(console.debug("WebWorker: writer not initialised. Received auth."),void g()):(console.debug("WebWorker: sender not initialised. Received auth."),void g()):void 0}if(null!==u){const t=u;i.forEach(i=>{55===i[0]&&(i[1]?p=setTimeout(()=>g(),18e5):clearTimeout(p)),t.writeMessage(i)})}u||(postMessage("not_init"),g())}else o()};'], { type: 'text/javascript' })));
|
|
85
88
|
this.worker.onerror = (e) => {
|
|
86
89
|
this._debug('webworker_error', e);
|
|
87
90
|
};
|
|
@@ -135,6 +138,28 @@ class App {
|
|
|
135
138
|
catch (e) {
|
|
136
139
|
this._debug('worker_start', e);
|
|
137
140
|
}
|
|
141
|
+
const thisTab = this.session.getTabId();
|
|
142
|
+
if (!this.session.getSessionToken() && !this.options.forceSingleTab) {
|
|
143
|
+
this.bc.postMessage({ line: 'never-gonna-give-you-up', source: thisTab });
|
|
144
|
+
}
|
|
145
|
+
this.bc.onmessage = (ev) => {
|
|
146
|
+
if (ev.data.source === thisTab)
|
|
147
|
+
return;
|
|
148
|
+
if (ev.data.line === 'never-gonna-let-you-down') {
|
|
149
|
+
const sessionToken = ev.data.token;
|
|
150
|
+
this.session.setSessionToken(sessionToken);
|
|
151
|
+
}
|
|
152
|
+
if (ev.data.line === 'never-gonna-give-you-up') {
|
|
153
|
+
const token = this.session.getSessionToken();
|
|
154
|
+
if (token) {
|
|
155
|
+
this.bc.postMessage({
|
|
156
|
+
line: 'never-gonna-let-you-down',
|
|
157
|
+
token,
|
|
158
|
+
source: thisTab,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
138
163
|
}
|
|
139
164
|
_debug(context, e) {
|
|
140
165
|
if (this.options.__debug_report_edp !== null) {
|
|
@@ -176,6 +201,7 @@ class App {
|
|
|
176
201
|
}
|
|
177
202
|
commit() {
|
|
178
203
|
if (this.worker && this.messages.length) {
|
|
204
|
+
this.messages.unshift((0, messages_gen_js_1.TabData)(this.session.getTabId()));
|
|
179
205
|
this.messages.unshift((0, messages_gen_js_1.Timestamp)(this.timestamp()));
|
|
180
206
|
this.worker.postMessage(this.messages);
|
|
181
207
|
this.commitCallbacks.forEach((cb) => cb(this.messages));
|
|
@@ -345,17 +371,21 @@ class App {
|
|
|
345
371
|
url: document.URL,
|
|
346
372
|
connAttemptCount: this.options.connAttemptCount,
|
|
347
373
|
connAttemptGap: this.options.connAttemptGap,
|
|
374
|
+
tabId: this.session.getTabId(),
|
|
348
375
|
});
|
|
349
376
|
const lsReset = this.sessionStorage.getItem(this.options.session_reset_key) !== null;
|
|
350
377
|
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
351
378
|
const needNewSessionID = startOpts.forceNew || lsReset || resetByWorker;
|
|
379
|
+
const sessionToken = this.session.getSessionToken();
|
|
380
|
+
const isNewSession = needNewSessionID || !sessionToken;
|
|
381
|
+
console.log('OpenReplay: starting session', needNewSessionID, sessionToken);
|
|
352
382
|
return window
|
|
353
383
|
.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
354
384
|
method: 'POST',
|
|
355
385
|
headers: {
|
|
356
386
|
'Content-Type': 'application/json',
|
|
357
387
|
},
|
|
358
|
-
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token:
|
|
388
|
+
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: isNewSession ? undefined : sessionToken, deviceMemory: performance_js_1.deviceMemory,
|
|
359
389
|
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit })),
|
|
360
390
|
})
|
|
361
391
|
.then((r) => {
|
|
@@ -397,6 +427,11 @@ class App {
|
|
|
397
427
|
timestamp: startTimestamp || timestamp,
|
|
398
428
|
projectID,
|
|
399
429
|
});
|
|
430
|
+
if (!isNewSession && token === sessionToken) {
|
|
431
|
+
console.log('continuing session on new tab', this.session.getTabId());
|
|
432
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
433
|
+
this.send((0, messages_gen_js_1.TabChange)(this.session.getTabId()));
|
|
434
|
+
}
|
|
400
435
|
// (Re)send Metadata for the case of a new session
|
|
401
436
|
Object.entries(this.session.getInfo().metadata).forEach(([key, value]) => this.send((0, messages_gen_js_1.Metadata)(key, value)));
|
|
402
437
|
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
@@ -431,22 +466,35 @@ class App {
|
|
|
431
466
|
return UnsuccessfulStart(START_ERROR);
|
|
432
467
|
});
|
|
433
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* basically we ask other tabs during constructor
|
|
471
|
+
* and here we just apply 10ms delay just in case
|
|
472
|
+
* */
|
|
434
473
|
start(...args) {
|
|
435
474
|
if (!document.hidden) {
|
|
436
|
-
return
|
|
475
|
+
return new Promise((resolve) => {
|
|
476
|
+
setTimeout(() => {
|
|
477
|
+
resolve(this._start(...args));
|
|
478
|
+
}, 10);
|
|
479
|
+
});
|
|
437
480
|
}
|
|
438
481
|
else {
|
|
439
482
|
return new Promise((resolve) => {
|
|
440
483
|
const onVisibilityChange = () => {
|
|
441
484
|
if (!document.hidden) {
|
|
442
485
|
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
443
|
-
|
|
486
|
+
setTimeout(() => {
|
|
487
|
+
resolve(this._start(...args));
|
|
488
|
+
}, 10);
|
|
444
489
|
}
|
|
445
490
|
};
|
|
446
491
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
447
492
|
});
|
|
448
493
|
}
|
|
449
494
|
}
|
|
495
|
+
getTabId() {
|
|
496
|
+
return this.session.getTabId();
|
|
497
|
+
}
|
|
450
498
|
stop(stopWorker = true) {
|
|
451
499
|
if (this.activityState !== ActivityState.NotActive) {
|
|
452
500
|
try {
|
|
@@ -66,3 +66,5 @@ export declare function SelectionChange(selectionStart: number, selectionEnd: nu
|
|
|
66
66
|
export declare function MouseThrashing(timestamp: number): Messages.MouseThrashing;
|
|
67
67
|
export declare function UnbindNodes(totalRemovedPercent: number): Messages.UnbindNodes;
|
|
68
68
|
export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string, transferredSize: number, cached: boolean): Messages.ResourceTiming;
|
|
69
|
+
export declare function TabChange(tabId: string): Messages.TabChange;
|
|
70
|
+
export declare function TabData(tabId: string): Messages.TabData;
|
package/cjs/app/messages.gen.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetNodeFocus = exports.LoadFontFace = exports.SetPageVisibility = exports.ConnectionInformation = exports.ResourceTimingDeprecated = exports.SetNodeAttributeDict = exports.StringDict = exports.PerformanceTrack = exports.GraphQL = exports.NgRx = exports.MobX = exports.Vuex = exports.Redux = exports.StateAction = exports.OTable = exports.Profiler = exports.Fetch = exports.CSSDeleteRule = exports.CSSInsertRule = exports.Metadata = exports.UserAnonymousID = exports.UserID = exports.CustomEvent = exports.PageRenderTiming = exports.PageLoadTiming = exports.ConsoleLog = exports.NetworkRequest = exports.MouseMove = exports.SetInputChecked = exports.SetInputValue = exports.SetInputTarget = exports.SetNodeScroll = exports.SetNodeData = exports.RemoveNodeAttribute = exports.SetNodeAttribute = exports.RemoveNode = exports.MoveNode = exports.CreateTextNode = exports.CreateElementNode = exports.CreateDocument = exports.SetViewportScroll = exports.SetViewportSize = exports.SetPageLocation = exports.Timestamp = void 0;
|
|
6
|
-
exports.ResourceTiming = exports.UnbindNodes = exports.MouseThrashing = exports.SelectionChange = exports.InputChange = exports.PartitionedMessage = exports.BatchMetadata = exports.Zustand = exports.JSException = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = exports.CreateIFrameDocument = exports.MouseClick = void 0;
|
|
6
|
+
exports.TabData = exports.TabChange = exports.ResourceTiming = exports.UnbindNodes = exports.MouseThrashing = exports.SelectionChange = exports.InputChange = exports.PartitionedMessage = exports.BatchMetadata = exports.Zustand = exports.JSException = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = exports.CreateIFrameDocument = exports.MouseClick = void 0;
|
|
7
7
|
function Timestamp(timestamp) {
|
|
8
8
|
return [
|
|
9
9
|
0 /* Messages.Type.Timestamp */,
|
|
@@ -600,3 +600,17 @@ function ResourceTiming(timestamp, duration, ttfb, headerSize, encodedBodySize,
|
|
|
600
600
|
];
|
|
601
601
|
}
|
|
602
602
|
exports.ResourceTiming = ResourceTiming;
|
|
603
|
+
function TabChange(tabId) {
|
|
604
|
+
return [
|
|
605
|
+
117 /* Messages.Type.TabChange */,
|
|
606
|
+
tabId,
|
|
607
|
+
];
|
|
608
|
+
}
|
|
609
|
+
exports.TabChange = TabChange;
|
|
610
|
+
function TabData(tabId) {
|
|
611
|
+
return [
|
|
612
|
+
118 /* Messages.Type.TabData */,
|
|
613
|
+
tabId,
|
|
614
|
+
];
|
|
615
|
+
}
|
|
616
|
+
exports.TabData = TabData;
|
package/cjs/app/sanitizer.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface Options {
|
|
|
9
9
|
obscureTextNumbers: boolean;
|
|
10
10
|
domSanitizer?: (node: Element) => SanitizeLevel;
|
|
11
11
|
}
|
|
12
|
+
export declare const stringWiper: (input: string) => string;
|
|
12
13
|
export default class Sanitizer {
|
|
13
14
|
private readonly app;
|
|
14
15
|
private readonly obscured;
|
package/cjs/app/sanitizer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SanitizeLevel = void 0;
|
|
3
|
+
exports.stringWiper = exports.SanitizeLevel = void 0;
|
|
4
4
|
const utils_js_1 = require("../utils.js");
|
|
5
5
|
const guards_js_1 = require("./guards.js");
|
|
6
6
|
var SanitizeLevel;
|
|
@@ -9,6 +9,10 @@ var SanitizeLevel;
|
|
|
9
9
|
SanitizeLevel[SanitizeLevel["Obscured"] = 1] = "Obscured";
|
|
10
10
|
SanitizeLevel[SanitizeLevel["Hidden"] = 2] = "Hidden";
|
|
11
11
|
})(SanitizeLevel = exports.SanitizeLevel || (exports.SanitizeLevel = {}));
|
|
12
|
+
const stringWiper = (input) => input
|
|
13
|
+
.trim()
|
|
14
|
+
.replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
|
|
15
|
+
exports.stringWiper = stringWiper;
|
|
12
16
|
class Sanitizer {
|
|
13
17
|
constructor(app, options) {
|
|
14
18
|
this.app = app;
|
|
@@ -43,9 +47,7 @@ class Sanitizer {
|
|
|
43
47
|
sanitize(id, data) {
|
|
44
48
|
if (this.obscured.has(id)) {
|
|
45
49
|
// TODO: is it the best place to put trim() ? Might trimmed spaces be considered in layout in certain cases?
|
|
46
|
-
return data
|
|
47
|
-
.trim()
|
|
48
|
-
.replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
|
|
50
|
+
return (0, exports.stringWiper)(data);
|
|
49
51
|
}
|
|
50
52
|
if (this.options.obscureTextNumbers) {
|
|
51
53
|
data = data.replace(/\d/g, '0');
|
package/cjs/app/session.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ type OnUpdateCallback = (i: Partial<SessionInfo>) => void;
|
|
|
10
10
|
export type Options = {
|
|
11
11
|
session_token_key: string;
|
|
12
12
|
session_pageno_key: string;
|
|
13
|
+
session_tabid_key: string;
|
|
13
14
|
};
|
|
14
15
|
export default class Session {
|
|
15
16
|
private readonly app;
|
|
@@ -20,6 +21,7 @@ export default class Session {
|
|
|
20
21
|
private readonly callbacks;
|
|
21
22
|
private timestamp;
|
|
22
23
|
private projectID;
|
|
24
|
+
private tabId;
|
|
23
25
|
constructor(app: App, options: Options);
|
|
24
26
|
attachUpdateCallback(cb: OnUpdateCallback): void;
|
|
25
27
|
private handleUpdate;
|
|
@@ -32,6 +34,8 @@ export default class Session {
|
|
|
32
34
|
setSessionToken(token: string): void;
|
|
33
35
|
applySessionHash(hash: string): void;
|
|
34
36
|
getSessionHash(): string | undefined;
|
|
37
|
+
getTabId(): string;
|
|
38
|
+
private createTabId;
|
|
35
39
|
getInfo(): SessionInfo;
|
|
36
40
|
reset(): void;
|
|
37
41
|
}
|
package/cjs/app/session.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_js_1 = require("../utils.js");
|
|
3
4
|
class Session {
|
|
4
5
|
constructor(app, options) {
|
|
5
6
|
this.app = app;
|
|
@@ -8,6 +9,7 @@ class Session {
|
|
|
8
9
|
this.userID = null;
|
|
9
10
|
this.callbacks = [];
|
|
10
11
|
this.timestamp = 0;
|
|
12
|
+
this.createTabId();
|
|
11
13
|
}
|
|
12
14
|
attachUpdateCallback(cb) {
|
|
13
15
|
this.callbacks.push(cb);
|
|
@@ -94,6 +96,22 @@ class Session {
|
|
|
94
96
|
}
|
|
95
97
|
return encodeURI(String(pageNo) + '&' + token);
|
|
96
98
|
}
|
|
99
|
+
getTabId() {
|
|
100
|
+
if (!this.tabId)
|
|
101
|
+
this.createTabId();
|
|
102
|
+
return this.tabId;
|
|
103
|
+
}
|
|
104
|
+
createTabId() {
|
|
105
|
+
const localId = this.app.sessionStorage.getItem(this.options.session_tabid_key);
|
|
106
|
+
if (localId) {
|
|
107
|
+
this.tabId = localId;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const randomId = (0, utils_js_1.generateRandomId)(12);
|
|
111
|
+
this.app.sessionStorage.setItem(this.options.session_tabid_key, randomId);
|
|
112
|
+
this.tabId = randomId;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
97
115
|
getInfo() {
|
|
98
116
|
return {
|
|
99
117
|
sessionID: this.sessionID,
|
|
@@ -64,7 +64,9 @@ export declare const enum Type {
|
|
|
64
64
|
SelectionChange = 113,
|
|
65
65
|
MouseThrashing = 114,
|
|
66
66
|
UnbindNodes = 115,
|
|
67
|
-
ResourceTiming = 116
|
|
67
|
+
ResourceTiming = 116,
|
|
68
|
+
TabChange = 117,
|
|
69
|
+
TabData = 118
|
|
68
70
|
}
|
|
69
71
|
export type Timestamp = [
|
|
70
72
|
Type.Timestamp,
|
|
@@ -464,5 +466,13 @@ export type ResourceTiming = [
|
|
|
464
466
|
number,
|
|
465
467
|
boolean
|
|
466
468
|
];
|
|
467
|
-
type
|
|
469
|
+
export type TabChange = [
|
|
470
|
+
Type.TabChange,
|
|
471
|
+
string
|
|
472
|
+
];
|
|
473
|
+
export type TabData = [
|
|
474
|
+
Type.TabData,
|
|
475
|
+
string
|
|
476
|
+
];
|
|
477
|
+
type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequest | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming | TabChange | TabData;
|
|
468
478
|
export default Message;
|
package/cjs/index.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export default class API {
|
|
|
33
33
|
stop(): string | undefined;
|
|
34
34
|
getSessionToken(): string | null | undefined;
|
|
35
35
|
getSessionID(): string | null | undefined;
|
|
36
|
+
getTabId(): string | null;
|
|
36
37
|
sessionID(): string | null | undefined;
|
|
37
38
|
getSessionURL(options?: {
|
|
38
39
|
withCurrentTime?: boolean;
|
package/cjs/index.js
CHANGED
|
@@ -25,6 +25,7 @@ const fonts_js_1 = require("./modules/fonts.js");
|
|
|
25
25
|
const network_js_1 = require("./modules/network.js");
|
|
26
26
|
const constructedStyleSheets_js_1 = require("./modules/constructedStyleSheets.js");
|
|
27
27
|
const selection_js_1 = require("./modules/selection.js");
|
|
28
|
+
const tabs_js_1 = require("./modules/tabs.js");
|
|
28
29
|
const utils_js_1 = require("./utils.js");
|
|
29
30
|
const DOCS_SETUP = '/installation/javascript-sdk';
|
|
30
31
|
function processOptions(obj) {
|
|
@@ -118,6 +119,7 @@ class API {
|
|
|
118
119
|
(0, fonts_js_1.default)(app);
|
|
119
120
|
(0, network_js_1.default)(app, options.network);
|
|
120
121
|
(0, selection_js_1.default)(app);
|
|
122
|
+
(0, tabs_js_1.default)(app);
|
|
121
123
|
window.__OPENREPLAY__ = this;
|
|
122
124
|
if (options.autoResetOnWindowOpen) {
|
|
123
125
|
const wOpen = window.open;
|
|
@@ -142,7 +144,7 @@ class API {
|
|
|
142
144
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
143
145
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
144
146
|
req.send(JSON.stringify({
|
|
145
|
-
trackerVersion: '
|
|
147
|
+
trackerVersion: '8.0.0-beta.1',
|
|
146
148
|
projectKey: options.projectKey,
|
|
147
149
|
doNotTrack,
|
|
148
150
|
// TODO: add precise reason (an exact API missing)
|
|
@@ -188,6 +190,12 @@ class API {
|
|
|
188
190
|
}
|
|
189
191
|
return this.app.getSessionID();
|
|
190
192
|
}
|
|
193
|
+
getTabId() {
|
|
194
|
+
if (this.app === null) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
return this.app.getTabId();
|
|
198
|
+
}
|
|
191
199
|
sessionID() {
|
|
192
200
|
(0, utils_js_1.deprecationWarn)("'sessionID' method", "'getSessionID' method", '/');
|
|
193
201
|
return this.getSessionID();
|
package/cjs/modules/network.js
CHANGED
|
@@ -160,7 +160,7 @@ function default_1(app, opts = {}) {
|
|
|
160
160
|
xhr.addEventListener('load', app.safe((e) => {
|
|
161
161
|
const { headers: reqHs, body: reqBody } = getXHRRequestDataObject(xhr);
|
|
162
162
|
const duration = startTime > 0 ? e.timeStamp - startTime : 0;
|
|
163
|
-
const hString = xhr.getAllResponseHeaders() || ''; // might be null (
|
|
163
|
+
const hString = xhr.getAllResponseHeaders() || ''; // might be null (only if no response received though)
|
|
164
164
|
const headersArr = hString.trim().split(/[\r\n]+/);
|
|
165
165
|
const headerMap = {};
|
|
166
166
|
headersArr.forEach(function (line) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
4
|
+
function default_1(app) {
|
|
5
|
+
function changeTab() {
|
|
6
|
+
if (!document.hidden) {
|
|
7
|
+
app.debug.log('Openreplay: tab change to' + app.session.getTabId());
|
|
8
|
+
app.send((0, messages_gen_js_1.TabChange)(app.session.getTabId()));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
app.attachEventListener(window, 'focus', changeTab, false, false);
|
|
12
|
+
}
|
|
13
|
+
exports.default = default_1;
|
package/cjs/utils.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export declare const DOCS_HOST = "https://docs.openreplay.com";
|
|
|
11
11
|
export declare function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath?: string): void;
|
|
12
12
|
export declare function getLabelAttribute(e: Element): string | null;
|
|
13
13
|
export declare function hasOpenreplayAttribute(e: Element, attr: string): boolean;
|
|
14
|
-
export declare function isIframeCrossdomain(e: HTMLIFrameElement): boolean;
|
|
15
14
|
/**
|
|
16
15
|
* checks if iframe is accessible
|
|
17
16
|
**/
|
|
18
17
|
export declare function canAccessIframe(iframe: HTMLIFrameElement): boolean;
|
|
18
|
+
export declare function generateRandomId(len?: number): string;
|
package/cjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateRandomId = exports.canAccessIframe = exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.now = exports.getTimeOrigin = exports.adjustTimeOrigin = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
|
|
4
4
|
const DEPRECATED_ATTRS = { htmlmasked: 'hidden', masked: 'obscured' };
|
|
5
5
|
exports.IN_BROWSER = !(typeof window === 'undefined');
|
|
6
6
|
exports.IS_FIREFOX = exports.IN_BROWSER && navigator.userAgent.match(/firefox|fxios/i);
|
|
@@ -69,16 +69,6 @@ function hasOpenreplayAttribute(e, attr) {
|
|
|
69
69
|
return false;
|
|
70
70
|
}
|
|
71
71
|
exports.hasOpenreplayAttribute = hasOpenreplayAttribute;
|
|
72
|
-
function isIframeCrossdomain(e) {
|
|
73
|
-
var _a;
|
|
74
|
-
try {
|
|
75
|
-
return ((_a = e.contentWindow) === null || _a === void 0 ? void 0 : _a.location.href) !== window.location.href;
|
|
76
|
-
}
|
|
77
|
-
catch (e) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
exports.isIframeCrossdomain = isIframeCrossdomain;
|
|
82
72
|
/**
|
|
83
73
|
* checks if iframe is accessible
|
|
84
74
|
**/
|
|
@@ -91,3 +81,15 @@ function canAccessIframe(iframe) {
|
|
|
91
81
|
}
|
|
92
82
|
}
|
|
93
83
|
exports.canAccessIframe = canAccessIframe;
|
|
84
|
+
function dec2hex(dec) {
|
|
85
|
+
return dec.toString(16).padStart(2, '0');
|
|
86
|
+
}
|
|
87
|
+
function generateRandomId(len) {
|
|
88
|
+
const arr = new Uint8Array((len || 40) / 2);
|
|
89
|
+
// msCrypto = IE11
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
const safeCrypto = window.crypto || window.msCrypto;
|
|
92
|
+
safeCrypto.getRandomValues(arr);
|
|
93
|
+
return Array.from(arr, dec2hex).join('');
|
|
94
|
+
}
|
|
95
|
+
exports.generateRandomId = generateRandomId;
|