@openreplay/tracker 4.1.4 → 4.1.6

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 (52) hide show
  1. package/cjs/app/guards.d.ts +1 -0
  2. package/cjs/app/index.d.ts +2 -0
  3. package/cjs/app/index.js +34 -26
  4. package/cjs/app/messages.d.ts +1 -1
  5. package/cjs/app/messages.gen.d.ts +4 -1
  6. package/cjs/app/messages.gen.js +32 -5
  7. package/cjs/app/messages.js +2 -2
  8. package/cjs/app/nodes.d.ts +1 -1
  9. package/cjs/app/nodes.js +4 -4
  10. package/cjs/app/observer/top_observer.js +2 -0
  11. package/cjs/common/interaction.d.ts +6 -1
  12. package/cjs/common/messages.gen.d.ts +26 -5
  13. package/cjs/index.d.ts +3 -3
  14. package/cjs/index.js +11 -6
  15. package/cjs/modules/constructedStyleSheets.js +14 -11
  16. package/cjs/modules/cssrules.js +6 -6
  17. package/cjs/modules/exception.d.ts +2 -2
  18. package/cjs/modules/exception.js +8 -8
  19. package/cjs/modules/focus.d.ts +2 -0
  20. package/cjs/modules/focus.js +45 -0
  21. package/cjs/modules/fonts.d.ts +2 -0
  22. package/cjs/modules/fonts.js +57 -0
  23. package/cjs/modules/img.js +1 -1
  24. package/cjs/utils.d.ts +1 -1
  25. package/cjs/utils.js +2 -2
  26. package/lib/app/guards.d.ts +1 -0
  27. package/lib/app/index.d.ts +2 -0
  28. package/lib/app/index.js +34 -26
  29. package/lib/app/messages.d.ts +1 -1
  30. package/lib/app/messages.gen.d.ts +4 -1
  31. package/lib/app/messages.gen.js +26 -2
  32. package/lib/app/messages.js +2 -2
  33. package/lib/app/nodes.d.ts +1 -1
  34. package/lib/app/nodes.js +4 -4
  35. package/lib/app/observer/top_observer.js +2 -0
  36. package/lib/common/interaction.d.ts +6 -1
  37. package/lib/common/messages.gen.d.ts +26 -5
  38. package/lib/common/tsconfig.tsbuildinfo +1 -1
  39. package/lib/index.d.ts +3 -3
  40. package/lib/index.js +11 -6
  41. package/lib/modules/constructedStyleSheets.js +15 -12
  42. package/lib/modules/cssrules.js +6 -6
  43. package/lib/modules/exception.d.ts +2 -2
  44. package/lib/modules/exception.js +8 -8
  45. package/lib/modules/focus.d.ts +2 -0
  46. package/lib/modules/focus.js +42 -0
  47. package/lib/modules/fonts.d.ts +2 -0
  48. package/lib/modules/fonts.js +54 -0
  49. package/lib/modules/img.js +2 -2
  50. package/lib/utils.d.ts +1 -1
  51. package/lib/utils.js +1 -1
  52. package/package.json +1 -1
@@ -20,20 +20,16 @@ function default_1(app) {
20
20
  return;
21
21
  }
22
22
  if (!hasAdoptedSS(document)) {
23
- app.attachStartCallback(() => {
24
- // MBTODO: pre-start sendQueue app
25
- app.send((0, messages_gen_js_1.TechnicalInfo)('no_adopted_stylesheets', ''));
26
- });
27
23
  return;
28
24
  }
29
25
  const styleSheetIDMap = new Map();
30
26
  const adoptedStyleSheetsOwnings = new Map();
