@openreplay/tracker 3.6.2 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.eslintignore +8 -0
  2. package/.prettierignore +1 -0
  3. package/LICENSE +1 -1
  4. package/cjs/app/guards.d.ts +2 -1
  5. package/cjs/app/guards.js +6 -3
  6. package/cjs/app/index.d.ts +28 -23
  7. package/cjs/app/index.js +107 -86
  8. package/cjs/app/logger.js +6 -3
  9. package/cjs/app/messages.d.ts +52 -0
  10. package/cjs/app/messages.gen.d.ts +58 -0
  11. package/cjs/app/messages.gen.js +501 -0
  12. package/cjs/app/messages.js +234 -0
  13. package/cjs/app/nodes.d.ts +1 -1
  14. package/cjs/app/nodes.js +2 -0
  15. package/cjs/app/observer/iframe_observer.d.ts +1 -1
  16. package/cjs/app/observer/iframe_observer.js +3 -3
  17. package/cjs/app/observer/observer.d.ts +2 -3
  18. package/cjs/app/observer/observer.js +50 -52
  19. package/cjs/app/observer/shadow_root_observer.d.ts +1 -1
  20. package/cjs/app/observer/shadow_root_observer.js +3 -3
  21. package/cjs/app/observer/top_observer.d.ts +13 -2
  22. package/cjs/app/observer/top_observer.js +58 -23
  23. package/cjs/app/sanitizer.d.ts +1 -1
  24. package/cjs/app/sanitizer.js +5 -5
  25. package/cjs/app/session.d.ts +20 -2
  26. package/cjs/app/session.js +65 -6
  27. package/cjs/app/ticker.d.ts +1 -1
  28. package/cjs/common/{webworker.d.ts → interaction.d.ts} +5 -5
  29. package/cjs/common/{types.js → interaction.js} +0 -0
  30. package/cjs/common/messages.gen.d.ts +388 -0
  31. package/cjs/common/{webworker.js → messages.gen.js} +1 -0
  32. package/cjs/index.d.ts +10 -9
  33. package/cjs/index.js +47 -36
  34. package/cjs/modules/adoptedStyleSheets.d.ts +2 -0
  35. package/cjs/modules/adoptedStyleSheets.js +127 -0
  36. package/cjs/modules/connection.d.ts +1 -1
  37. package/cjs/modules/connection.js +2 -2
  38. package/cjs/modules/console.d.ts +1 -1
  39. package/cjs/modules/console.js +7 -21
  40. package/cjs/modules/cssrules.d.ts +1 -1
  41. package/cjs/modules/cssrules.js +18 -14
  42. package/cjs/modules/exception.d.ts +3 -3
  43. package/cjs/modules/exception.js +23 -18
  44. package/cjs/modules/img.d.ts +1 -1
  45. package/cjs/modules/img.js +39 -26
  46. package/cjs/modules/input.d.ts +1 -1
  47. package/cjs/modules/input.js +21 -21
  48. package/cjs/modules/mouse.d.ts +1 -1
  49. package/cjs/modules/mouse.js +50 -43
  50. package/cjs/modules/performance.d.ts +1 -1
  51. package/cjs/modules/performance.js +2 -2
  52. package/cjs/modules/scroll.d.ts +1 -1
  53. package/cjs/modules/scroll.js +16 -7
  54. package/cjs/modules/timing.d.ts +1 -1
  55. package/cjs/modules/timing.js +14 -26
  56. package/cjs/modules/viewport.d.ts +1 -1
  57. package/cjs/modules/viewport.js +4 -4
  58. package/cjs/utils.js +7 -7
  59. package/cjs/vendors/finder/finder.js +53 -48
  60. package/lib/app/guards.d.ts +2 -1
  61. package/lib/app/guards.js +4 -2
  62. package/lib/app/index.d.ts +28 -23
  63. package/lib/app/index.js +115 -94
  64. package/lib/app/logger.js +6 -3
  65. package/lib/app/messages.d.ts +52 -0
  66. package/lib/app/messages.gen.d.ts +58 -0
  67. package/lib/app/messages.gen.js +441 -0
  68. package/lib/app/messages.js +181 -0
  69. package/lib/app/nodes.d.ts +1 -1
  70. package/lib/app/nodes.js +2 -0
  71. package/lib/app/observer/iframe_observer.d.ts +1 -1
  72. package/lib/app/observer/iframe_observer.js +3 -3
  73. package/lib/app/observer/observer.d.ts +2 -3
  74. package/lib/app/observer/observer.js +51 -53
  75. package/lib/app/observer/shadow_root_observer.d.ts +1 -1
  76. package/lib/app/observer/shadow_root_observer.js +3 -3
  77. package/lib/app/observer/top_observer.d.ts +13 -2
  78. package/lib/app/observer/top_observer.js +62 -27
  79. package/lib/app/sanitizer.d.ts +1 -1
  80. package/lib/app/sanitizer.js +7 -7
  81. package/lib/app/session.d.ts +20 -2
  82. package/lib/app/session.js +65 -6
  83. package/lib/app/ticker.d.ts +1 -1
  84. package/lib/common/{webworker.d.ts → interaction.d.ts} +5 -5
  85. package/lib/common/{types.js → interaction.js} +0 -0
  86. package/lib/common/messages.gen.d.ts +388 -0
  87. package/lib/common/messages.gen.js +2 -0
  88. package/lib/common/tsconfig.tsbuildinfo +1 -1
  89. package/lib/index.d.ts +10 -9
  90. package/lib/index.js +60 -49
  91. package/lib/modules/adoptedStyleSheets.d.ts +2 -0
  92. package/lib/modules/adoptedStyleSheets.js +124 -0
  93. package/lib/modules/connection.d.ts +1 -1
  94. package/lib/modules/connection.js +2 -2
  95. package/lib/modules/console.d.ts +1 -1
  96. package/lib/modules/console.js +8 -22
  97. package/lib/modules/cssrules.d.ts +1 -1
  98. package/lib/modules/cssrules.js +19 -15
  99. package/lib/modules/exception.d.ts +3 -3
  100. package/lib/modules/exception.js +23 -18
  101. package/lib/modules/img.d.ts +1 -1
  102. package/lib/modules/img.js +41 -28
  103. package/lib/modules/input.d.ts +1 -1
  104. package/lib/modules/input.js +23 -23
  105. package/lib/modules/mouse.d.ts +1 -1
  106. package/lib/modules/mouse.js +53 -46
  107. package/lib/modules/performance.d.ts +1 -1
  108. package/lib/modules/performance.js +3 -3
  109. package/lib/modules/scroll.d.ts +1 -1
  110. package/lib/modules/scroll.js +17 -8
  111. package/lib/modules/timing.d.ts +1 -1
  112. package/lib/modules/timing.js +16 -28
  113. package/lib/modules/viewport.d.ts +1 -1
  114. package/lib/modules/viewport.js +4 -4
  115. package/lib/utils.js +7 -7
  116. package/lib/vendors/finder/finder.js +53 -48
  117. package/package.json +27 -10
  118. package/cjs/common/messages.d.ts +0 -444
  119. package/cjs/common/messages.js +0 -794
  120. package/cjs/common/types.d.ts +0 -9
  121. package/cjs/modules/longtasks.d.ts +0 -2
  122. package/cjs/modules/longtasks.js +0 -26
  123. package/lib/common/messages.d.ts +0 -444
  124. package/lib/common/messages.js +0 -790
  125. package/lib/common/types.d.ts +0 -9
  126. package/lib/common/webworker.js +0 -1
  127. package/lib/modules/longtasks.d.ts +0 -2
  128. package/lib/modules/longtasks.js +0 -23
