@openreplay/tracker 3.4.17-beta.1 → 3.5.2

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/lib/app/index.js CHANGED
@@ -1,21 +1,35 @@
1
- import { timestamp, log, warn } from "../utils.js";
2
- import { Timestamp } from "../messages/index.js";
1
+ import { timestamp } from "../utils.js";
2
+ import { Timestamp, Metadata } from "../messages/index.js";
3
3
  import Nodes from "./nodes.js";
4
4
  import Observer from "./observer/top_observer.js";
5
5
  import Sanitizer from "./sanitizer.js";
6
6
  import Ticker from "./ticker.js";
7
+ import Logger, { LogLevel } from "./logger.js";
7
8
  import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
9
+ var ActivityState;
10
+ (function (ActivityState) {
11
+ ActivityState[ActivityState["NotActive"] = 0] = "NotActive";
12
+ ActivityState[ActivityState["Starting"] = 1] = "Starting";
13
+ ActivityState[ActivityState["Active"] = 2] = "Active";
14
+ })(ActivityState || (ActivityState = {}));
15
+ export const CANCELED = "canceled";
8
16
  // TODO: use backendHost only
9
17
  export const DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
10
18
  export default class App {
11
19
  constructor(projectKey, sessionToken, options) {
20
+ // if (options.onStart !== undefined) {
21
+ // deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)")
22
+ // } ?? maybe onStart is good
12
23
  this.messages = [];
13
24
  this.startCallbacks = [];
14
25
  this.stopCallbacks = [];
15
26
  this.commitCallbacks = [];
16
27
  this._sessionID = null;
17
- this.isActive = false;
18
- this.version = '3.4.17-beta.1';
28
+ this._userID = null;
29
+ this._metadata = {};
30
+ this.activityState = ActivityState.NotActive;
31
+ this.version = '3.5.2'; // TODO: version compatability check inside each plugin.
32
+ this.preStartMessages = [];
19
33
  this.projectKey = projectKey;
20
34
  this.options = Object.assign({
21
35
  revID: '',
@@ -26,9 +40,9 @@ export default class App {
26
40
  local_uuid_key: '__openreplay_uuid',
27
41
  ingestPoint: DEFAULT_INGEST_POINT,
28
42
  resourceBaseHref: null,
43
+ verbose: false,
29
44
  __is_snippet: false,
30
45
  __debug_report_edp: null,
31
- __debug_log: false,
32
46
  }, options);
33
47
  if (sessionToken != null) {
34
48
  sessionStorage.setItem(this.options.session_token_key, sessionToken);
@@ -39,8 +53,10 @@ export default class App {
39
53
  this.observer = new Observer(this, options);
40
54
  this.ticker = new Ticker(this);
41
55
  this.ticker.attach(() => this.commit());
56
+ this.debug = new Logger(this.options.__debug__);
57
+ this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
42
58
  try {
43
- this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}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=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st=1e6,it=2e5,nt=new tt(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}let lt=null;const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(at||""===rt||""===et)return;const t=nt.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),at=!0,dt()}function St(){et="",rt="",null!==lt&&(clearInterval(lt),lt=null),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ft)),nt.checkpoint(),!i.encode(nt)&&(vt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new tt(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null===lt&&(lt=setInterval(vt,1e4))));vt()};
59
+ this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}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=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st=1e6,it=2e5,nt=new tt(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}let lt=null;const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(at||""===rt||""===et)return;const t=nt.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return pt=!1,St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),at=!0,dt()}function St(){et="",rt="",null!==lt&&(clearInterval(lt),lt=null),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ft)),nt.checkpoint(),!i.encode(nt)&&(vt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new tt(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null===lt&&(lt=setInterval(vt,1e4))));vt()};
44
60
  `], { type: 'text/javascript' })));
45
61
  this.worker.onerror = e => {
46
62
  this._debug("webworker_error", e);
@@ -53,7 +69,11 @@ export default class App {
53
69
  }
54
70
  else if (data === "restart") {
55
71
  this.stop();
56
- this.start(true);
72
+ this.start({
73
+ forceNew: true,
74
+ userID: this._userID || undefined,
75
+ metadata: this._metadata || undefined,
76
+ });
57
77
  }
58
78
  };
59
79
  const alertWorker = () => {
@@ -81,14 +101,19 @@ export default class App {
81
101
  })
82
102
  });
83
103
  }
84
- if (this.options.__debug_log) {
85
- warn("OpenReplay error: ", context, e);
86
- }
104
+ this.debug.error("OpenReplay error: ", context, e);
87
105
  }
88
106
  send(message, urgent = false) {
89
- if (!this.isActive) {
107
+ if (this.activityState === ActivityState.NotActive) {
90
108
  return;
91
109
  }
110
+ if (this.activityState === ActivityState.Starting) {
111
+ this.preStartMessages.push(message);
112
+ }
113
+ if (this.preStartMessages.length) {
114
+ this.messages.push(...this.preStartMessages);
115
+ this.preStartMessages.length = 0;
116
+ }
92
117
  this.messages.push(message);
93
118
  if (urgent) {
94
119
  this.commit();
@@ -105,10 +130,6 @@ export default class App {
105
130
  attachCommitCallback(cb) {
106
131
  this.commitCallbacks.push(cb);
107
132
  }
108
- // @Depricated (TODO: remove in 3.5.*)
109
- addCommitCallback(cb) {
110
- this.attachCommitCallback(cb);
111
- }
112
133
  safe(fn) {
113
134
  const app = this;
114
135
  return function (...args) {
@@ -137,6 +158,30 @@ export default class App {
137
158
  this.attachStartCallback(() => target.addEventListener(type, listener, useCapture));
138
159
  this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture));
139
160
  }
161
+ checkRequiredVersion(version) {
162
+ const reqVer = version.split('.');
163
+ const ver = this.version.split('.');
164
+ for (let i = 0; i < ver.length; i++) {
165
+ if (Number(ver[i]) < Number(reqVer[i]) || isNaN(Number(ver[i])) || isNaN(Number(reqVer[i]))) {
166
+ return false;
167
+ }
168
+ }
169
+ return true;
170
+ }
171
+ getStartInfo() {
172
+ return {
173
+ userUUID: localStorage.getItem(this.options.local_uuid_key),
174
+ projectKey: this.projectKey,
175
+ revID: this.revID,
176
+ timestamp: timestamp(),
177
+ trackerVersion: this.version,
178
+ userID: this._userID,
179
+ isSnippet: this.options.__is_snippet,
180
+ };
181
+ }
182
+ getSessionInfo() {
183
+ return Object.assign({ sessionID: this._sessionID, metadata: this._metadata }, this.getStartInfo());
184
+ }
140
185
  getSessionToken() {
141
186
  const token = sessionStorage.getItem(this.options.session_token_key);
142
187
  if (token !== null) {
@@ -176,7 +221,7 @@ export default class App {
176
221
  return url.startsWith(this.options.ingestPoint);
177
222
  }
178
223
  active() {
179
- return this.isActive;
224
+ return this.activityState === ActivityState.Active;
180
225
  }
181
226
  resetNextPageSession(flag) {
182
227
  if (flag) {
@@ -186,116 +231,102 @@ export default class App {
186
231
  sessionStorage.removeItem(this.options.session_reset_key);
187
232
  }
188
233
  }
189
- _start(reset) {
190
- if (!this.isActive) {
234
+ _start(startOpts) {
235
+ if (!this.worker) {
236
+ return Promise.reject("No worker found: perhaps, CSP is not set.");
237
+ }
238
+ if (this.activityState !== ActivityState.NotActive) {
239
+ return Promise.reject("OpenReplay: trying to call `start()` on the instance that has been started already.");
240
+ }
241
+ this.activityState = ActivityState.Starting;
242
+ let pageNo = 0;
243
+ const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
244
+ if (pageNoStr != null) {
245
+ pageNo = parseInt(pageNoStr);
246
+ pageNo++;
247
+ }
248
+ sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
249
+ this._userID = startOpts.userID || null;
250
+ this._metadata = startOpts.metadata || {}; // TODO: update both dynamically on corresponding messages
251
+ const startInfo = this.getStartInfo();
252
+ const messageData = {
253
+ ingestPoint: this.options.ingestPoint,
254
+ pageNo,
255
+ startTimestamp: startInfo.timestamp,
256
+ connAttemptCount: this.options.connAttemptCount,
257
+ connAttemptGap: this.options.connAttemptGap,
258
+ };
259
+ this.worker.postMessage(messageData); // brings delay of 10th ms?
260
+ const sReset = sessionStorage.getItem(this.options.session_reset_key);
261
+ sessionStorage.removeItem(this.options.session_reset_key);
262
+ return window.fetch(this.options.ingestPoint + '/v1/web/start', {
263
+ method: 'POST',
264
+ headers: {
265
+ 'Content-Type': 'application/json',
266
+ },
267
+ body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { token: sessionStorage.getItem(this.options.session_token_key), deviceMemory,
268
+ jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
269
+ })
270
+ .then(r => {
271
+ if (r.status === 200) {
272
+ return r.json();
273
+ }
274
+ else {
275
+ return r.text().then(text => text === CANCELED
276
+ ? Promise.reject(CANCELED) // TODO: return {error: CANCELED} instead
277
+ : Promise.reject(`Server error: ${r.status}. ${text}`));
278
+ }
279
+ })
280
+ .then(r => {
191
281
  if (!this.worker) {
192
- return Promise.reject("No worker found: perhaps, CSP is not set.");
282
+ return Promise.reject("no worker found after start request (this might not happen)");
193
283
  }
194
- this.isActive = true;
195
- let pageNo = 0;
196
- const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
197
- if (pageNoStr != null) {
198
- pageNo = parseInt(pageNoStr);
199
- pageNo++;
284
+ const { token, userUUID, sessionID, beaconSizeLimit } = r;
285
+ if (typeof token !== 'string' ||
286
+ typeof userUUID !== 'string' ||
287
+ (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
288
+ return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
200
289
  }
201
- sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
202
- const startTimestamp = timestamp();
203
- const messageData = {
204
- ingestPoint: this.options.ingestPoint,
205
- pageNo,
206
- startTimestamp,
207
- connAttemptCount: this.options.connAttemptCount,
208
- connAttemptGap: this.options.connAttemptGap,
209
- };
210
- this.worker.postMessage(messageData); // brings delay of 10th ms?
211
- // let token = sessionStorage.getItem(this.options.session_token_key)
212
- // const tokenIsActive = localStorage.getItem("__or_at_" + token)
213
- // if (tokenIsActive) {
214
- // token = null
215
- // }
216
- const sReset = sessionStorage.getItem(this.options.session_reset_key);
217
- sessionStorage.removeItem(this.options.session_reset_key);
218
- return window.fetch(this.options.ingestPoint + '/v1/web/start', {
219
- method: 'POST',
220
- headers: {
221
- 'Content-Type': 'application/json',
222
- },
223
- body: JSON.stringify({
224
- token: sessionStorage.getItem(this.options.session_token_key),
225
- userUUID: localStorage.getItem(this.options.local_uuid_key),
226
- projectKey: this.projectKey,
227
- revID: this.revID,
228
- timestamp: startTimestamp,
229
- trackerVersion: this.version,
230
- isSnippet: this.options.__is_snippet,
231
- deviceMemory,
232
- jsHeapSizeLimit,
233
- reset: reset || sReset !== null,
234
- }),
235
- })
236
- .then(r => {
237
- if (r.status === 200) {
238
- return r.json();
239
- }
240
- else { // TODO: handle canceling && 403
241
- return r.text().then(text => {
242
- throw new Error(`Server error: ${r.status}. ${text}`);
243
- });
244
- }
245
- })
246
- .then(r => {
247
- const { token, userUUID, sessionID, beaconSizeLimit } = r;
248
- if (typeof token !== 'string' ||
249
- typeof userUUID !== 'string' ||
250
- (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
251
- throw new Error(`Incorrect server response: ${JSON.stringify(r)}`);
252
- }
253
- sessionStorage.setItem(this.options.session_token_key, token);
254
- localStorage.setItem(this.options.local_uuid_key, userUUID);
255
- // localStorage.setItem("__or_at_" + token, "true")
256
- // this.attachEventListener(window, 'beforeunload', ()=>{
257
- // localStorage.removeItem("__or_at_" + token)
258
- // }, false);
259
- // this.attachEventListener(window, 'pagehide', ()=>{
260
- // localStorage.removeItem("__or_at_" + token)
261
- // }, false);
262
- if (typeof sessionID === 'string') {
263
- this._sessionID = sessionID;
264
- }
265
- if (!this.worker) {
266
- throw new Error("no worker found after start request (this might not happen)");
267
- }
268
- this.worker.postMessage({ token, beaconSizeLimit });
269
- this.startCallbacks.forEach((cb) => cb());
270
- this.observer.observe();
271
- this.ticker.start();
272
- log("OpenReplay tracking started.");
273
- const onStartInfo = { sessionToken: token, userUUID, sessionID };
274
- if (typeof this.options.onStart === 'function') {
275
- this.options.onStart(onStartInfo);
276
- }
277
- return onStartInfo;
278
- })
279
- .catch(e => {
280
- sessionStorage.removeItem(this.options.session_token_key);
281
- this.stop();
282
- warn("OpenReplay was unable to start. ", e);
283
- this._debug("session_start", e);
284
- throw e;
285
- });
286
- }
287
- return Promise.reject("Player is already active");
290
+ sessionStorage.setItem(this.options.session_token_key, token);
291
+ localStorage.setItem(this.options.local_uuid_key, userUUID);
292
+ if (typeof sessionID === 'string') {
293
+ this._sessionID = sessionID;
294
+ }
295
+ this.activityState = ActivityState.Active;
296
+ this.worker.postMessage({ token, beaconSizeLimit });
297
+ this.startCallbacks.forEach((cb) => cb());
298
+ this.observer.observe();
299
+ this.ticker.start();
300
+ Object.entries(this._metadata).forEach(([key, value]) => this.send(new Metadata(key, value)));
301
+ this.notify.log("OpenReplay tracking started.");
302
+ // TODO: get rid of onStart
303
+ const onStartInfo = { sessionToken: token, userUUID, sessionID };
304
+ if (typeof this.options.onStart === 'function') {
305
+ this.options.onStart(onStartInfo);
306
+ }
307
+ return onStartInfo;
308
+ })
309
+ .catch(reason => {
310
+ sessionStorage.removeItem(this.options.session_token_key);
311
+ this.stop();
312
+ //if (reason === CANCELED) { return Promise.resolve(CANCELED) } // TODO: what to return ????? Throwing is baad
313
+ if (reason !== CANCELED) {
314
+ this.notify.log("OpenReplay was unable to start. ", reason);
315
+ this._debug("session_start", reason);
316
+ }
317
+ return Promise.reject(reason);
318
+ });
288
319
  }
289
- start(reset = false) {
320
+ start(options = { forceNew: false }) {
290
321
  if (!document.hidden) {
291
- return this._start(reset);
322
+ return this._start(options);
292
323
  }
293
324
  else {
294
325
  return new Promise((resolve) => {
295
326
  const onVisibilityChange = () => {
296
327
  if (!document.hidden) {
297
328
  document.removeEventListener("visibilitychange", onVisibilityChange);
298
- resolve(this._start(reset));
329
+ resolve(this._start(options));
299
330
  }
300
331
  };
301
332
  document.addEventListener("visibilitychange", onVisibilityChange);
@@ -303,7 +334,7 @@ export default class App {
303
334
  }
304
335
  }
305
336
  stop() {
306
- if (this.isActive) {
337
+ if (this.activityState !== ActivityState.NotActive) {
307
338
  try {
308
339
  if (this.worker) {
309
340
  this.worker.postMessage("stop");
@@ -313,10 +344,10 @@ export default class App {
313
344
  this.nodes.clear();
314
345
  this.ticker.stop();
315
346
  this.stopCallbacks.forEach((cb) => cb());
316
- log("OpenReplay tracking stopped.");
347
+ this.notify.log("OpenReplay tracking stopped.");
317
348
  }
318
349
  finally {
319
- this.isActive = false;
350
+ this.activityState = ActivityState.NotActive;
320
351
  }
321
352
  }
322
353
  }
@@ -0,0 +1,27 @@
1
+ export declare const LogLevel: {
2
+ readonly Verbose: 4;
3
+ readonly Errors: 4;
4
+ readonly Warnings: 3;
5
+ readonly Log: 2;
6
+ readonly Silent: 0;
7
+ };
8
+ declare type LogLevel = typeof LogLevel[keyof typeof LogLevel];
9
+ declare type CustomLevel = {
10
+ error: boolean;
11
+ warn: boolean;
12
+ log: boolean;
13
+ };
14
+ interface _Options {
15
+ level: LogLevel | CustomLevel;
16
+ messages?: number[];
17
+ }
18
+ export declare type Options = true | _Options | LogLevel;
19
+ export default class Logger {
20
+ private readonly options;
21
+ private readonly opts;
22
+ constructor(options?: Options);
23
+ log(...args: any): void;
24
+ warn(...args: any): void;
25
+ error(...args: any): void;
26
+ }
27
+ export {};
package/lib/app/logger.js CHANGED
@@ -1 +1,39 @@
1
- "use strict";
1
+ export const LogLevel = {
2
+ Verbose: 4,
3
+ Errors: 4,
4
+ Warnings: 3,
5
+ Log: 2,
6
+ Silent: 0,
7
+ };
8
+ function IsCustomLevel(l) {
9
+ return typeof l === 'object';
10
+ }
11
+ export default class Logger {
12
+ constructor(options = LogLevel.Silent) {
13
+ this.options = options;
14
+ this.opts = options === true
15
+ ? { level: LogLevel.Verbose }
16
+ : typeof options === "number" ? { level: options } : options;
17
+ }
18
+ log(...args) {
19
+ if (IsCustomLevel(this.opts.level)
20
+ ? this.opts.level.log
21
+ : this.opts.level >= LogLevel.Log) {
22
+ console.log(...args);
23
+ }
24
+ }
25
+ warn(...args) {
26
+ if (IsCustomLevel(this.opts.level)
27
+ ? this.opts.level.warn
28
+ : this.opts.level >= LogLevel.Warnings) {
29
+ console.warn(...args);
30
+ }
31
+ }
32
+ error(...args) {
33
+ if (IsCustomLevel(this.opts.level)
34
+ ? this.opts.level.error
35
+ : this.opts.level >= LogLevel.Errors) {
36
+ console.error(...args);
37
+ }
38
+ }
39
+ }
package/lib/index.d.ts CHANGED
@@ -2,18 +2,20 @@ import App from "./app/index.js";
2
2
  export { default as App } from './app/index.js';
3
3
  import * as _Messages from "./messages/index.js";
4
4
  export declare const Messages: typeof _Messages;
5
- import { Options as AppOptions } from "./app/index.js";
6
- import { Options as ConsoleOptions } from "./modules/console.js";
7
- import { Options as ExceptionOptions } from "./modules/exception.js";
8
- import { Options as InputOptions } from "./modules/input.js";
9
- import { Options as PerformanceOptions } from "./modules/performance.js";
10
- import { Options as TimingOptions } from "./modules/timing.js";
11
- export type { OnStartInfo } from './app/index.js';
5
+ import type { Options as AppOptions } from "./app/index.js";
6
+ import type { Options as ConsoleOptions } from "./modules/console.js";
7
+ import type { Options as ExceptionOptions } from "./modules/exception.js";
8
+ import type { Options as InputOptions } from "./modules/input.js";
9
+ import type { Options as PerformanceOptions } from "./modules/performance.js";
10
+ import type { Options as TimingOptions } from "./modules/timing.js";
11
+ import type { StartOptions } from './app/index.js';
12
+ import type { OnStartInfo } from './app/index.js';
12
13
  export declare type Options = Partial<AppOptions & ConsoleOptions & ExceptionOptions & InputOptions & PerformanceOptions & TimingOptions> & {
13
14
  projectID?: number;
14
15
  projectKey: string;
15
16
  sessionToken?: string;
16
17
  respectDoNotTrack?: boolean;
18
+ autoResetOnWindowOpen?: boolean;
17
19
  __DISABLE_SECURE_MODE?: boolean;
18
20
  };
19
21
  export default class API {
@@ -22,8 +24,7 @@ export default class API {
22
24
  constructor(options: Options);
23
25
  use<T>(fn: (app: App | null, options?: Options) => T): T;
24
26
  isActive(): boolean;
25
- active(): boolean;
26
- start(): Promise<import("./app/index.js").OnStartInfo>;
27
+ start(startOpts?: StartOptions): Promise<OnStartInfo>;
27
28
  stop(): void;
28
29
  getSessionToken(): string | null | undefined;
29
30
  getSessionID(): string | null | undefined;
@@ -37,5 +38,4 @@ export default class API {
37
38
  event(key: string, payload: any, issue?: boolean): void;
38
39
  issue(key: string, payload: any): void;
39
40
  handleError: (e: Error | ErrorEvent | PromiseRejectionEvent) => void;
40
- resetNextPageSession(flag: boolean): void;
41
41
  }
package/lib/index.js CHANGED
@@ -77,7 +77,7 @@ export default class API {
77
77
  (navigator.doNotTrack == '1'
78
78
  // @ts-ignore
79
79
  || window.doNotTrack == '1');
80
- this.app = doNotTrack ||
80
+ const app = this.app = doNotTrack ||
81
81
  !('Map' in window) ||
82
82
  !('Set' in window) ||
83
83
  !('MutationObserver' in window) ||
@@ -88,20 +88,34 @@ export default class API {
88
88
  !('Worker' in window)
89
89
  ? null
90
90
  : new App(options.projectKey, options.sessionToken, options);
91
- if (this.app !== null) {
92
- Viewport(this.app);
93
- CSSRules(this.app);
94
- Connection(this.app);
95
- Console(this.app, options);
96
- Exception(this.app, options);
97
- Img(this.app);
98
- Input(this.app, options);
99
- Mouse(this.app);
100
- Timing(this.app, options);
101
- Performance(this.app, options);
102
- Scroll(this.app);
103
- Longtasks(this.app);
91
+ if (app !== null) {
92
+ Viewport(app);
93
+ CSSRules(app);
94
+ Connection(app);
95
+ Console(app, options);
96
+ Exception(app, options);
97
+ Img(app);
98
+ Input(app, options);
99
+ Mouse(app);
100
+ Timing(app, options);
101
+ Performance(app, options);
102
+ Scroll(app);
103
+ Longtasks(app);
104
104
  window.__OPENREPLAY__ = this;
105
+ if (options.autoResetOnWindowOpen) {
106
+ const wOpen = window.open;
107
+ app.attachStartCallback(() => {
108
+ // @ts-ignore ?
109
+ window.open = function (...args) {
110
+ app.resetNextPageSession(true);
111
+ wOpen.call(window, ...args);
112
+ app.resetNextPageSession(false);
113
+ };
114
+ });
115
+ app.attachStopCallback(() => {
116
+ window.open = wOpen;
117
+ });
118
+ }
105
119
  }
106
120
  else {
107
121
  console.log("OpenReplay: browser doesn't support API required for tracking or doNotTrack is set to 1.");
@@ -111,7 +125,7 @@ export default class API {
111
125
  // no-cors issue only with text/plain or not-set Content-Type
112
126
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
113
127
  req.send(JSON.stringify({
114
- trackerVersion: '3.4.17-beta.1',
128
+ trackerVersion: '3.5.2',
115
129
  projectKey: options.projectKey,
116
130
  doNotTrack,
117
131
  // TODO: add precise reason (an exact API missing)
@@ -127,11 +141,7 @@ export default class API {
127
141
  }
128
142
  return this.app.active();
129
143
  }
130
- active() {
131
- deprecationWarn("'active' method", "'isActive' method", "/");
132
- return this.isActive();
133
- }
134
- start() {
144
+ start(startOpts) {
135
145
  if (!IN_BROWSER) {
136
146
  console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on ${DOCS_HOST}${DOCS_SETUP}`);
137
147
  return Promise.reject("Trying to start not in browser.");
@@ -139,7 +149,8 @@ export default class API {
139
149
  if (this.app === null) {
140
150
  return Promise.reject("Browser doesn't support required api, or doNotTrack is active.");
141
151
  }
142
- return this.app.start();
152
+ // TODO: check argument typing
153
+ return this.app.start(startOpts);
143
154
  }
144
155
  stop() {
145
156
  if (this.app === null) {
@@ -219,10 +230,4 @@ export default class API {
219
230
  this.app.send(new CustomIssue(key, payload));
220
231
  }
221
232
  }
222
- resetNextPageSession(flag) {
223
- if (typeof flag !== 'boolean' || !this.app) {
224
- return;
225
- }
226
- this.app.resetNextPageSession(flag);
227
- }
228
233
  }
@@ -16,7 +16,7 @@ function printString(arg) {
16
16
  if (Array.isArray(arg)) {
17
17
  return `Array(${arg.length})`;
18
18
  }
19
- return arg.toString();
19
+ return String(arg);
20
20
  }
21
21
  function printFloat(arg) {
22
22
  if (typeof arg !== 'number')