31
- const sendAdoptedStyleSheetsUpdate = (root) => {
27
+ const sendAdoptedStyleSheetsUpdate = (root) => setTimeout(() => {
32
28
  let nodeID = app.nodes.getID(root);
33
29
  if (root === document) {
34
30
  nodeID = 0; // main document doesn't have nodeID. ID count starts from the documentElement
35
31
  }
36
- if (!nodeID) {
32
+ if (nodeID === undefined) {
37
33
  return;
38
34
  }
39
35
  let pastOwning = adoptedStyleSheetsOwnings.get(nodeID);
@@ -47,8 +43,8 @@ function default_1(app) {
47
43
  const init = !sheetID;
48
44
  if (!sheetID) {
49
45
  sheetID = nextID();
46
+ styleSheetIDMap.set(s, sheetID);
50
47
  }
51
- nowOwning.push(sheetID);
52
48
  if (!pastOwning.includes(sheetID)) {
53
49
  app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
54
50
  }
@@ -58,6 +54,7 @@ function default_1(app) {
58
54
  app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, rules[i].cssText, i, app.getBaseHref()));
59
55
  }
60
56
  }
57
+ nowOwning.push(sheetID);
61
58
  }
62
59
  for (const sheetID of pastOwning) {
63
60
  if (!nowOwning.includes(sheetID)) {
@@ -65,7 +62,13 @@ function default_1(app) {
65
62
  }
66
63
  }
67
64
  adoptedStyleSheetsOwnings.set(nodeID, nowOwning);
68
- };
65
+ }, 20); // Misterious bug:
66
+ /* On the page https://explore.fast.design/components/fast-accordion
67
+ the only rule inside the only adoptedStyleSheet of the iframe-s document
68
+ gets changed during first milliseconds after the load.
69
+ Howerer, none of the documented methods (replace, insertRule) is triggered.
70
+ The rule is not substituted (remains the same object), however the text gets changed.
71
+ */
69
72
  function patchAdoptedStyleSheets(prototype) {
70
73
  const nativeAdoptedStyleSheetsDescriptor = Object.getOwnPropertyDescriptor(prototype, 'adoptedStyleSheets');
71
74
  if (nativeAdoptedStyleSheetsDescriptor) {
@@ -88,8 +91,8 @@ function default_1(app) {
88
91
  }
89
92
  patchAdoptedStyleSheets(context.Document.prototype);
90
93
  patchAdoptedStyleSheets(context.ShadowRoot.prototype);
91
- //@ts-ignore TODO: configure ts (use necessary lib)
92
- const { insertRule, deleteRule, replace, replaceSync } = context.CSSStyleSheet.prototype;
94
+ //@ts-ignore TODO: upgrade ts to 4.8+
95
+ const { replace, replaceSync } = context.CSSStyleSheet.prototype;
93
96
  //@ts-ignore
94
97
  context.CSSStyleSheet.prototype.replace = function (text) {
95
98
  return replace.call(this, text).then((sheet) => {
@@ -110,7 +113,7 @@ function default_1(app) {
110
113
  };
111
114
  };
112
115
  patchContext(window);
113
- app.observer.attachContextCallback(patchContext);
116
+ app.observer.attachContextCallback(app.safe(patchContext));
114
117
  app.attachStopCallback(() => {
115
118
  styleSheetIDMap.clear();
116
119
  adoptedStyleSheetsOwnings.clear();
@@ -11,7 +11,7 @@ function default_1(app) {
11
11
  app.send((0, messages_gen_js_1.TechnicalInfo)('no_stylesheet_prototype_in_window', ''));
12
12
  return;
13
13
  }
14
- const sendInserDeleteRule = app.safe((sheet, index, rule) => {
14
+ const sendInsertDeleteRule = app.safe((sheet, index, rule) => {
15
15
  const sheetID = constructedStyleSheets_js_1.styleSheetIDMap.get(sheet);
16
16
  if (!sheetID) {
17
17
  // OK-case. Sheet haven't been registered yet. Rules will be sent on registration.
@@ -51,15 +51,15 @@ function default_1(app) {
51
51
  app.debug.warn('Rule index not found in', sheet, topmostRule);
52
52
  }
53
53
  });
54
- const patchContext = (context) => {
54
+ const patchContext = app.safe((context) => {
55
55
  const { insertRule, deleteRule } = context.CSSStyleSheet.prototype;
56
56
  const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype;
57
57
  context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
58
- sendInserDeleteRule(this, index, rule);
58
+ sendInsertDeleteRule(this, index, rule);
59
59
  return insertRule.call(this, rule, index);
60
60
  };
61
61
  context.CSSStyleSheet.prototype.deleteRule = function (index) {
62
- sendInserDeleteRule(this, index);
62
+ sendInsertDeleteRule(this, index);
63
63
  return deleteRule.call(this, index);
64
64
  };
65
65
  context.CSSGroupingRule.prototype.insertRule = function (rule, index = 0) {
@@ -72,7 +72,7 @@ function default_1(app) {
72
72
  sendReplaceGroupingRule(this);
73
73
  return result;
74
74
  };
75
- };
75
+ });
76
76
  patchContext(window);
77
77
  app.observer.attachContextCallback(patchContext);
78
78
  app.nodes.attachNodeCallback((node) => {
@@ -92,7 +92,7 @@ function default_1(app) {
92
92
  app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
93
93
  const rules = sheet.cssRules;
94
94
  for (let i = 0; i < rules.length; i++) {
95
- sendInserDeleteRule(sheet, i, rules[i].cssText);
95
+ sendInsertDeleteRule(sheet, i, rules[i].cssText);
96
96
  }
97
97
  });
98
98
  }
@@ -10,7 +10,7 @@ interface StackFrame {
10
10
  functionName?: string;
11
11
  source?: string;
12
12
  }
13
- export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>): Message;
14
- export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis): Message | null;
13
+ export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>, metadata?: Record<string, any>): Message;
14
+ export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis, metadata?: Record<string, any>): Message | null;
15
15
  export default function (app: App, opts: Partial<Options>): void;
16
16
  export {};
@@ -14,19 +14,19 @@ function getDefaultStack(e) {
14
14
  },
15
15
  ];
16
16
  }
17
- function getExceptionMessage(error, fallbackStack) {
17
+ function getExceptionMessage(error, fallbackStack, metadata = {}) {
18
18
  let stack = fallbackStack;
19
19
  try {
20
20
  stack = error_stack_parser_1.default.parse(error);
21
21
  }
22
22
  catch (e) { }
23
- return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack));
23
+ return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack), JSON.stringify(metadata));
24
24
  }
