@openreplay/tracker 3.5.2 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import Nodes from "./nodes.js";
3
3
  import Sanitizer from "./sanitizer.js";
4
4
  import Ticker from "./ticker.js";
5
5
  import Logger from "./logger.js";
6
+ import Session from "./session.js";
6
7
  import type { Options as ObserverOptions } from "./observer/top_observer.js";
7
8
  import type { Options as SanitizerOptions } from "./sanitizer.js";
8
9
  import type { Options as LoggerOptions } from "./logger.js";
@@ -44,6 +45,7 @@ export default class App {
44
45
  readonly sanitizer: Sanitizer;
45
46
  readonly debug: Logger;
46
47
  readonly notify: Logger;
48
+ readonly session: Session;
47
49
  private readonly messages;
48
50
  private readonly observer;
49
51
  private readonly startCallbacks;
@@ -51,9 +53,6 @@ export default class App {
51
53
  private readonly commitCallbacks;
52
54
  private readonly options;
53
55
  private readonly revID;
54
- private _sessionID;
55
- private _userID;
56
- private _metadata;
57
56
  private activityState;
58
57
  private version;
59
58
  private readonly worker?;
@@ -62,8 +61,8 @@ export default class App {
62
61
  private readonly preStartMessages;
63
62
  send(message: Message, urgent?: boolean): void;
64
63
  private commit;
65
- attachCommitCallback(cb: CommitCallback): void;
66
64
  safe<T extends (...args: any[]) => void>(fn: T): T;
65
+ attachCommitCallback(cb: CommitCallback): void;
67
66
  attachStartCallback(cb: Callback): void;
68
67
  attachStopCallback(cb: Callback): void;
69
68
  attachEventListener(target: EventTarget, type: string, listener: EventListener, useSafe?: boolean, useCapture?: boolean): void;
@@ -75,10 +74,10 @@ export default class App {
75
74
  revID: string;
76
75
  timestamp: number;
77
76
  trackerVersion: string;
78
- userID: string | null;
79
77
  isSnippet: boolean;
80
78
  sessionID: string | null;
81
79
  metadata: Record<string, string>;
80
+ userID: string | null;
82
81
  };
83
82
  getSessionToken(): string | undefined;
84
83
  getSessionID(): string | undefined;
package/cjs/app/index.js CHANGED
@@ -8,6 +8,7 @@ const top_observer_js_1 = require("./observer/top_observer.js");
8
8
  const sanitizer_js_1 = require("./sanitizer.js");
9
9
  const ticker_js_1 = require("./ticker.js");
10
10
  const logger_js_1 = require("./logger.js");
11
+ const session_js_1 = require("./session.js");
11
12
  const performance_js_1 = require("../modules/performance.js");
12
13
  var ActivityState;
13
14
  (function (ActivityState) {
@@ -27,11 +28,8 @@ class App {
27
28
  this.startCallbacks = [];
28
29
  this.stopCallbacks = [];
29
30
  this.commitCallbacks = [];
30
- this._sessionID = null;
31
- this._userID = null;
32
- this._metadata = {};
33
31
  this.activityState = ActivityState.NotActive;
34
- this.version = '3.5.2'; // TODO: version compatability check inside each plugin.
32
+ this.version = '3.5.3'; // TODO: version compatability check inside each plugin.
35
33
  this.preStartMessages = [];
36
34
  this.projectKey = projectKey;
37
35
  this.options = Object.assign({
@@ -58,25 +56,20 @@ class App {
58
56
  this.ticker.attach(() => this.commit());
59
57
  this.debug = new logger_js_1.default(this.options.__debug__);
60
58
  this.notify = new logger_js_1.default(this.options.verbose ? logger_js_1.LogLevel.Warnings : logger_js_1.LogLevel.Silent);
59
+ this.session = new session_js_1.default(this);
61
60
  try {
62
61
  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()};
63
62
  `], { type: 'text/javascript' })));
64
63
  this.worker.onerror = e => {
65
64
  this._debug("webworker_error", e);
66
65
  };
67
- let lastTs = (0, utils_js_1.timestamp)();
68
- let fileno = 0;
69
66
  this.worker.onmessage = ({ data }) => {
70
67
  if (data === null) {
71
68
  this.stop();
72
69
  }
73
70
  else if (data === "restart") {
74
71
  this.stop();
75
- this.start({
76
- forceNew: true,
77
- userID: this._userID || undefined,
78
- metadata: this._metadata || undefined,
79
- });
72
+ this.start({ forceNew: true });
80
73
  }
81
74
  };
82
75
  const alertWorker = () => {
@@ -130,9 +123,6 @@ class App {
130
123
  this.messages.length = 0;
131
124
  }
132
125
  }
133
- attachCommitCallback(cb) {
134
- this.commitCallbacks.push(cb);
135
- }
136
126
  safe(fn) {
137
127
  const app = this;
138
128
  return function (...args) {
@@ -148,6 +138,9 @@ class App {
148
138
  }
149
139
  }; // TODO: correct typing
150
140
  }
141
+ attachCommitCallback(cb) {
142
+ this.commitCallbacks.push(cb);
143
+ }
151
144
  attachStartCallback(cb) {
152
145
  this.startCallbacks.push(cb);
153
146
  }
@@ -178,12 +171,11 @@ class App {
178
171
  revID: this.revID,
179
172
  timestamp: (0, utils_js_1.timestamp)(),
180
173
  trackerVersion: this.version,
181
- userID: this._userID,
182
174
  isSnippet: this.options.__is_snippet,
183
175
  };
184
176
  }
185
177
  getSessionInfo() {
186
- return Object.assign({ sessionID: this._sessionID, metadata: this._metadata }, this.getStartInfo());
178
+ return Object.assign(Object.assign({}, this.session.getInfo()), this.getStartInfo());
187
179
  }
188
180
  getSessionToken() {
189
181
  const token = sessionStorage.getItem(this.options.session_token_key);
@@ -192,7 +184,7 @@ class App {
192
184
  }
193
185
  }
194
186
  getSessionID() {
195
- return this._sessionID || undefined;
187
+ return this.session.getInfo().sessionID || undefined;
196
188
  }
197
189
  getHost() {
198
190
  return new URL(this.options.ingestPoint).hostname;
@@ -249,8 +241,6 @@ class App {
249
241
  pageNo++;
250
242
  }
251
243
  sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
252
- this._userID = startOpts.userID || null;
253
- this._metadata = startOpts.metadata || {}; // TODO: update both dynamically on corresponding messages
254
244
  const startInfo = this.getStartInfo();
255
245
  const messageData = {
256
246
  ingestPoint: this.options.ingestPoint,
@@ -267,7 +257,7 @@ class App {
267
257
  headers: {
268
258
  'Content-Type': 'application/json',
269
259
  },
270
- body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { token: sessionStorage.getItem(this.options.session_token_key), deviceMemory: performance_js_1.deviceMemory,
260
+ body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID: startOpts.userID || this.session.getInfo().userID, token: sessionStorage.getItem(this.options.session_token_key), deviceMemory: performance_js_1.deviceMemory,
271
261
  jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
272
262
  })
273
263
  .then(r => {
@@ -292,15 +282,12 @@ class App {
292
282
  }
293
283
  sessionStorage.setItem(this.options.session_token_key, token);
294
284
  localStorage.setItem(this.options.local_uuid_key, userUUID);
295
- if (typeof sessionID === 'string') {
296
- this._sessionID = sessionID;
297
- }
285
+ this.session.update(Object.assign({ sessionID }, startOpts));
298
286
  this.activityState = ActivityState.Active;
299
287
  this.worker.postMessage({ token, beaconSizeLimit });
300
288
  this.startCallbacks.forEach((cb) => cb());
301
289
  this.observer.observe();
302
290
  this.ticker.start();
303
- Object.entries(this._metadata).forEach(([key, value]) => this.send(new index_js_1.Metadata(key, value)));
304
291
  this.notify.log("OpenReplay tracking started.");
305
292
  // TODO: get rid of onStart
306
293
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
@@ -1,8 +1,8 @@
1
1
  export declare const LogLevel: {
2
- readonly Verbose: 4;
3
- readonly Errors: 4;
2
+ readonly Verbose: 5;
3
+ readonly Log: 4;
4
4
  readonly Warnings: 3;
5
- readonly Log: 2;
5
+ readonly Errors: 2;
6
6
  readonly Silent: 0;
7
7
  };
8
8
  declare type LogLevel = typeof LogLevel[keyof typeof LogLevel];
@@ -18,7 +18,6 @@ interface _Options {
18
18
  export declare type Options = true | _Options | LogLevel;
19
19
  export default class Logger {
20
20
  private readonly options;
21
- private readonly opts;
22
21
  constructor(options?: Options);
23
22
  log(...args: any): void;
24
23
  warn(...args: any): void;
package/cjs/app/logger.js CHANGED
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LogLevel = void 0;
4
4
  exports.LogLevel = {
5
- Verbose: 4,
6
- Errors: 4,
5
+ Verbose: 5,
6
+ Log: 4,
7
7
  Warnings: 3,
8
- Log: 2,
8
+ Errors: 2,
9
9
  Silent: 0,
10
10
  };
11
11
  function IsCustomLevel(l) {
@@ -13,29 +13,28 @@ function IsCustomLevel(l) {
13
13
  }
14
14
  class Logger {
15
15
  constructor(options = exports.LogLevel.Silent) {
16
- this.options = options;
17
- this.opts = options === true
16
+ this.options = options === true
18
17
  ? { level: exports.LogLevel.Verbose }
19
18
  : typeof options === "number" ? { level: options } : options;
20
19
  }
21
20
  log(...args) {
22
- if (IsCustomLevel(this.opts.level)
23
- ? this.opts.level.log
24
- : this.opts.level >= exports.LogLevel.Log) {
21
+ if (IsCustomLevel(this.options.level)
22
+ ? this.options.level.log
23
+ : this.options.level >= exports.LogLevel.Log) {
25
24
  console.log(...args);
26
25
  }
27
26
  }
28
27
  warn(...args) {
29
- if (IsCustomLevel(this.opts.level)
30
- ? this.opts.level.warn
31
- : this.opts.level >= exports.LogLevel.Warnings) {
28
+ if (IsCustomLevel(this.options.level)
29
+ ? this.options.level.warn
30
+ : this.options.level >= exports.LogLevel.Warnings) {
32
31
  console.warn(...args);
33
32
  }
34
33
  }
35
34
  error(...args) {
36
- if (IsCustomLevel(this.opts.level)
37
- ? this.opts.level.error
38
- : this.opts.level >= exports.LogLevel.Errors) {
35
+ if (IsCustomLevel(this.options.level)
36
+ ? this.options.level.error
37
+ : this.options.level >= exports.LogLevel.Errors) {
39
38
  console.error(...args);
40
39
  }
41
40
  }
@@ -0,0 +1,25 @@
1
+ import App from "./index.js";
2
+ interface SessionInfo {
3
+ sessionID: string | null;
4
+ metadata: Record<string, string>;
5
+ userID: string | null;
6
+ }
7
+ declare type OnUpdateCallback = (i: Partial<SessionInfo>) => void;
8
+ export default class Session {
9
+ private app;
10
+ private metadata;
11
+ private userID;
12
+ private sessionID;
13
+ private activityState;
14
+ private callbacks;
15
+ constructor(app: App);
16
+ attachUpdateCallback(cb: OnUpdateCallback): void;
17
+ private handleUpdate;
18
+ update({ userID, metadata, sessionID }: Partial<SessionInfo>): void;
19
+ private _setMetadata;
20
+ private _setUserID;
21
+ setMetadata(key: string, value: string): void;
22
+ setUserID(userID: string): void;
23
+ getInfo(): SessionInfo;
24
+ }
25
+ export {};
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_js_1 = require("../messages/index.js");
4
+ var ActivityState;
5
+ (function (ActivityState) {
6
+ ActivityState[ActivityState["NotActive"] = 0] = "NotActive";
7
+ ActivityState[ActivityState["Starting"] = 1] = "Starting";
8
+ ActivityState[ActivityState["Active"] = 2] = "Active";
9
+ })(ActivityState || (ActivityState = {}));
10
+ class Session {
11
+ constructor(app) {
12
+ this.app = app;
13
+ this.metadata = {};
14
+ this.userID = null;
15
+ this.sessionID = null;
16
+ this.activityState = ActivityState.NotActive;
17
+ this.callbacks = [];
18
+ }
19
+ attachUpdateCallback(cb) {
20
+ this.callbacks.push(cb);
21
+ }
22
+ handleUpdate() {
23
+ const sessInfo = this.getInfo();
24
+ if (sessInfo.userID == null) {
25
+ delete sessInfo.userID;
26
+ }
27
+ if (sessInfo.sessionID == null) {
28
+ delete sessInfo.sessionID;
29
+ }
30
+ this.callbacks.forEach(cb => cb(sessInfo));
31
+ }
32
+ update({ userID, metadata, sessionID }) {
33
+ if (userID != null) { // TODO clear nullable/undefinable types
34
+ this._setUserID(userID);
35
+ }
36
+ if (metadata !== undefined) {
37
+ Object.entries(metadata).forEach(kv => this._setMetadata(...kv));
38
+ }
39
+ if (sessionID !== undefined) {
40
+ this.sessionID = sessionID;
41
+ }
42
+ this.handleUpdate();
43
+ }
44
+ _setMetadata(key, value) {
45
+ this.app.send(new index_js_1.Metadata(key, value));
46
+ this.metadata[key] = value;
47
+ }
48
+ _setUserID(userID) {
49
+ this.app.send(new index_js_1.UserID(userID));
50
+ this.userID = userID;
51
+ }
52
+ setMetadata(key, value) {
53
+ this._setMetadata(key, value);
54
+ this.handleUpdate();
55
+ }
56
+ setUserID(userID) {
57
+ this._setUserID(userID);
58
+ this.handleUpdate();
59
+ }
60
+ getInfo() {
61
+ return {
62
+ sessionID: this.sessionID,
63
+ metadata: this.metadata,
64
+ userID: this.userID,
65
+ };
66
+ }
67
+ }
68
+ exports.default = Session;
package/cjs/index.js CHANGED
@@ -17,7 +17,6 @@ const timing_js_1 = require("./modules/timing.js");
17
17
  const performance_js_1 = require("./modules/performance.js");
18
18
  const scroll_js_1 = require("./modules/scroll.js");
19
19
  const viewport_js_1 = require("./modules/viewport.js");
20
- const longtasks_js_1 = require("./modules/longtasks.js");
21
20
  const cssrules_js_1 = require("./modules/cssrules.js");
22
21
  const utils_js_1 = require("./utils.js");
23
22
  const DOCS_SETUP = '/installation/setup-or';
@@ -104,7 +103,6 @@ class API {
104
103
  (0, timing_js_1.default)(app, options);
105
104
  (0, performance_js_1.default)(app, options);
106
105
  (0, scroll_js_1.default)(app);
107
- (0, longtasks_js_1.default)(app);
108
106
  window.__OPENREPLAY__ = this;
109
107
  if (options.autoResetOnWindowOpen) {
110
108
  const wOpen = window.open;
@@ -129,7 +127,7 @@ class API {
129
127
  // no-cors issue only with text/plain or not-set Content-Type
130
128
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
131
129
  req.send(JSON.stringify({
132
- trackerVersion: '3.5.2',
130
+ trackerVersion: '3.5.3',
133
131
  projectKey: options.projectKey,
134
132
  doNotTrack,
135
133
  // TODO: add precise reason (an exact API missing)
@@ -180,7 +178,7 @@ class API {
180
178
  }
181
179
  setUserID(id) {
182
180
  if (typeof id === 'string' && this.app !== null) {
183
- this.app.send(new index_js_3.UserID(id));
181
+ this.app.session.setUserID(id);
184
182
  }
185
183
  }
186
184
  userID(id) {
@@ -200,7 +198,7 @@ class API {
200
198
  if (typeof key === 'string' &&
201
199
  typeof value === 'string' &&
202
200
  this.app !== null) {
203
- this.app.send(new index_js_3.Metadata(key, value));
201
+ this.app.session.setMetadata(key, value);
204
202
  }
205
203
  }
206
204
  metadata(key, value) {
@@ -3,6 +3,7 @@ import Nodes from "./nodes.js";
3
3
  import Sanitizer from "./sanitizer.js";
4
4
  import Ticker from "./ticker.js";
5
5
  import Logger from "./logger.js";
6
+ import Session from "./session.js";
6
7
  import type { Options as ObserverOptions } from "./observer/top_observer.js";
7
8
  import type { Options as SanitizerOptions } from "./sanitizer.js";
8
9
  import type { Options as LoggerOptions } from "./logger.js";
@@ -44,6 +45,7 @@ export default class App {
44
45
  readonly sanitizer: Sanitizer;
45
46
  readonly debug: Logger;
46
47
  readonly notify: Logger;
48
+ readonly session: Session;
47
49
  private readonly messages;
48
50
  private readonly observer;
49
51
  private readonly startCallbacks;
@@ -51,9 +53,6 @@ export default class App {
51
53
  private readonly commitCallbacks;
52
54
  private readonly options;
53
55
  private readonly revID;
54
- private _sessionID;
55
- private _userID;
56
- private _metadata;
57
56
  private activityState;
58
57
  private version;
59
58
  private readonly worker?;
@@ -62,8 +61,8 @@ export default class App {
62
61
  private readonly preStartMessages;
63
62
  send(message: Message, urgent?: boolean): void;
64
63
  private commit;
65
- attachCommitCallback(cb: CommitCallback): void;
66
64
  safe<T extends (...args: any[]) => void>(fn: T): T;
65
+ attachCommitCallback(cb: CommitCallback): void;
67
66
  attachStartCallback(cb: Callback): void;
68
67
  attachStopCallback(cb: Callback): void;
69
68
  attachEventListener(target: EventTarget, type: string, listener: EventListener, useSafe?: boolean, useCapture?: boolean): void;
@@ -75,10 +74,10 @@ export default class App {
75
74
  revID: string;
76
75
  timestamp: number;
77
76
  trackerVersion: string;
78
- userID: string | null;
79
77
  isSnippet: boolean;
80
78
  sessionID: string | null;
81
79
  metadata: Record<string, string>;
80
+ userID: string | null;
82
81
  };
83
82
  getSessionToken(): string | undefined;
84
83
  getSessionID(): string | undefined;
package/lib/app/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { timestamp } from "../utils.js";
2
- import { Timestamp, Metadata } from "../messages/index.js";
2
+ import { Timestamp } 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
7
  import Logger, { LogLevel } from "./logger.js";
8
+ import Session from "./session.js";
8
9
  import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
9
10
  var ActivityState;
10
11
  (function (ActivityState) {
@@ -24,11 +25,8 @@ export default class App {
24
25
  this.startCallbacks = [];
25
26
  this.stopCallbacks = [];
26
27
  this.commitCallbacks = [];
27
- this._sessionID = null;
28
- this._userID = null;
29
- this._metadata = {};
30
28
  this.activityState = ActivityState.NotActive;
31
- this.version = '3.5.2'; // TODO: version compatability check inside each plugin.
29
+ this.version = '3.5.3'; // TODO: version compatability check inside each plugin.
32
30
  this.preStartMessages = [];
33
31
  this.projectKey = projectKey;
34
32
  this.options = Object.assign({
@@ -55,25 +53,20 @@ export default class App {
55
53
  this.ticker.attach(() => this.commit());
56
54
  this.debug = new Logger(this.options.__debug__);
57
55
  this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
56
+ this.session = new Session(this);
58
57
  try {
59
58
  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()};
60
59
  `], { type: 'text/javascript' })));
61
60
  this.worker.onerror = e => {
62
61
  this._debug("webworker_error", e);
63
62
  };
64
- let lastTs = timestamp();
65
- let fileno = 0;
66
63
  this.worker.onmessage = ({ data }) => {
67
64
  if (data === null) {
68
65
  this.stop();
69
66
  }
70
67
  else if (data === "restart") {
71
68
  this.stop();
72
- this.start({
73
- forceNew: true,
74
- userID: this._userID || undefined,
75
- metadata: this._metadata || undefined,
76
- });
69
+ this.start({ forceNew: true });
77
70
  }
78
71
  };
79
72
  const alertWorker = () => {
@@ -127,9 +120,6 @@ export default class App {
127
120
  this.messages.length = 0;
128
121
  }
129
122
  }
130
- attachCommitCallback(cb) {
131
- this.commitCallbacks.push(cb);
132
- }
133
123
  safe(fn) {
134
124
  const app = this;
135
125
  return function (...args) {
@@ -145,6 +135,9 @@ export default class App {
145
135
  }
146
136
  }; // TODO: correct typing
147
137
  }
138
+ attachCommitCallback(cb) {
139
+ this.commitCallbacks.push(cb);
140
+ }
148
141
  attachStartCallback(cb) {
149
142
  this.startCallbacks.push(cb);
150
143
  }
@@ -175,12 +168,11 @@ export default class App {
175
168
  revID: this.revID,
176
169
  timestamp: timestamp(),
177
170
  trackerVersion: this.version,
178
- userID: this._userID,
179
171
  isSnippet: this.options.__is_snippet,
180
172
  };
181
173
  }
182
174
  getSessionInfo() {
183
- return Object.assign({ sessionID: this._sessionID, metadata: this._metadata }, this.getStartInfo());
175
+ return Object.assign(Object.assign({}, this.session.getInfo()), this.getStartInfo());
184
176
  }
185
177
  getSessionToken() {
186
178
  const token = sessionStorage.getItem(this.options.session_token_key);
@@ -189,7 +181,7 @@ export default class App {
189
181
  }
190
182
  }
191
183
  getSessionID() {
192
- return this._sessionID || undefined;
184
+ return this.session.getInfo().sessionID || undefined;
193
185
  }
194
186
  getHost() {
195
187
  return new URL(this.options.ingestPoint).hostname;
@@ -246,8 +238,6 @@ export default class App {
246
238
  pageNo++;
247
239
  }
248
240
  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
241
  const startInfo = this.getStartInfo();
252
242
  const messageData = {
253
243
  ingestPoint: this.options.ingestPoint,
@@ -264,7 +254,7 @@ export default class App {
264
254
  headers: {
265
255
  'Content-Type': 'application/json',
266
256
  },
267
- body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { token: sessionStorage.getItem(this.options.session_token_key), deviceMemory,
257
+ body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID: startOpts.userID || this.session.getInfo().userID, token: sessionStorage.getItem(this.options.session_token_key), deviceMemory,
268
258
  jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
269
259
  })
270
260
  .then(r => {
@@ -289,15 +279,12 @@ export default class App {
289
279
  }
290
280
  sessionStorage.setItem(this.options.session_token_key, token);
291
281
  localStorage.setItem(this.options.local_uuid_key, userUUID);
292
- if (typeof sessionID === 'string') {
293
- this._sessionID = sessionID;
294
- }
282
+ this.session.update(Object.assign({ sessionID }, startOpts));
295
283
  this.activityState = ActivityState.Active;
296
284
  this.worker.postMessage({ token, beaconSizeLimit });
297
285
  this.startCallbacks.forEach((cb) => cb());
298
286
  this.observer.observe();
299
287
  this.ticker.start();
300
- Object.entries(this._metadata).forEach(([key, value]) => this.send(new Metadata(key, value)));
301
288
  this.notify.log("OpenReplay tracking started.");
302
289
  // TODO: get rid of onStart
303
290
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
@@ -1,8 +1,8 @@
1
1
  export declare const LogLevel: {
2
- readonly Verbose: 4;
3
- readonly Errors: 4;
2
+ readonly Verbose: 5;
3
+ readonly Log: 4;
4
4
  readonly Warnings: 3;
5
- readonly Log: 2;
5
+ readonly Errors: 2;
6
6
  readonly Silent: 0;
7
7
  };
8
8
  declare type LogLevel = typeof LogLevel[keyof typeof LogLevel];
@@ -18,7 +18,6 @@ interface _Options {
18
18
  export declare type Options = true | _Options | LogLevel;
19
19
  export default class Logger {
20
20
  private readonly options;
21
- private readonly opts;
22
21
  constructor(options?: Options);
23
22
  log(...args: any): void;
24
23
  warn(...args: any): void;
package/lib/app/logger.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export const LogLevel = {
2
- Verbose: 4,
3
- Errors: 4,
2
+ Verbose: 5,
3
+ Log: 4,
4
4
  Warnings: 3,
5
- Log: 2,
5
+ Errors: 2,
6
6
  Silent: 0,
7
7
  };
8
8
  function IsCustomLevel(l) {
@@ -10,29 +10,28 @@ function IsCustomLevel(l) {
10
10
  }
11
11
  export default class Logger {
12
12
  constructor(options = LogLevel.Silent) {
13
- this.options = options;
14
- this.opts = options === true
13
+ this.options = options === true
15
14
  ? { level: LogLevel.Verbose }
16
15
  : typeof options === "number" ? { level: options } : options;
17
16
  }
18
17
  log(...args) {
19
- if (IsCustomLevel(this.opts.level)
20
- ? this.opts.level.log
21
- : this.opts.level >= LogLevel.Log) {
18
+ if (IsCustomLevel(this.options.level)
19
+ ? this.options.level.log
20
+ : this.options.level >= LogLevel.Log) {
22
21
  console.log(...args);
23
22
  }
24
23
  }
25
24
  warn(...args) {
26
- if (IsCustomLevel(this.opts.level)
27
- ? this.opts.level.warn
28
- : this.opts.level >= LogLevel.Warnings) {
25
+ if (IsCustomLevel(this.options.level)
26
+ ? this.options.level.warn
27
+ : this.options.level >= LogLevel.Warnings) {
29
28
  console.warn(...args);
30
29
  }
31
30
  }
32
31
  error(...args) {
33
- if (IsCustomLevel(this.opts.level)
34
- ? this.opts.level.error
35
- : this.opts.level >= LogLevel.Errors) {
32
+ if (IsCustomLevel(this.options.level)
33
+ ? this.options.level.error
34
+ : this.options.level >= LogLevel.Errors) {
36
35
  console.error(...args);
37
36
  }
38
37
  }
@@ -0,0 +1,25 @@
1
+ import App from "./index.js";
2
+ interface SessionInfo {
3
+ sessionID: string | null;
4
+ metadata: Record<string, string>;
5
+ userID: string | null;
6
+ }
7
+ declare type OnUpdateCallback = (i: Partial<SessionInfo>) => void;
8
+ export default class Session {
9
+ private app;
10
+ private metadata;
11
+ private userID;
12
+ private sessionID;
13
+ private activityState;
14
+ private callbacks;
15
+ constructor(app: App);
16
+ attachUpdateCallback(cb: OnUpdateCallback): void;
17
+ private handleUpdate;
18
+ update({ userID, metadata, sessionID }: Partial<SessionInfo>): void;
19
+ private _setMetadata;
20
+ private _setUserID;
21
+ setMetadata(key: string, value: string): void;
22
+ setUserID(userID: string): void;
23
+ getInfo(): SessionInfo;
24
+ }
25
+ export {};
@@ -0,0 +1,65 @@
1
+ import { UserID, Metadata } from "../messages/index.js";
2
+ var ActivityState;
3
+ (function (ActivityState) {
4
+ ActivityState[ActivityState["NotActive"] = 0] = "NotActive";
5
+ ActivityState[ActivityState["Starting"] = 1] = "Starting";
6
+ ActivityState[ActivityState["Active"] = 2] = "Active";
7
+ })(ActivityState || (ActivityState = {}));
8
+ export default class Session {
9
+ constructor(app) {
10
+ this.app = app;
11
+ this.metadata = {};
12
+ this.userID = null;
13
+ this.sessionID = null;
14
+ this.activityState = ActivityState.NotActive;
15
+ this.callbacks = [];
16
+ }
17
+ attachUpdateCallback(cb) {
18
+ this.callbacks.push(cb);
19
+ }
20
+ handleUpdate() {
21
+ const sessInfo = this.getInfo();
22
+ if (sessInfo.userID == null) {
23
+ delete sessInfo.userID;
24
+ }
25
+ if (sessInfo.sessionID == null) {
26
+ delete sessInfo.sessionID;
27
+ }
28
+ this.callbacks.forEach(cb => cb(sessInfo));
29
+ }
30
+ update({ userID, metadata, sessionID }) {
31
+ if (userID != null) { // TODO clear nullable/undefinable types
32
+ this._setUserID(userID);
33
+ }
34
+ if (metadata !== undefined) {
35
+ Object.entries(metadata).forEach(kv => this._setMetadata(...kv));
36
+ }
37
+ if (sessionID !== undefined) {
38
+ this.sessionID = sessionID;
39
+ }
40
+ this.handleUpdate();
41
+ }
42
+ _setMetadata(key, value) {
43
+ this.app.send(new Metadata(key, value));
44
+ this.metadata[key] = value;
45
+ }
46
+ _setUserID(userID) {
47
+ this.app.send(new UserID(userID));
48
+ this.userID = userID;
49
+ }
50
+ setMetadata(key, value) {
51
+ this._setMetadata(key, value);
52
+ this.handleUpdate();
53
+ }
54
+ setUserID(userID) {
55
+ this._setUserID(userID);
56
+ this.handleUpdate();
57
+ }
58
+ getInfo() {
59
+ return {
60
+ sessionID: this.sessionID,
61
+ metadata: this.metadata,
62
+ userID: this.userID,
63
+ };
64
+ }
65
+ }
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import App, { DEFAULT_INGEST_POINT } from "./app/index.js";
2
2
  export { default as App } from './app/index.js';
3
- import { UserID, UserAnonymousID, Metadata, RawCustomEvent, CustomIssue } from "./messages/index.js";
3
+ import { UserAnonymousID, RawCustomEvent, CustomIssue } from "./messages/index.js";
4
4
  import * as _Messages from "./messages/index.js";
5
5
  export const Messages = _Messages;
6
6
  import Connection from "./modules/connection.js";
@@ -13,7 +13,6 @@ import Timing from "./modules/timing.js";
13
13
  import Performance from "./modules/performance.js";
14
14
  import Scroll from "./modules/scroll.js";
15
15
  import Viewport from "./modules/viewport.js";
16
- import Longtasks from "./modules/longtasks.js";
17
16
  import CSSRules from "./modules/cssrules.js";
18
17
  import { IN_BROWSER, deprecationWarn, DOCS_HOST } from "./utils.js";
19
18
  const DOCS_SETUP = '/installation/setup-or';
@@ -100,7 +99,6 @@ export default class API {
100
99
  Timing(app, options);
101
100
  Performance(app, options);
102
101
  Scroll(app);
103
- Longtasks(app);
104
102
  window.__OPENREPLAY__ = this;
105
103
  if (options.autoResetOnWindowOpen) {
106
104
  const wOpen = window.open;
@@ -125,7 +123,7 @@ export default class API {
125
123
  // no-cors issue only with text/plain or not-set Content-Type
126
124
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
127
125
  req.send(JSON.stringify({
128
- trackerVersion: '3.5.2',
126
+ trackerVersion: '3.5.3',
129
127
  projectKey: options.projectKey,
130
128
  doNotTrack,
131
129
  // TODO: add precise reason (an exact API missing)
@@ -176,7 +174,7 @@ export default class API {
176
174
  }
177
175
  setUserID(id) {
178
176
  if (typeof id === 'string' && this.app !== null) {
179
- this.app.send(new UserID(id));
177
+ this.app.session.setUserID(id);
180
178
  }
181
179
  }
182
180
  userID(id) {
@@ -196,7 +194,7 @@ export default class API {
196
194
  if (typeof key === 'string' &&
197
195
  typeof value === 'string' &&
198
196
  this.app !== null) {
199
- this.app.send(new Metadata(key, value));
197
+ this.app.session.setMetadata(key, value);
200
198
  }
201
199
  }
202
200
  metadata(key, value) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openreplay/tracker",
3
3
  "description": "The OpenReplay tracker main package",
4
- "version": "3.5.2",
4
+ "version": "3.5.3",
5
5
  "keywords": [
6
6
  "logging",
7
7
  "replay"