package/lib/app/index.js CHANGED
@@ -1,14 +1,14 @@
1
- import { Timestamp, Metadata, UserID } from "../common/messages.js";
2
- import { timestamp } from "../utils.js";
3
- import Nodes from "./nodes.js";
4
- import Observer from "./observer/top_observer.js";
5
- import Sanitizer from "./sanitizer.js";
6
- import Ticker from "./ticker.js";
7
- import Logger, { LogLevel } from "./logger.js";
8
- import Session from "./session.js";
9
- import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
10
- const CANCELED = "canceled";
11
- const START_ERROR = ":(";
1
+ import { Timestamp, Metadata, UserID } from './messages.gen.js';
2
+ import { timestamp as now } from '../utils.js';
3
+ import Nodes from './nodes.js';
4
+ import Observer from './observer/top_observer.js';
5
+ import Sanitizer from './sanitizer.js';
6
+ import Ticker from './ticker.js';
7
+ import Logger, { LogLevel } from './logger.js';
8
+ import Session from './session.js';
9
+ import { deviceMemory, jsHeapSizeLimit } from '../modules/performance.js';
10
+ const CANCELED = 'canceled';
11
+ const START_ERROR = ':(';
12
12
  const UnsuccessfulStart = (reason) => ({ reason, success: false });
13
13
  const SuccessfulStart = (body) => (Object.assign(Object.assign({}, body), { success: true }));
14
14
  var ActivityState;