25
25
  exports.getExceptionMessage = getExceptionMessage;
26
- function getExceptionMessageFromEvent(e, context = window) {
26
+ function getExceptionMessageFromEvent(e, context = window, metadata = {}) {
27
27
  if (e instanceof ErrorEvent) {
28
28
  if (e.error instanceof Error) {
29
- return getExceptionMessage(e.error, getDefaultStack(e));
29
+ return getExceptionMessage(e.error, getDefaultStack(e), metadata);
30
30
  }
31
31
  else {
32
32
  let [name, message] = e.message.split(':');
@@ -34,12 +34,12 @@ function getExceptionMessageFromEvent(e, context = window) {
34
34
  name = 'Error';
35
35
  message = e.message;
36
36
  }
37
- return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)));
37
+ return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)), JSON.stringify(metadata));
38
38
  }
39
39
  }
40
40
  else if ('PromiseRejectionEvent' in context && e instanceof context.PromiseRejectionEvent) {
41
41
  if (e.reason instanceof Error) {
42
- return getExceptionMessage(e.reason, []);
42
+ return getExceptionMessage(e.reason, [], metadata);
43
43
  }
44
44
  else {
45
45
  let message;
@@ -49,7 +49,7 @@ function getExceptionMessageFromEvent(e, context = window) {
49
49
  catch (_) {
50
50
  message = String(e.reason);
51
51
  }
52
- return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]');
52
+ return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]', JSON.stringify(metadata));
53
53
  }
54
54
  }
55
55
  return null;
@@ -70,7 +70,7 @@ function default_1(app, opts) {
70
70
  app.attachEventListener(context, 'error', handler);
71
71
  }
72
72
  if (options.captureExceptions) {
73
- app.observer.attachContextCallback(patchContext);
73
+ app.observer.attachContextCallback(patchContext); // TODO: attach once-per-iframe (?)
74
74
  patchContext(window);
75
75
  }
76
76
  }