@@ -29,7 +29,7 @@ export default class App {
29
29
  this.stopCallbacks = [];
30
30
  this.commitCallbacks = [];
31
31
  this.activityState = ActivityState.NotActive;
32
- this.version = '3.6.2'; // TODO: version compatability check inside each plugin.
32
+ this.version = '4.0.1'; // TODO: version compatability check inside each plugin.
33
33
  this.projectKey = projectKey;
34
34
  this.options = Object.assign({
35
35
  revID: '',
@@ -43,8 +43,8 @@ export default class App {
43
43
  verbose: false,
44
44
  __is_snippet: false,
45
45
  __debug_report_edp: null,
46
- localStorage: window.localStorage,
47
- sessionStorage: window.sessionStorage,
46
+ localStorage: window === null || window === void 0 ? void 0 : window.localStorage,
47
+ sessionStorage: window === null || window === void 0 ? void 0 : window.sessionStorage,
48
48
  }, options);
49
49
  this.revID = this.options.revID;
50
50
  this.sanitizer = new Sanitizer(this, options);
@@ -54,32 +54,33 @@ export default class App {
54
54
  this.ticker.attach(() => this.commit());
55
55
  this.debug = new Logger(this.options.__debug__);
56
56
  this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
57
- this.session = new Session();
57
+ this.localStorage = this.options.localStorage || window.localStorage;
58
+ this.sessionStorage = this.options.sessionStorage || window.sessionStorage;
59
+ this.session = new Session(this, this.options);
58
60
  this.session.attachUpdateCallback(({ userID, metadata }) => {
59
- if (userID != null) { // TODO: nullable userID
60
- this.send(new UserID(userID));
61
+ if (userID != null) {
62
+ // TODO: nullable userID
63
+ this.send(UserID(userID));
61
64
  }
62
65
  if (metadata != null) {
63
- Object.entries(metadata).forEach(([key, value]) => this.send(new Metadata(key, value)));
66
+ Object.entries(metadata).forEach(([key, value]) => this.send(Metadata(key, value)));
64
67
  }
65
68
  });
66
- this.localStorage = this.options.localStorage;
67
- this.sessionStorage = this.options.sessionStorage;
69
+ // @depricated (use sessionHash on start instead)
68
70
  if (sessionToken != null) {
69
- this.sessionStorage.setItem(this.options.session_token_key, sessionToken);
71
+ this.session.applySessionHash(sessionToken);
70
72
  }
71
73
  try {
72
- this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function i(...i){return new t(...i)}return i.prototype=t.prototype,i}const i=new Map;const s=t(class{constructor(t,i,s){this.pageNo=t,this.firstIndex=i,this.timestamp=s,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});i.set(80,s);const e=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});i.set(0,e);const n=t(class{constructor(t,i,s){this.url=t,this.referrer=i,this.navigationStart=s,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});i.set(4,n);const r=t(class{constructor(t,i){this.width=t,this.height=i,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});i.set(5,r);const h=t(class{constructor(t,i){this.x=t,this.y=i,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});i.set(6,h);const o=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});i.set(7,o);const c=t(class{constructor(t,i,s,e,n){this.id=t,this.parentID=i,this.index=s,this.tag=e,this.svg=n,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)}});i.set(8,c);const a=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(9,a);const u=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(10,u);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});i.set(11,d);const l=t(class{constructor(t,i,s){this.id=t,this.name=i,this.value=s,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});i.set(12,l);const p=t(class{constructor(t,i){this.id=t,this.name=i,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});i.set(13,p);const g=t(class{constructor(t,i){this.id=t,this.data=i,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});i.set(14,g);const m=t(class{constructor(t,i,s){this.id=t,this.x=i,this.y=s,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});i.set(16,m);const f=t(class{constructor(t,i){this.id=t,this.label=i,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});i.set(17,f);const y=t(class{constructor(t,i,s){this.id=t,this.value=i,this.mask=s,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});i.set(18,y);const _=t(class{constructor(t,i){this.id=t,this.checked=i,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});i.set(19,_);const v=t(class{constructor(t,i){this.x=t,this.y=i,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});i.set(20,v);const S=t(class{constructor(t,i){this.level=t,this.value=i,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});i.set(22,S);const b=t(class{constructor(t,i,s,e,n,r,h,o,c){this.requestStart=t,this.responseStart=i,this.responseEnd=s,this.domContentLoadedEventStart=e,this.domContentLoadedEventEnd=n,this.loadEventStart=r,this.loadEventEnd=h,this.firstPaint=o,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)}});i.set(23,b);const w=t(class{constructor(t,i,s){this.speedIndex=t,this.visuallyComplete=i,this.timeToInteractive=s,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});i.set(24,w);const E=t(class{constructor(t,i,s){this.name=t,this.message=i,this.payload=s,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});i.set(25,E);const x=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});i.set(27,x);const T=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});i.set(28,T);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});i.set(29,z);const k=t(class{constructor(t,i){this.key=t,this.value=i,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});i.set(30,k);const A=t(class{constructor(t,i,s){this.id=t,this.rule=i,this.index=s,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});i.set(37,A);const I=t(class{constructor(t,i){this.id=t,this.index=i,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});i.set(38,I);const L=t(class{constructor(t,i,s,e,n,r,h){this.method=t,this.url=i,this.request=s,this.response=e,this.status=n,this.timestamp=r,this.duration=h,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)}});i.set(39,L);const C=t(class{constructor(t,i,s,e){this.name=t,this.duration=i,this.args=s,this.result=e,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)}});i.set(40,C);const M=t(class{constructor(t,i){this.key=t,this.value=i,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});i.set(41,M);const N=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});i.set(42,N);const B=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(44,B);const U=t(class{constructor(t,i){this.mutation=t,this.state=i,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});i.set(45,U);const R=t(class{constructor(t,i){this.type=t,this.payload=i,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});i.set(46,R);const O=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(47,O);const P=t(class{constructor(t,i,s,e){this.operationKind=t,this.operationName=i,this.variables=s,this.response=e,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)}});i.set(48,P);const q=t(class{constructor(t,i,s,e){this.frames=t,this.ticks=i,this.totalJSHeapSize=s,this.usedJSHeapSize=e,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)}});i.set(49,q);const D=t(class{constructor(t,i,s,e,n,r,h,o){this.timestamp=t,this.duration=i,this.ttfb=s,this.headerSize=e,this.encodedBodySize=n,this.decodedBodySize=r,this.url=h,this.initiator=o,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)}});i.set(53,D);const W=t(class{constructor(t,i){this.downlink=t,this.type=i,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});i.set(54,W);const H=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});i.set(55,H);const J=t(class{constructor(t,i,s,e,n,r,h){this.timestamp=t,this.duration=i,this.context=s,this.containerType=e,this.containerSrc=n,this.containerId=r,this.containerName=h,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)}});i.set(59,J);const F=t(class{constructor(t,i,s,e){this.id=t,this.name=i,this.value=s,this.baseURL=e,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)}});i.set(60,F);const X=t(class{constructor(t,i,s){this.id=t,this.data=i,this.baseURL=s,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});i.set(61,X);const G=t(class{constructor(t,i){this.type=t,this.value=i,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});i.set(63,G);const K=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});i.set(64,K);const j=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});i.set(65,j);const Q=t(class{constructor(t,i,s,e){this.id=t,this.rule=i,this.index=s,this.baseURL=e,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)}});i.set(67,Q);const V=t(class{constructor(t,i,s,e){this.id=t,this.hesitationTime=i,this.label=s,this.selector=e,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)}});i.set(69,V);const Y=t(class{constructor(t,i){this.frameID=t,this.id=i,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});i.set(70,Y);class Z{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const tt="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(var n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(!((r=t.charCodeAt(h))>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(h+=1,(n=1024*(n-55296)+r-56320+65536)>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class it{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 i=tt.encode(t),s=i.byteLength;return!(!this.uint(s)||this.offset+s>this.size)&&(this.data.set(i,this.offset),this.offset+=s,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class st{constructor(t,i,s){this.pageNo=t,this.timestamp=i,this.onBatch=s,this.nextIndex=0,this.beaconSize=2e5,this.writer=new it(this.beaconSize),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}prepare(){this.writer.isEmpty()&&new s(this.pageNo,this.nextIndex,this.timestamp).encode(this.writer)}write(t){const i=t.encode(this.writer);return i&&(this.isEmpty=!1,this.writer.checkpoint(),this.nextIndex++),i}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){for(t instanceof e&&(this.timestamp=t.timestamp);!this.write(t);){if(this.finaliseBatch(),this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message."),this.writer.reset(),this.prepare(),void(this.isEmpty=!0);this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.writer=new it(this.beaconSize),this.prepare(),this.isEmpty=!0}}finaliseBatch(){this.isEmpty||(this.onBatch(this.writer.flush()),this.prepare(),this.isEmpty=!0)}clean(){this.writer.reset()}}var et;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(et||(et={}));let nt=null,rt=null;function ht(){rt&&rt.finaliseBatch()}function ot(){et.Stopping,null!==at&&(clearInterval(at),at=null),rt&&(rt.clean(),rt=null),et.NotActive}et.NotActive;let ct,at=null;self.onmessage=({data:t})=>{if(null!=t){if("stop"===t)return ht(),void ot();if(Array.isArray(t)){if(!rt)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const s=rt;t.forEach(t=>{const e=new(i.get(t._id));Object.assign(e,t),e instanceof H&&(e.hidden?ct=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ct)),s.writeMessage(e)})}else{if("start"===t.type)return et.Starting,nt=new Z(t.ingestPoint,()=>{self.postMessage("restart")},()=>{nt&&(nt.clean(),nt=null),ot(),self.postMessage("failed")},t.connAttemptCount,t.connAttemptGap),rt=new st(t.pageNo,t.timestamp,t=>nt&&nt.push(t)),null===at&&(at=setInterval(ht,1e4)),et.Active;if("auth"===t.type){if(!nt)throw new Error("WebWorker: sender not initialised. Received auth.");if(!rt)throw new Error("WebWorker: writer not initialised. Received auth.");return nt.authorise(t.token),void(t.beaconSizeLimit&&rt.setBeaconSizeLimit(t.beaconSizeLimit))}}}else ht()};
73
- `], { type: 'text/javascript' })));
74
- this.worker.onerror = e => {
75
- this._debug("webworker_error", e);
74
+ this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==c&&(clearInterval(c),c=null),h&&(h.clean(),h=null),n.NotActive}n.NotActive;let o,c=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return u(),void a();if(Array.isArray(i)){if(!h)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const t=h;i.forEach(i=>{55===i[0]&&(i[1]?o=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(o)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{self.postMessage("restart")},()=>{r&&(r.clean(),r=null),a(),self.postMessage("failed")},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===c&&(c=setInterval(u,1e4)),n.Active;if("auth"===i.type){if(!r)throw new Error("WebWorker: sender not initialised. Received auth.");if(!h)throw new Error("WebWorker: writer not initialised. Received auth.");return r.authorise(i.token),void(i.beaconSizeLimit&&h.setBeaconSizeLimit(i.beaconSizeLimit))}}}else u()};'], { type: 'text/javascript' })));
75
+ this.worker.onerror = (e) => {
76
+ this._debug('webworker_error', e);
76
77
  };
77
78
  this.worker.onmessage = ({ data }) => {
78
- if (data === "failed") {
79
+ if (data === 'failed') {
79
80
  this.stop();
80
- this._debug("worker_failed", {}); // add context (from worker)
81
+ this._debug('worker_failed', {}); // add context (from worker)
81
82
  }
82
- else if (data === "restart") {
83
+ else if (data === 'restart') {
83
84
  this.stop();
84
85
  this.start({ forceNew: true });
85
86
  }
@@ -96,7 +97,7 @@ export default class App {
96
97
  this.attachEventListener(document, 'visibilitychange', alertWorker, false);
97
98
  }
98
99
  catch (e) {
99
- this._debug("worker_start", e);
100
+ this._debug('worker_start', e);
100
101
  }
101
102
  }
102
103
  _debug(context, e) {
@@ -106,20 +107,20 @@ export default class App {
106
107
  headers: { 'Content-Type': 'application/json' },
107
108
  body: JSON.stringify({
108
109
  context,
109
- error: `${e}`
110
- })
110
+ error: `${e}`,
111
+ }),
111
112
  });
112
113
  }
113
- this.debug.error("OpenReplay error: ", context, e);
114
+ this.debug.error('OpenReplay error: ', context, e);
114
115
  }
115
116
  send(message, urgent = false) {
116
117
  if (this.activityState === ActivityState.NotActive) {
117
118
  return;
118
119
  }
119
120
  this.messages.push(message);
120
- // TODO: commit on start if there were `urgent` sends;
121
+ // TODO: commit on start if there were `urgent` sends;
121
122
  // Clearify where urgent can be used for;
122
- // Clearify workflow for each type of message in case it was sent before start
123
+ // Clearify workflow for each type of message in case it was sent before start
123
124
  // (like Fetch before start; maybe add an option "preCapture: boolean" or sth alike)
124
125
  if (this.activityState === ActivityState.Active && urgent) {
125
126
  this.commit();
@@ -127,9 +128,9 @@ export default class App {
127
128
  }
128
129
  commit() {
129
130
  if (this.worker && this.messages.length) {
130
- this.messages.unshift(new Timestamp(timestamp()));
131
+ this.messages.unshift(Timestamp(now()));
131
132
  this.worker.postMessage(this.messages);
132
- this.commitCallbacks.forEach(cb => cb(this.messages));
133
+ this.commitCallbacks.forEach((cb) => cb(this.messages));
133
134
  this.messages.length = 0;
134
135
  }
135
136
  }
@@ -140,8 +141,8 @@ export default class App {
140
141
  fn.apply(this, args);
141
142
  }
142
143
  catch (e) {
143
- app._debug("safe_fn_call", e);
144
- // time: timestamp(),
144
+ app._debug('safe_fn_call', e);
145
+ // time: now(),
145
146
  // name: e.name,
146
147
  // message: e.message,
147
148
  // stack: e.stack
@@ -149,54 +150,72 @@ export default class App {
149
150
  }; // TODO: correct typing
150
151
  }
151
152
  attachCommitCallback(cb) {
153
+ // TODO!: what if start callback added when activityState === Active ?
154
+ // For example - attachEventListener() called during dynamic <iframe> appearance
152
155
  this.commitCallbacks.push(cb);
153
156
  }
154
- attachStartCallback(cb) {
157
+ attachStartCallback(cb, useSafe = false) {
158
+ if (useSafe) {
159
+ cb = this.safe(cb);
160
+ }
155
161
  this.startCallbacks.push(cb);
156
162
  }
157
- attachStopCallback(cb) {
163
+ attachStopCallback(cb, useSafe = false) {
164
+ if (useSafe) {
165
+ cb = this.safe(cb);
166
+ }
158
167
  this.stopCallbacks.push(cb);
159
168
  }
160
169
  attachEventListener(target, type, listener, useSafe = true, useCapture = true) {
161
170
  if (useSafe) {
162
171
  listener = this.safe(listener);
163
172
  }
164
- this.attachStartCallback(() => target.addEventListener(type, listener, useCapture));
165
- this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture));
173
+ this.attachStartCallback(() => target.addEventListener(type, listener, useCapture), useSafe);
174
+ this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture), useSafe);
166
175
  }
167
176
  // TODO: full correct semantic
168
177
  checkRequiredVersion(version) {
169
178
  const reqVer = version.split(/[.-]/);
170
179
  const ver = this.version.split(/[.-]/);
171
180
  for (let i = 0; i < 3; i++) {
172
- if (Number(ver[i]) < Number(reqVer[i]) || isNaN(Number(ver[i])) || isNaN(Number(reqVer[i]))) {
181
+ if (isNaN(Number(ver[i])) || isNaN(Number(reqVer[i]))) {
182
+ return false;
183
+ }
184
+ if (Number(ver[i]) > Number(reqVer[i])) {
185
+ return true;
186
+ }
187
+ if (Number(ver[i]) < Number(reqVer[i])) {
173
188
  return false;
174
189
  }
175
190
  }
176
191
  return true;
177
192
  }
178
- getStartInfo() {
193
+ getTrackerInfo() {
179
194
  return {
180
195
  userUUID: this.localStorage.getItem(this.options.local_uuid_key),
181
196
  projectKey: this.projectKey,
182
197
  revID: this.revID,
183
- timestamp: timestamp(),
184
198
  trackerVersion: this.version,
185
199
  isSnippet: this.options.__is_snippet,
186
200
  };
187
201
  }
188
202
  getSessionInfo() {
189
- return Object.assign(Object.assign({}, this.session.getInfo()), this.getStartInfo());
203
+ return Object.assign(Object.assign({}, this.session.getInfo()), this.getTrackerInfo());
190
204
  }
191
205
  getSessionToken() {
192
- const token = this.sessionStorage.getItem(this.options.session_token_key);
193
- if (token !== null) {
194
- return token;
195
- }
206
+ return this.session.getSessionToken();
196
207
  }
197
208
  getSessionID() {
198
209
  return this.session.getInfo().sessionID || undefined;
199
210
  }
211
+ getSessionURL() {
212
+ const { projectID, sessionID } = this.session.getInfo();
213
+ if (!projectID || !sessionID) {
214
+ this.debug.error('OpenReplay error: Unable to build session URL');
215
+ return undefined;
216
+ }
217
+ return this.options.ingestPoint.replace(/ingest$/, `${projectID}/session/${sessionID}`);
218
+ }
200
219
  getHost() {
201
220
  return new URL(this.options.ingestPoint).hostname;
202
221
  }
@@ -209,18 +228,19 @@ export default class App {
209
228
  return this.options.resourceBaseHref;
210
229
  }
211
230
  else if (typeof this.options.resourceBaseHref === 'object') {
212
- //switch between types
231
+ //TODO: switch between types
213
232
  }
214
233
  if (document.baseURI) {
215
234
  return document.baseURI;
216
235
  }
217
236
  // IE only
218
- return ((_b = (_a = document.head) === null || _a === void 0 ? void 0 : _a.getElementsByTagName("base")[0]) === null || _b === void 0 ? void 0 : _b.getAttribute("href")) || location.origin + location.pathname;
237
+ return (((_b = (_a = document.head) === null || _a === void 0 ? void 0 : _a.getElementsByTagName('base')[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('href')) ||
238
+ location.origin + location.pathname);
219
239
  }
220
240
  resolveResourceURL(resourceURL) {
221
241
  const base = new URL(this.getBaseHref());
222
- base.pathname += "/" + new URL(resourceURL).pathname;
223
- base.pathname.replace(/\/+/g, "/");
242
+ base.pathname += '/' + new URL(resourceURL).pathname;
243
+ base.pathname.replace(/\/+/g, '/');
224
244
  return base.toString();
225
245
  }
226
246
  isServiceURL(url) {
@@ -239,94 +259,98 @@ export default class App {
239
259
  }
240
260
  _start(startOpts) {
241
261
  if (!this.worker) {
242
- return Promise.resolve(UnsuccessfulStart("No worker found: perhaps, CSP is not set."));
262
+ return Promise.resolve(UnsuccessfulStart('No worker found: perhaps, CSP is not set.'));
243
263
  }
244
264
  if (this.activityState !== ActivityState.NotActive) {
245
- return Promise.resolve(UnsuccessfulStart("OpenReplay: trying to call `start()` on the instance that has been started already."));
265
+ return Promise.resolve(UnsuccessfulStart('OpenReplay: trying to call `start()` on the instance that has been started already.'));
246
266
  }
247
267
  this.activityState = ActivityState.Starting;
248
- let pageNo = 0;
249
- const pageNoStr = this.sessionStorage.getItem(this.options.session_pageno_key);
250
- if (pageNoStr != null) {
251
- pageNo = parseInt(pageNoStr);
252
- pageNo++;
268
+ if (startOpts.sessionHash) {
269
+ this.session.applySessionHash(startOpts.sessionHash);
253
270
  }
254
- this.sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
255
- const startInfo = this.getStartInfo();
271
+ const timestamp = now();
256
272
  const startWorkerMsg = {
257
- type: "start",
258
- pageNo,
273
+ type: 'start',
274
+ pageNo: this.session.incPageNo(),
259
275
  ingestPoint: this.options.ingestPoint,
260
- timestamp: startInfo.timestamp,
276
+ timestamp,
277
+ url: document.URL,
261
278
  connAttemptCount: this.options.connAttemptCount,
262
279
  connAttemptGap: this.options.connAttemptGap,
263
280
  };
264
281
  this.worker.postMessage(startWorkerMsg);
265
282
  this.session.update({
266
- // "updating" with old metadata in order to trigger session's UpdateCallbacks.
283
+ // TODO: transparent "session" module logic AND explicit internal api for plugins.
284
+ // "updating" with old metadata in order to trigger session's UpdateCallbacks.
267
285
  // (for the case of internal .start() calls, like on "restart" webworker signal or assistent connection in tracker-assist )
268
286
  metadata: startOpts.metadata || this.session.getInfo().metadata,
269
287
  userID: startOpts.userID,
270
288
  });
271
289
  const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
272
290
  this.sessionStorage.removeItem(this.options.session_reset_key);
273
- return window.fetch(this.options.ingestPoint + '/v1/web/start', {
291
+ return window
292
+ .fetch(this.options.ingestPoint + '/v1/web/start', {
274
293
  method: 'POST',
275
294
  headers: {
276
295
  'Content-Type': 'application/json',
277
296
  },
278
- body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID: this.session.getInfo().userID, token: this.sessionStorage.getItem(this.options.session_token_key), deviceMemory,
297
+ body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: this.session.getSessionToken(), deviceMemory,
279
298
  jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
280
299
  })
281
- .then(r => {
300
+ .then((r) => {
282
301
  if (r.status === 200) {
283
302
  return r.json();
284
303
  }
285
304
  else {
286
- return r.text().then(text => text === CANCELED
305
+ return r
306
+ .text()
307
+ .then((text) => text === CANCELED
287
308
  ? Promise.reject(CANCELED)
288
309
  : Promise.reject(`Server error: ${r.status}. ${text}`));
289
310
  }
290
311
  })
291
- .then(r => {
312
+ .then((r) => {
292
313
  if (!this.worker) {
293
- return Promise.reject("no worker found after start request (this might not happen)");
314
+ return Promise.reject('no worker found after start request (this might not happen)');
294
315
  }
295
- const { token, userUUID, sessionID, beaconSizeLimit } = r;
316
+ const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
317
+ } = r;
296
318
  if (typeof token !== 'string' ||
297
319
  typeof userUUID !== 'string' ||
320
+ //typeof startTimestamp !== 'number' ||
321
+ //typeof sessionID !== 'string' ||
298
322
  (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
299
323
  return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
300
324
  }
301
- this.sessionStorage.setItem(this.options.session_token_key, token);
325
+ this.session.setSessionToken(token);
302
326
  this.localStorage.setItem(this.options.local_uuid_key, userUUID);
303
- this.session.update({ sessionID }); // TODO: no no-explicit 'any'
327
+ this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
304
328
  const startWorkerMsg = {
305
- type: "auth",
329
+ type: 'auth',
306
330
  token,
307
- beaconSizeLimit
331
+ beaconSizeLimit,
308
332
  };
309
333
  this.worker.postMessage(startWorkerMsg);
310
- this.activityState = ActivityState.Active;
311
334
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
312
335
  this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
313
336
  this.observer.observe();
314
337
  this.ticker.start();
315
- this.notify.log("OpenReplay tracking started.");
338
+ this.activityState = ActivityState.Active;
339
+ this.notify.log('OpenReplay tracking started.');
316
340
  // get rid of onStart ?
317
341
  if (typeof this.options.onStart === 'function') {
318
342
  this.options.onStart(onStartInfo);
319
343
  }
320
344
  return SuccessfulStart(onStartInfo);
321
345
  })
322
- .catch(reason => {
323
- this.sessionStorage.removeItem(this.options.session_token_key);
346
+ .catch((reason) => {
324
347
  this.stop();
348
+ this.session.reset();
325
349
  if (reason === CANCELED) {
326
350
  return UnsuccessfulStart(CANCELED);
327
351
  }
328
- this.notify.log("OpenReplay was unable to start. ", reason);
329
- this._debug("session_start", reason);
352
+ this.notify.log('OpenReplay was unable to start. ', reason);
353
+ this._debug('session_start', reason);
330
354
  return UnsuccessfulStart(START_ERROR);
331
355
  });
332
356
  }
@@ -338,15 +362,15 @@ export default class App {
338
362
  return new Promise((resolve) => {
339
363
  const onVisibilityChange = () => {
340
364
  if (!document.hidden) {
341
- document.removeEventListener("visibilitychange", onVisibilityChange);
365
+ document.removeEventListener('visibilitychange', onVisibilityChange);
342
366
  resolve(this._start(options));
343
367
  }
344
368
  };
345
- document.addEventListener("visibilitychange", onVisibilityChange);
369
+ document.addEventListener('visibilitychange', onVisibilityChange);
346
370
  });
347
371
  }
348
372
  }
349
- stop(calledFromAPI = false, restarting = false) {
373
+ stop(stopWorker = true) {
350
374
  if (this.activityState !== ActivityState.NotActive) {
351
375
  try {
352
376
  this.sanitizer.clear();
@@ -354,12 +378,9 @@ export default class App {
354
378
  this.nodes.clear();
355
379
  this.ticker.stop();
356
380
  this.stopCallbacks.forEach((cb) => cb());
357
- if (calledFromAPI) {
358
- this.session.reset();
359
- }
360
- this.notify.log("OpenReplay tracking stopped.");
361
- if (this.worker && !restarting) {
362
- this.worker.postMessage("stop");
381
+ this.notify.log('OpenReplay tracking stopped.');
382
+ if (this.worker && stopWorker) {
383
+ this.worker.postMessage('stop');
363
384
  }
364
385
  }
365
386
  finally {
@@ -368,7 +389,7 @@ export default class App {
368
389
  }
369
390
  }
370
391
  restart() {
371
- this.stop(false, true);
392
+ this.stop(false);
372
393
  this.start({ forceNew: false });
373
394
  }
374
395
  }
package/lib/app/logger.js CHANGED
@@ -10,9 +10,12 @@ function IsCustomLevel(l) {
10
10
  }
11
11
  export default class Logger {
12
12
  constructor(options = LogLevel.Silent) {
13
- this.options = options === true
14
- ? { level: LogLevel.Verbose }
15
- : typeof options === "number" ? { level: options } : options;
13
+ this.options =
14
+ options === true
15
+ ? { level: LogLevel.Verbose }
16
+ : typeof options === 'number'
17
+ ? { level: options }
18
+ : options;
16
19
  }
17
20
  log(...args) {
18
21
  if (IsCustomLevel(this.options.level)
@@ -0,0 +1,52 @@
1
+ import * as Messages from '../common/messages.gen.js';
2
+ export { default } from '../common/messages.gen.js';
3
+ export declare function BatchMetadata(version: number, pageNo: number, firstIndex: number, timestamp: number, location: string): Messages.BatchMetadata;
4
+ export declare function PartitionedMessage(partNo: number, partTotal: number): Messages.PartitionedMessage;
5
+ export declare function Timestamp(timestamp: number): Messages.Timestamp;
6
+ export declare function SetPageLocation(url: string, referrer: string, navigationStart: number): Messages.SetPageLocation;
7
+ export declare function SetViewportSize(width: number, height: number): Messages.SetViewportSize;
8
+ export declare function SetViewportScroll(x: number, y: number): Messages.SetViewportScroll;
9
+ export declare function CreateDocument(): Messages.CreateDocument;
10
+ export declare function CreateElementNode(id: number, parentID: number, index: number, tag: string, svg: boolean): Messages.CreateElementNode;
11
+ export declare function CreateTextNode(id: number, parentID: number, index: number): Messages.CreateTextNode;
12
+ export declare function MoveNode(id: number, parentID: number, index: number): Messages.MoveNode;
13
+ export declare function RemoveNode(id: number): Messages.RemoveNode;
14
+ export declare function SetNodeAttribute(id: number, name: string, value: string): Messages.SetNodeAttribute;
15
+ export declare function RemoveNodeAttribute(id: number, name: string): Messages.RemoveNodeAttribute;
16
+ export declare function SetNodeData(id: number, data: string): Messages.SetNodeData;
17
+ export declare function SetNodeScroll(id: number, x: number, y: number): Messages.SetNodeScroll;
18
+ export declare function SetInputTarget(id: number, label: string): Messages.SetInputTarget;
19
+ export declare function SetInputValue(id: number, value: string, mask: number): Messages.SetInputValue;
20
+ export declare function SetInputChecked(id: number, checked: boolean): Messages.SetInputChecked;
21
+ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
+ export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
+ export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
24
+ export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
25
+ export declare function JSException(name: string, message: string, payload: string): Messages.JSException;
26
+ export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
+ export declare function UserID(id: string): Messages.UserID;
28
+ export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
29
+ export declare function Metadata(key: string, value: string): Messages.Metadata;
30
+ export declare function CSSInsertRule(id: number, rule: string, index: number): Messages.CSSInsertRule;
31
+ export declare function CSSDeleteRule(id: number, index: number): Messages.CSSDeleteRule;
32
+ export declare function Fetch(method: string, url: string, request: string, response: string, status: number, timestamp: number, duration: number): Messages.Fetch;
33
+ export declare function Profiler(name: string, duration: number, args: string, result: string): Messages.Profiler;
34
+ export declare function OTable(key: string, value: string): Messages.OTable;
35
+ export declare function StateAction(type: string): Messages.StateAction;
36
+ export declare function Redux(action: string, state: string, duration: number): Messages.Redux;
37
+ export declare function Vuex(mutation: string, state: string): Messages.Vuex;
38
+ export declare function MobX(type: string, payload: string): Messages.MobX;
39
+ export declare function NgRx(action: string, state: string, duration: number): Messages.NgRx;
40
+ export declare function GraphQL(operationKind: string, operationName: string, variables: string, response: string): Messages.GraphQL;
41
+ export declare function PerformanceTrack(frames: number, ticks: number, totalJSHeapSize: number, usedJSHeapSize: number): Messages.PerformanceTrack;
42
+ export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string): Messages.ResourceTiming;
43
+ export declare function ConnectionInformation(downlink: number, type: string): Messages.ConnectionInformation;
44
+ export declare function SetPageVisibility(hidden: boolean): Messages.SetPageVisibility;
45
+ export declare function LongTask(timestamp: number, duration: number, context: number, containerType: number, containerSrc: string, containerId: string, containerName: string): Messages.LongTask;
46
+ export declare function SetNodeAttributeURLBased(id: number, name: string, value: string, baseURL: string): Messages.SetNodeAttributeURLBased;
47
+ export declare function SetCSSDataURLBased(id: number, data: string, baseURL: string): Messages.SetCSSDataURLBased;
48
+ export declare function TechnicalInfo(type: string, value: string): Messages.TechnicalInfo;
49
+ export declare function CustomIssue(name: string, payload: string): Messages.CustomIssue;
50
+ export declare function CSSInsertRuleURLBased(id: number, rule: string, index: number, baseURL: string): Messages.CSSInsertRuleURLBased;
51
+ export declare function MouseClick(id: number, hesitationTime: number, label: string, selector: string): Messages.MouseClick;
52
+ export declare function CreateIFrameDocument(frameID: number, id: number): Messages.CreateIFrameDocument;
@@ -0,0 +1,58 @@
1
+ import * as Messages from '../common/messages.gen.js';
2
+ export { default } from '../common/messages.gen.js';
3
+ export declare function BatchMetadata(version: number, pageNo: number, firstIndex: number, timestamp: number, location: string): Messages.BatchMetadata;
4
+ export declare function PartitionedMessage(partNo: number, partTotal: number): Messages.PartitionedMessage;
5
+ export declare function Timestamp(timestamp: number): Messages.Timestamp;
6
+ export declare function SetPageLocation(url: string, referrer: string, navigationStart: number): Messages.SetPageLocation;
7
+ export declare function SetViewportSize(width: number, height: number): Messages.SetViewportSize;
8
+ export declare function SetViewportScroll(x: number, y: number): Messages.SetViewportScroll;
9
+ export declare function CreateDocument(): Messages.CreateDocument;
10
+ export declare function CreateElementNode(id: number, parentID: number, index: number, tag: string, svg: boolean): Messages.CreateElementNode;
11
+ export declare function CreateTextNode(id: number, parentID: number, index: number): Messages.CreateTextNode;
12
+ export declare function MoveNode(id: number, parentID: number, index: number): Messages.MoveNode;
13
+ export declare function RemoveNode(id: number): Messages.RemoveNode;
14
+ export declare function SetNodeAttribute(id: number, name: string, value: string): Messages.SetNodeAttribute;
15
+ export declare function RemoveNodeAttribute(id: number, name: string): Messages.RemoveNodeAttribute;
16
+ export declare function SetNodeData(id: number, data: string): Messages.SetNodeData;
17
+ export declare function SetNodeScroll(id: number, x: number, y: number): Messages.SetNodeScroll;
18
+ export declare function SetInputTarget(id: number, label: string): Messages.SetInputTarget;
19
+ export declare function SetInputValue(id: number, value: string, mask: number): Messages.SetInputValue;
20
+ export declare function SetInputChecked(id: number, checked: boolean): Messages.SetInputChecked;
21
+ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
+ export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
+ export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
24
+ export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
25
+ export declare function JSException(name: string, message: string, payload: string): Messages.JSException;
26
+ export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
+ export declare function UserID(id: string): Messages.UserID;
28
+ export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
29
+ export declare function Metadata(key: string, value: string): Messages.Metadata;
30
+ export declare function CSSInsertRule(id: number, rule: string, index: number): Messages.CSSInsertRule;
31
+ export declare function CSSDeleteRule(id: number, index: number): Messages.CSSDeleteRule;
32
+ export declare function Fetch(method: string, url: string, request: string, response: string, status: number, timestamp: number, duration: number): Messages.Fetch;
33
+ export declare function Profiler(name: string, duration: number, args: string, result: string): Messages.Profiler;
34
+ export declare function OTable(key: string, value: string): Messages.OTable;
35
+ export declare function StateAction(type: string): Messages.StateAction;
36
+ export declare function Redux(action: string, state: string, duration: number): Messages.Redux;
37
+ export declare function Vuex(mutation: string, state: string): Messages.Vuex;
38
+ export declare function MobX(type: string, payload: string): Messages.MobX;
39
+ export declare function NgRx(action: string, state: string, duration: number): Messages.NgRx;
40
+ export declare function GraphQL(operationKind: string, operationName: string, variables: string, response: string): Messages.GraphQL;
41
+ export declare function PerformanceTrack(frames: number, ticks: number, totalJSHeapSize: number, usedJSHeapSize: number): Messages.PerformanceTrack;
42
+ export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string): Messages.ResourceTiming;
43
+ export declare function ConnectionInformation(downlink: number, type: string): Messages.ConnectionInformation;
44
+ export declare function SetPageVisibility(hidden: boolean): Messages.SetPageVisibility;
45
+ export declare function LongTask(timestamp: number, duration: number, context: number, containerType: number, containerSrc: string, containerId: string, containerName: string): Messages.LongTask;
46
+ export declare function SetNodeAttributeURLBased(id: number, name: string, value: string, baseURL: string): Messages.SetNodeAttributeURLBased;
47
+ export declare function SetCSSDataURLBased(id: number, data: string, baseURL: string): Messages.SetCSSDataURLBased;
48
+ export declare function TechnicalInfo(type: string, value: string): Messages.TechnicalInfo;
49
+ export declare function CustomIssue(name: string, payload: string): Messages.CustomIssue;
50
+ export declare function CSSInsertRuleURLBased(id: number, rule: string, index: number, baseURL: string): Messages.CSSInsertRuleURLBased;
51
+ export declare function MouseClick(id: number, hesitationTime: number, label: string, selector: string): Messages.MouseClick;
52
+ export declare function CreateIFrameDocument(frameID: number, id: number): Messages.CreateIFrameDocument;
53
+ export declare function AdoptedSSReplaceURLBased(sheetID: number, text: string, baseURL: string): Messages.AdoptedSSReplaceURLBased;
54
+ export declare function AdoptedSSInsertRuleURLBased(sheetID: number, rule: string, index: number, baseURL: string): Messages.AdoptedSSInsertRuleURLBased;
55
+ export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Messages.AdoptedSSDeleteRule;
56
+ export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
57
+ export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
58
+ export declare function Zustand(mutation: string, state: string): Messages.Zustand;