@@ -0,0 +1,2 @@
1
+ import type App from '../app/index.js';
2
+ export default function (app: App): void;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const guards_js_1 = require("../app/guards.js");
4
+ const messages_gen_js_1 = require("../app/messages.gen.js");
5
+ function default_1(app) {
6
+ function sendSetNodeFocus(n) {
7
+ const id = app.nodes.getID(n);
8
+ if (id !== undefined) {
9
+ app.send((0, messages_gen_js_1.SetNodeFocus)(id));
10
+ }
11
+ }
12
+ let blurred = false;
13
+ app.nodes.attachNodeCallback((node) => {
14
+ if (!(0, guards_js_1.hasTag)(node, 'BODY')) {
15
+ return;
16
+ }
17
+ app.nodes.attachNodeListener(node, 'focus', (e) => {
18
+ if (!(0, guards_js_1.isNode)(e.target)) {
19
+ return;
20
+ }
21
+ sendSetNodeFocus(e.target);
22
+ blurred = false;
23
+ });
24
+ app.nodes.attachNodeListener(node, 'blur', (e) => {
25
+ if (e.relatedTarget === null) {
26
+ blurred = true;
27
+ setTimeout(() => {
28
+ if (blurred) {
29
+ app.send((0, messages_gen_js_1.SetNodeFocus)(-1));
30
+ }
31
+ }, 0);
32
+ }
33
+ });
34
+ });
35
+ app.attachStartCallback(() => {
36
+ let elem = document.activeElement;
37
+ while (elem && (0, guards_js_1.hasTag)(elem, 'IFRAME') && elem.contentDocument) {
38
+ elem = elem.contentDocument.activeElement;
39
+ }
40
+ if (elem && elem !== elem.ownerDocument.body) {
41
+ sendSetNodeFocus(elem);
42
+ }
43
+ }, true);
44
+ }
45
+ exports.default = default_1;
@@ -0,0 +1,2 @@
1
+ import type App from '../app/index.js';
2
+ export default function (app: App): void;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const guards_js_1 = require("../app/guards.js");
4
+ const messages_gen_js_1 = require("../app/messages.gen.js");
5
+ function default_1(app) {
6
+ if (!window.FontFace) {
7
+ return;
8
+ }
9
+ const docFonts = new Map();
10
+ const patchWindow = (wnd) => {
11
+ class FontFaceInterceptor extends wnd.FontFace {
12
+ constructor(...args) {
13
+ //maybe do this on load(). In this case check if the document.fonts.load(...) function calls the font's load()
14
+ if (typeof args[1] === 'string') {
15
+ let desc = '';
16
+ if (args[2]) {
17
+ app.safe(() => {
18
+ desc = JSON.stringify(args[2]);
19
+ });
20
+ }
21
+ const ffData = [args[0], args[1], desc];
22
+ const ffDataArr = docFonts.get(wnd.document) || [];
23
+ ffDataArr.push(ffData);
24
+ docFonts.set(wnd.document, ffDataArr);
25
+ const parentID = wnd === window ? 0 : app.nodes.getID(wnd.document);
26
+ if (parentID === undefined) {
27
+ return;
28
+ }
29
+ if (app.active()) {
30
+ app.send((0, messages_gen_js_1.LoadFontFace)(parentID, ...ffData));
31
+ }
32
+ }
33
+ super(...args);
34
+ }
35
+ }
36
+ wnd.FontFace = FontFaceInterceptor;
37
+ };
38
+ app.observer.attachContextCallback(patchWindow);
39
+ patchWindow(window);
40
+ app.nodes.attachNodeCallback((node) => {
41
+ if (!(0, guards_js_1.isDocument)(node)) {
42
+ return;
43
+ }
44
+ const ffDataArr = docFonts.get(node);
45
+ if (!ffDataArr) {
46
+ return;
47
+ }
48
+ const parentID = node.defaultView === window ? 0 : app.nodes.getID(node);
49
+ if (parentID === undefined) {
50
+ return;
51
+ }
52
+ ffDataArr.forEach((ffData) => {
53
+ app.send((0, messages_gen_js_1.LoadFontFace)(parentID, ...ffData));
54
+ });
55
+ });
56
+ }
57
+ exports.default = default_1;
@@ -54,7 +54,7 @@ function default_1(app) {
54
54
  const sendImgError = app.safe(function (img) {
55
55
  const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
56
56
  if ((0, utils_js_1.isURL)(resolvedSrc)) {
57
- app.send((0, messages_gen_js_1.ResourceTiming)((0, utils_js_1.timestamp)(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
57
+ app.send((0, messages_gen_js_1.ResourceTiming)(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
58
58
  }
59
59
  });
60
60
  const sendImgAttrs = app.safe(function (img) {
package/cjs/utils.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export declare const IN_BROWSER: boolean;
2
2
  export declare const IS_FIREFOX: false | RegExpMatchArray | null;
3
3
  export declare const MAX_STR_LEN = 100000;
4
- export declare const timestamp: () => number;
4
+ export declare const now: () => number;
5
5
  export declare const stars: (str: string) => string;
6
6
  export declare function normSpaces(str: string): string;
7
7
  export declare function isURL(s: string): boolean;
package/cjs/utils.js CHANGED
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.timestamp = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
3
+ exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.now = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
4
4
  const DEPRECATED_ATTRS = { htmlmasked: 'hidden', masked: 'obscured' };
5
5
  exports.IN_BROWSER = !(typeof window === 'undefined');
6
6
  exports.IS_FIREFOX = exports.IN_BROWSER && navigator.userAgent.match(/firefox|fxios/i);
7
7
  exports.MAX_STR_LEN = 1e5;
8
8
  const navigationStart = exports.IN_BROWSER && (performance.timing.navigationStart || performance.timeOrigin);
9
9
  // performance.now() is buggy in some browsers
10
- exports.timestamp = exports.IN_BROWSER && performance.now() && navigationStart
10
+ exports.now = exports.IN_BROWSER && performance.now() && navigationStart
11
11
  ? () => Math.round(performance.now() + navigationStart)
12
12
  : () => Date.now();
13
13
  exports.stars = 'repeat' in String.prototype
@@ -6,6 +6,7 @@ export declare function isDocument(node: Node): node is Document;
6
6
  export declare function isRootNode(node: Node): node is Document | DocumentFragment;
7
7
  declare type TagTypeMap = {
8
8
  HTML: HTMLHtmlElement;
9
+ BODY: HTMLBodyElement;
9
10
  IMG: HTMLImageElement;
10
11
  INPUT: HTMLInputElement;
11
12
  TEXTAREA: HTMLTextAreaElement;
@@ -77,6 +77,8 @@ export default class App {
77
77
  private _debug;
78
78
  send(message: Message, urgent?: boolean): void;
79
79
  private commit;
80
+ private delay;
81
+ timestamp(): number;
80
82
  safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
81
83
  attachCommitCallback(cb: CommitCallback): void;
82
84
  attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
package/lib/app/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Timestamp, Metadata, UserID } from './messages.gen.js';
2
- import { timestamp as now } from '../utils.js';
2
+ import { now } from '../utils.js';
3
3
  import Nodes from './nodes.js';
4
4
  import Observer from './observer/top_observer.js';
5
5
  import Sanitizer from './sanitizer.js';
@@ -24,12 +24,14 @@ export default class App {
24
24
  // if (options.onStart !== undefined) {
25
25
  // deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)")
26
26
  // } ?? maybe onStart is good
27
+ var _a, _b;
27
28
  this.messages = [];
28
29
  this.startCallbacks = [];
29
30
  this.stopCallbacks = [];
30
31
  this.commitCallbacks = [];
31
32
  this.activityState = ActivityState.NotActive;
32
- this.version = '4.1.4'; // TODO: version compatability check inside each plugin.
33
+ this.version = '4.1.6'; // TODO: version compatability check inside each plugin.
34
+ this.delay = 0;
33
35
  this.projectKey = projectKey;
34
36
  this.options = Object.assign({
35
37
  revID: '',
@@ -43,10 +45,12 @@ export default class App {
43
45
  verbose: false,
44
46
  __is_snippet: false,
45
47
  __debug_report_edp: null,
46
- localStorage: window === null || window === void 0 ? void 0 : window.localStorage,
47
- sessionStorage: window === null || window === void 0 ? void 0 : window.sessionStorage,
48
+ localStorage: null,
49
+ sessionStorage: null,
48
50
  }, options);
49
51
  this.revID = this.options.revID;
52
+ this.localStorage = (_a = this.options.localStorage) !== null && _a !== void 0 ? _a : window.localStorage;
53
+ this.sessionStorage = (_b = this.options.sessionStorage) !== null && _b !== void 0 ? _b : window.sessionStorage;
50
54
  this.sanitizer = new Sanitizer(this, options);
51
55
  this.nodes = new Nodes(this.options.node_id);
52
56
  this.observer = new Observer(this, options);
@@ -54,8 +58,6 @@ export default class App {
54
58
  this.ticker.attach(() => this.commit());
55
59
  this.debug = new Logger(this.options.__debug__);
56
60
  this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
57
- this.localStorage = this.options.localStorage || window.localStorage;
58
- this.sessionStorage = this.options.sessionStorage || window.sessionStorage;
59
61
  this.session = new Session(this, this.options);
60
62
  this.session.attachUpdateCallback(({ userID, metadata }) => {
61
63
  if (userID != null) {
@@ -71,18 +73,18 @@ export default class App {
71
73
  this.session.applySessionHash(sessionToken);
72
74
  }
73
75
  try {
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!==f&&(clearInterval(f),f=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){self.postMessage("restart"),a()}n.NotActive;let c,f=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]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},()=>{self.postMessage("failed"),a()},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===f&&(f=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' })));
76
+ 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(`Failed to send batch after ${this.attemptsCount} attempts.`):(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 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])}}}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!==g&&(clearInterval(g),g=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){postMessage("restart"),a()}n.NotActive;let c,g=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]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},t=>{!function(t){postMessage({type:"failure",reason:t}),a()}(t)},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===g&&(g=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
77
  this.worker.onerror = (e) => {
76
78
  this._debug('webworker_error', e);
77
79
  };
78
80
  this.worker.onmessage = ({ data }) => {
79
- if (data === 'failed') {
81
+ if (data === 'restart') {
80
82
  this.stop(false);
81
- this._debug('worker_failed', {}); // add context (from worker)
83
+ this.start({ forceNew: true }); // TODO: keep userID & metadata (draw scenarios)
82
84
  }
83
- else if (data === 'restart') {
85
+ else if (data.type === 'failure') {
84
86
  this.stop(false);
85
- this.start({ forceNew: true }); // TODO: keep userID & metadata (draw scenarios)
87
+ this._debug('worker_failed', data.reason);
86
88
  }
87
89
  };
88
90
  const alertWorker = () => {
@@ -102,7 +104,7 @@ export default class App {
102
104
  }
103
105
  _debug(context, e) {
104
106
  if (this.options.__debug_report_edp !== null) {
105
- fetch(this.options.__debug_report_edp, {
107
+ void fetch(this.options.__debug_report_edp, {
106
108
  method: 'POST',
107
109
  headers: { 'Content-Type': 'application/json' },
108
110
  body: JSON.stringify({
@@ -115,25 +117,30 @@ export default class App {
115
117
  }
116
118
  send(message, urgent = false) {
117
119
  if (this.activityState === ActivityState.NotActive) {
120
+ // this.debug.log('SendiTrying to send when not active', message) <- crashing the app
118
121
  return;
119
122
  }
120
123
  this.messages.push(message);
121
124
  // TODO: commit on start if there were `urgent` sends;
122
- // Clearify where urgent can be used for;
123
- // Clearify workflow for each type of message in case it was sent before start
125
+ // Clarify where urgent can be used for;
126
+ // Clarify workflow for each type of message in case it was sent before start
124
127
  // (like Fetch before start; maybe add an option "preCapture: boolean" or sth alike)
128
+ // Careful: `this.delay` is equal to zero before start hense all Timestamp-s will have to be updated on start
125
129
  if (this.activityState === ActivityState.Active && urgent) {
126
130
  this.commit();
127
131
  }
128
132
  }
129
133
  commit() {
130
134
  if (this.worker && this.messages.length) {
131
- this.messages.unshift(Timestamp(now()));
135
+ this.messages.unshift(Timestamp(this.timestamp()));
132
136
  this.worker.postMessage(this.messages);
133
137
  this.commitCallbacks.forEach((cb) => cb(this.messages));
134
138
  this.messages.length = 0;
135
139
  }
136
140
  }
141
+ timestamp() {
142
+ return now() + this.delay;
143
+ }
137
144
  safe(fn) {
138
145
  const app = this;
139
146
  return function (...args) {
@@ -142,7 +149,7 @@ export default class App {
142
149
  }
143
150
  catch (e) {
144
151
  app._debug('safe_fn_call', e);
145
- // time: now(),
152
+ // time: this.timestamp(),
146
153
  // name: e.name,
147
154
  // message: e.message,
148
155
  // stack: e.stack
@@ -169,8 +176,8 @@ export default class App {
169
176
  if (useSafe) {
170
177
  listener = this.safe(listener);
171
178
  }
172
- this.attachStartCallback(() => target.addEventListener(type, listener, useCapture), useSafe);
173
- this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture), useSafe);
179
+ this.attachStartCallback(() => target === null || target === void 0 ? void 0 : target.addEventListener(type, listener, useCapture), useSafe);
180
+ this.attachStopCallback(() => target === null || target === void 0 ? void 0 : target.removeEventListener(type, listener, useCapture), useSafe);
174
181
  }
175
182
  // TODO: full correct semantic
176
183
  checkRequiredVersion(version) {
@@ -271,7 +278,7 @@ export default class App {
271
278
  this.session.applySessionHash(startOpts.sessionHash);
272
279
  }
273
280
  const timestamp = now();
274
- const startWorkerMsg = {
281
+ this.worker.postMessage({
275
282
  type: 'start',
276
283
  pageNo: this.session.incPageNo(),
277
284
  ingestPoint: this.options.ingestPoint,
@@ -279,8 +286,7 @@ export default class App {
279
286
  url: document.URL,
280
287
  connAttemptCount: this.options.connAttemptCount,
281
288
  connAttemptGap: this.options.connAttemptGap,
282
- };
283
- this.worker.postMessage(startWorkerMsg);
289
+ });
284
290
  this.session.update({
285
291
  // TODO: transparent "session" module logic AND explicit internal api for plugins.
286
292
  // "updating" with old metadata in order to trigger session's UpdateCallbacks.
@@ -320,14 +326,16 @@ export default class App {
320
326
  return Promise.reject('Tracker stopped during authorisation');
321
327
  }
322
328
  const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
323
- } = r;
329
+ delay, } = r;
324
330
  if (typeof token !== 'string' ||
325
331
  typeof userUUID !== 'string' ||
326
332
  //typeof startTimestamp !== 'number' ||
327
333
  //typeof sessionID !== 'string' ||
334
+ typeof delay !== 'number' ||
328
335
  (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
329
336
  return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
330
337
  }
338
+ this.delay = delay;
331
339
  const prevSessionID = this.session.getInfo().sessionID;
332
340
  if (prevSessionID && prevSessionID !== sessionID) {
333
341
  this.session.reset();
@@ -335,14 +343,14 @@ export default class App {
335
343
  this.session.setSessionToken(token);
336
344
  this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
337
345
  this.localStorage.setItem(this.options.local_uuid_key, userUUID);
338
- const startWorkerMsg = {
346
+ this.worker.postMessage({
339
347
  type: 'auth',
340
348
  token,
341
349
  beaconSizeLimit,
342
- };
343
- this.worker.postMessage(startWorkerMsg);
350
+ });
344
351
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
345
- this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
352
+ // TODO: start as early as possible (before receiving the token)
353
+ this.startCallbacks.forEach((cb) => cb(onStartInfo)); // MBTODO: callbacks after DOM "mounted" (observed)
346
354
  this.observer.observe();
347
355
  this.ticker.start();
348
356
  this.activityState = ActivityState.Active;
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
22
  export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
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
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;
25
+ export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
26
26
  export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
27
  export declare function UserID(id: string): Messages.UserID;
28
28
  export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
22
  export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
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
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;
25
+ export declare function JSExceptionDeprecated(name: string, message: string, payload: string): Messages.JSExceptionDeprecated;
26
26
  export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
27
  export declare function UserID(id: string): Messages.UserID;
28
28
  export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
@@ -42,6 +42,8 @@ export declare function PerformanceTrack(frames: number, ticks: number, totalJSH
42
42
  export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string): Messages.ResourceTiming;
43
43
  export declare function ConnectionInformation(downlink: number, type: string): Messages.ConnectionInformation;
44
44
  export declare function SetPageVisibility(hidden: boolean): Messages.SetPageVisibility;
45
+ export declare function LoadFontFace(parentID: number, family: string, source: string, descriptors: string): Messages.LoadFontFace;
46
+ export declare function SetNodeFocus(id: number): Messages.SetNodeFocus;
45
47
  export declare function LongTask(timestamp: number, duration: number, context: number, containerType: number, containerSrc: string, containerId: string, containerName: string): Messages.LongTask;
46
48
  export declare function SetNodeAttributeURLBased(id: number, name: string, value: string, baseURL: string): Messages.SetNodeAttributeURLBased;
47
49
  export declare function SetCSSDataURLBased(id: number, data: string, baseURL: string): Messages.SetCSSDataURLBased;
@@ -56,3 +58,4 @@ export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Mes
56
58
  export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
57
59
  export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
58
60
  export declare function Zustand(mutation: string, state: string): Messages.Zustand;
61
+ export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;