@openreplay/tracker 4.1.11 → 5.0.0

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 (71) hide show
  1. package/.eslintignore +3 -0
  2. package/CHANGELOG.md +20 -0
  3. package/README.md +22 -18
  4. package/cjs/app/guards.d.ts +11 -12
  5. package/cjs/app/guards.js +2 -1
  6. package/cjs/app/index.d.ts +11 -8
  7. package/cjs/app/index.js +27 -8
  8. package/cjs/app/logger.d.ts +3 -3
  9. package/cjs/app/messages.gen.d.ts +8 -6
  10. package/cjs/app/messages.gen.js +116 -94
  11. package/cjs/app/nodes.d.ts +1 -1
  12. package/cjs/app/observer/iframe_offsets.d.ts +1 -1
  13. package/cjs/app/observer/observer.js +5 -5
  14. package/cjs/app/observer/top_observer.d.ts +2 -2
  15. package/cjs/app/observer/top_observer.js +1 -1
  16. package/cjs/app/session.d.ts +2 -2
  17. package/cjs/app/ticker.d.ts +1 -1
  18. package/cjs/common/interaction.d.ts +5 -5
  19. package/cjs/common/messages.gen.d.ts +104 -86
  20. package/cjs/index.d.ts +6 -2
  21. package/cjs/index.js +7 -5
  22. package/cjs/modules/cssrules.js +1 -1
  23. package/cjs/modules/focus.js +2 -2
  24. package/cjs/modules/fonts.js +2 -2
  25. package/cjs/modules/img.js +6 -5
  26. package/cjs/modules/input.d.ts +1 -1
  27. package/cjs/modules/input.js +15 -23
  28. package/cjs/modules/mouse.js +1 -1
  29. package/cjs/modules/network.d.ts +28 -0
  30. package/cjs/modules/network.js +203 -0
  31. package/cjs/modules/timing.js +7 -3
  32. package/cjs/modules/viewport.js +3 -1
  33. package/cjs/vendors/finder/finder.d.ts +1 -1
  34. package/jest.config.js +11 -0
  35. package/lib/app/guards.d.ts +11 -12
  36. package/lib/app/guards.js +2 -1
  37. package/lib/app/index.d.ts +11 -8
  38. package/lib/app/index.js +28 -9
  39. package/lib/app/logger.d.ts +3 -3
  40. package/lib/app/messages.gen.d.ts +8 -6
  41. package/lib/app/messages.gen.js +107 -87
  42. package/lib/app/nodes.d.ts +1 -1
  43. package/lib/app/observer/iframe_offsets.d.ts +1 -1
  44. package/lib/app/observer/observer.js +5 -5
  45. package/lib/app/observer/top_observer.d.ts +2 -2
  46. package/lib/app/observer/top_observer.js +1 -1
  47. package/lib/app/session.d.ts +2 -2
  48. package/lib/app/ticker.d.ts +1 -1
  49. package/lib/common/interaction.d.ts +5 -5
  50. package/lib/common/messages.gen.d.ts +104 -86
  51. package/lib/common/tsconfig.tsbuildinfo +1 -1
  52. package/lib/index.d.ts +6 -2
  53. package/lib/index.js +8 -6
  54. package/lib/modules/cssrules.js +1 -1
  55. package/lib/modules/focus.js +2 -2
  56. package/lib/modules/fonts.js +2 -2
  57. package/lib/modules/img.js +6 -5
  58. package/lib/modules/input.d.ts +1 -1
  59. package/lib/modules/input.js +15 -23
  60. package/lib/modules/mouse.js +1 -1
  61. package/lib/modules/network.d.ts +28 -0
  62. package/lib/modules/network.js +200 -0
  63. package/lib/modules/timing.js +8 -4
  64. package/lib/modules/viewport.js +3 -1
  65. package/lib/vendors/finder/finder.d.ts +1 -1
  66. package/package.json +8 -3
  67. package/tsconfig-base.json +2 -1
  68. package/cjs/app/messages.d.ts +0 -52
  69. package/cjs/app/messages.js +0 -234
  70. package/lib/app/messages.d.ts +0 -52
  71. package/lib/app/messages.js +0 -181
package/.eslintignore CHANGED
@@ -6,3 +6,6 @@ build
6
6
  .cache
7
7
  .eslintrc.cjs
8
8
  *.gen.ts
9
+
10
+ **/*.test.ts
11
+ src/main/plugin.ts
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ ## 5.0.0
2
+
3
+ - Added "tel" to supported input types
4
+ - Added `{ withCurrentTime: true }` to `tracker.getSessionURL` method which will return sessionURL with current session's timestamp
5
+ - Added Network module that captures fetch/xhr by default (with no plugin required)
6
+ - Use `timeOrigin()` instead of `performance.timing.navigationStart` in ResourceTiming messages
7
+ - Added app restart when service worker died after inactivity (mobile safari)
8
+ - **[breaking]** string dictionary to reduce session size
9
+
10
+ ## 4.1.8
11
+
12
+ - recalculate timeOrigin on start to prevent wrong timestamps on "sleeping" sessions
13
+
14
+ ## 4.1.7
15
+
16
+ - resend metadata on start
17
+
18
+ ## 4.1.6
19
+
20
+ - remove log that potentially caused crashed during slow initial render
package/README.md CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  The main package of the [OpenReplay](https://openreplay.com/) tracker.
4
4
 
5
+ ## Documentation
6
+
7
+ For launch options and available public methods, [refer to the documentation](https://docs.openreplay.com/installation/javascript-sdk#options)
8
+
5
9
  ## Installation
6
10
 
7
11
  ```bash
8
- npm i @openreplay/tracker
12
+ npm i @openreplay/tracker
9
13
  ```
10
14
 
11
15
  ## Usage
@@ -13,30 +17,30 @@ npm i @openreplay/tracker
13
17
  Initialize the package from your codebase entry point and start the tracker. You must set the `projectKey` option in the constructor. Its value can can be found in your OpenReplay dashboard under [Preferences -> Projects](https://app.openreplay.com/client/projects).
14
18
 
15
19
  ```js
16
- import Tracker from '@openreplay/tracker';
20
+ import Tracker from '@openreplay/tracker'
17
21
 
18
22
  const tracker = new Tracker({
19
23
  projectKey: YOUR_PROJECT_KEY,
20
- });
21
- tracker.start({
22
- userID: "Mr.Smith",
23
- metadata: {
24
- version: "3.5.0",
25
- balance: "10M",
26
- role: "admin",
27
- }
28
- }).then(startedSession => {
29
- if (startedSession.success) {
30
- console.log(startedSession)
31
- }
32
24
  })
25
+ tracker
26
+ .start({
27
+ userID: 'Mr.Smith',
28
+ metadata: {
29
+ version: '3.5.0',
30
+ balance: '10M',
31
+ role: 'admin',
32
+ },
33
+ })
34
+ .then((startedSession) => {
35
+ if (startedSession.success) {
36
+ console.log(startedSession)
37
+ }
38
+ })
33
39
  ```
34
40
 
35
41
  Then you can use OpenReplay JavaScript API anywhere in your code.
36
42
 
37
43
  ```js
38
- tracker.setUserID('my_user_id');
39
- tracker.setMetadata('env', 'prod');
44
+ tracker.setUserID('my_user_id')
45
+ tracker.setMetadata('env', 'prod')
40
46
  ```
41
-
42
- Read [our docs](https://docs.openreplay.com/) for more information.
@@ -4,18 +4,17 @@ export declare function isElementNode(node: Node): node is Element;
4
4
  export declare function isTextNode(node: Node): node is Text;
5
5
  export declare function isDocument(node: Node): node is Document;
6
6
  export declare function isRootNode(node: Node): node is Document | DocumentFragment;
7
- declare type TagTypeMap = {
8
- HTML: HTMLHtmlElement;
9
- BODY: HTMLBodyElement;
10
- IMG: HTMLImageElement;
11
- INPUT: HTMLInputElement;
12
- TEXTAREA: HTMLTextAreaElement;
13
- SELECT: HTMLSelectElement;
14
- LABEL: HTMLLabelElement;
15
- IFRAME: HTMLIFrameElement;
16
- STYLE: HTMLStyleElement;
17
- style: SVGStyleElement;
18
- LINK: HTMLLinkElement;
7
+ type TagTypeMap = {
8
+ html: HTMLHtmlElement;
9
+ body: HTMLBodyElement;
10
+ img: HTMLImageElement;
11
+ input: HTMLInputElement;
12
+ textarea: HTMLTextAreaElement;
13
+ select: HTMLSelectElement;
14
+ label: HTMLLabelElement;
15
+ iframe: HTMLIFrameElement;
16
+ style: HTMLStyleElement | SVGStyleElement;
17
+ link: HTMLLinkElement;
19
18
  };
20
19
  export declare function hasTag<T extends keyof TagTypeMap>(el: Node, tagName: T): el is TagTypeMap[typeof tagName];
21
20
  export {};
package/cjs/app/guards.js CHANGED
@@ -27,6 +27,7 @@ function isRootNode(node) {
27
27
  }
28
28
  exports.isRootNode = isRootNode;
29
29
  function hasTag(el, tagName) {
30
- return el.nodeName === tagName;
30
+ // @ts-ignore
31
+ return el.localName === tagName;
31
32
  }
32
33
  exports.hasTag = hasTag;
@@ -22,19 +22,19 @@ interface OnStartInfo {
22
22
  userUUID: string;
23
23
  }
24
24
  declare const CANCELED: "canceled";
25
- declare type SuccessfulStart = OnStartInfo & {
25
+ type SuccessfulStart = OnStartInfo & {
26
26
  success: true;
27
27
  };
28
- declare type UnsuccessfulStart = {
28
+ type UnsuccessfulStart = {
29
29
  reason: typeof CANCELED | string;
30
30
  success: false;
31
31
  };
32
32
  declare const UnsuccessfulStart: (reason: string) => UnsuccessfulStart;
33
33
  declare const SuccessfulStart: (body: OnStartInfo) => SuccessfulStart;
34
- export declare type StartPromiseReturn = SuccessfulStart | UnsuccessfulStart;
35
- declare type StartCallback = (i: OnStartInfo) => void;
36
- declare type CommitCallback = (messages: Array<Message>) => void;
37
- declare type AppOptions = {
34
+ export type StartPromiseReturn = SuccessfulStart | UnsuccessfulStart;
35
+ type StartCallback = (i: OnStartInfo) => void;
36
+ type CommitCallback = (messages: Array<Message>) => void;
37
+ type AppOptions = {
38
38
  revID: string;
39
39
  node_id: string;
40
40
  session_reset_key: string;
@@ -51,7 +51,7 @@ declare type AppOptions = {
51
51
  sessionStorage: Storage | null;
52
52
  onStart?: StartCallback;
53
53
  } & WebworkerOptions & SessOptions;
54
- export declare type Options = AppOptions & ObserverOptions & SanitizerOptions;
54
+ export type Options = AppOptions & ObserverOptions & SanitizerOptions;
55
55
  export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest";
56
56
  export default class App {
57
57
  readonly nodes: Nodes;
@@ -75,6 +75,7 @@ export default class App {
75
75
  private readonly worker?;
76
76
  constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>);
77
77
  private _debug;
78
+ private _usingOldFetchPlugin;
78
79
  send(message: Message, urgent?: boolean): void;
79
80
  private commit;
80
81
  private delay;
@@ -100,7 +101,9 @@ export default class App {
100
101
  };
101
102
  getSessionToken(): string | undefined;
102
103
  getSessionID(): string | undefined;
103
- getSessionURL(): string | undefined;
104
+ getSessionURL(options?: {
105
+ withCurrentTime?: boolean;
106
+ }): string | undefined;
104
107
  getHost(): string;
105
108
  getProjectKey(): string;
106
109
  getBaseHref(): string;
package/cjs/app/index.js CHANGED
@@ -33,7 +33,8 @@ class App {
33
33
  this.stopCallbacks = [];
34
34
  this.commitCallbacks = [];
35
35
  this.activityState = ActivityState.NotActive;
36
- this.version = '4.1.11'; // TODO: version compatability check inside each plugin.
36
+ this.version = '5.0.0'; // TODO: version compatability check inside each plugin.
37
+ this._usingOldFetchPlugin = false;
37
38
  this.delay = 0;
38
39
  this.projectKey = projectKey;
39
40
  this.options = Object.assign({
@@ -76,7 +77,7 @@ class App {
76
77
  this.session.applySessionHash(sessionToken);
77
78
  }
78
79
  try {
79
- 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' })));
80
+ 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,this.busy||this.sendNext()}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}sendNext(){const t=this.queue.shift();t?this.sendBatch(t):this.busy=!1}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();i.status>=400?this.retry(t):(this.attemptsCount=0,this.sendNext())}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0,this.token=null}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,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}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 50:return this.uint(t[1])&&this.string(t[2]);case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 79:return this.string(t[1])&&this.string(t[2]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2])}}}class e{constructor(){this.idx=1,this.backDict={}}getKey(t){let i=!1;return this.backDict[t]||(i=!0,this.backDict[t]=this.idx++),[this.backDict[t],i]}}class n{constructor(t,i,n,r){this.pageNo=t,this.timestamp=i,this.url=n,this.onBatch=r,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.strDict=new e,this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}applyDict(t){const[i,s]=this.strDict.getKey(t);return s&&this.writeMessage([50,i,t]),i}writeMessage(t){0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),12===t[0]&&(t=[51,t[1],this.applyDict(t[2]),this.applyDict(t[3])]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new s(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)||console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new s(this.beaconSize),this.prepare()))}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var r;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(r||(r={}));let h=null,u=null;r.NotActive;let a=0;function c(){u&&u.finaliseBatch()}function o(){r.Stopping,null!==l&&(clearInterval(l),l=null),u&&(u.clean(),u=null),h&&(h.clean(),h=null),r.NotActive}function g(){postMessage("restart"),o()}let f,l=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return c(),void o();if(Array.isArray(i)){if(null!==u){const t=u;i.forEach(i=>{55===i[0]&&(i[1]?f=setTimeout(()=>g(),18e5):clearTimeout(f)),t.writeMessage(i)})}u||(postMessage("not_init"),0===a&&(a+=1,g()))}else{if("start"===i.type)return r.Starting,h=new t(i.ingestPoint,()=>{g()},t=>{!function(t){postMessage({type:"failure",reason:t}),o()}(t)},i.connAttemptCount,i.connAttemptGap),u=new n(i.pageNo,i.timestamp,i.url,t=>h&&h.push(t)),null===l&&(l=setInterval(c,1e4)),r.Active;if("auth"===i.type){if(!h)throw new Error("WebWorker: sender not initialised. Received auth.");if(!u)throw new Error("WebWorker: writer not initialised. Received auth.");return h.authorise(i.token),void(i.beaconSizeLimit&&u.setBeaconSizeLimit(i.beaconSizeLimit))}}}else c()};'], { type: 'text/javascript' })));
80
81
  this.worker.onerror = (e) => {
81
82
  this._debug('webworker_error', e);
82
83
  };
@@ -85,6 +86,9 @@ class App {
85
86
  this.stop(false);
86
87
  this.start({}, true);
87
88
  }
89
+ else if (data === 'not_init') {
90
+ console.warn('WebWorker: writer not initialised. Restarting tracker');
91
+ }
88
92
  else if (data.type === 'failure') {
89
93
  this.stop(false);
90
94
  this._debug('worker_failed', data.reason);
@@ -122,6 +126,16 @@ class App {
122
126
  if (this.activityState === ActivityState.NotActive) {
123
127
  return;
124
128
  }
129
+ // === Back compatibility with Fetch/Axios plugins ===
130
+ if (message[0] === 39 /* MType.Fetch */) {
131
+ this._usingOldFetchPlugin = true;
132
+ (0, utils_js_1.deprecationWarn)('Fetch plugin', "'network' init option", '/installation/network-options');
133
+ (0, utils_js_1.deprecationWarn)('Axios plugin', "'network' init option", '/installation/network-options');
134
+ }
135
+ if (this._usingOldFetchPlugin && message[0] === 21 /* MType.NetworkRequest */) {
136
+ return;
137
+ }
138
+ // ====================================================
125
139
  this.messages.push(message);
126
140
  // TODO: commit on start if there were `urgent` sends;
127
141
  // Clarify where urgent can be used for;
@@ -216,16 +230,21 @@ class App {
216
230
  getSessionID() {
217
231
  return this.session.getInfo().sessionID || undefined;
218
232
  }
219
- getSessionURL() {
220
- const { projectID, sessionID } = this.session.getInfo();
233
+ getSessionURL(options) {
234
+ const { projectID, sessionID, timestamp } = this.session.getInfo();
221
235
  if (!projectID || !sessionID) {
222
236
  this.debug.error('OpenReplay error: Unable to build session URL');
223
237
  return undefined;
224
238
  }
225
239
  const ingest = this.options.ingestPoint;
226
- const isSaas = ingest === exports.DEFAULT_INGEST_POINT;
227
- const projectPath = isSaas ? ingest.replace('api', 'app') : ingest;
228
- return projectPath.replace(/ingest$/, `${projectID}/session/${sessionID}`);
240
+ const isSaas = /api\.openreplay\.com/.test(ingest);
241
+ const projectPath = isSaas ? 'https://openreplay.com/ingest' : ingest;
242
+ const url = projectPath.replace(/ingest$/, `${projectID}/session/${sessionID}`);
243
+ if (options === null || options === void 0 ? void 0 : options.withCurrentTime) {
244
+ const jumpTo = (0, utils_js_1.now)() - timestamp;
245
+ return `${url}?jumpto=${jumpTo}`;
246
+ }
247
+ return url;
229
248
  }
230
249
  getHost() {
231
250
  return new URL(this.options.ingestPoint).host;
@@ -328,7 +347,7 @@ class App {
328
347
  return Promise.reject('no worker found after start request (this might not happen)');
329
348
  }
330
349
  if (this.activityState === ActivityState.NotActive) {
331
- return Promise.reject('Tracker stopped during authorisation');
350
+ return Promise.reject('Tracker stopped during authorization');
332
351
  }
333
352
  const { token, userUUID, projectID, beaconSizeLimit, delay, // derived from token
334
353
  sessionID, // derived from token
@@ -5,8 +5,8 @@ export declare const LogLevel: {
5
5
  readonly Errors: 2;
6
6
  readonly Silent: 0;
7
7
  };
8
- declare type LogLevel = typeof LogLevel[keyof typeof LogLevel];
9
- declare type CustomLevel = {
8
+ type LogLevel = typeof LogLevel[keyof typeof LogLevel];
9
+ type CustomLevel = {
10
10
  error: boolean;
11
11
  warn: boolean;
12
12
  log: boolean;
@@ -15,7 +15,7 @@ interface _Options {
15
15
  level: LogLevel | CustomLevel;
16
16
  messages?: number[];
17
17
  }
18
- export declare type Options = true | _Options | LogLevel;
18
+ export type Options = true | _Options | LogLevel;
19
19
  export default class Logger {
20
20
  private readonly options;
21
21
  constructor(options?: Options);
@@ -1,7 +1,5 @@
1
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;
2
+ export { default, Type } from '../common/messages.gen.js';
5
3
  export declare function Timestamp(timestamp: number): Messages.Timestamp;
6
4
  export declare function SetPageLocation(url: string, referrer: string, navigationStart: number): Messages.SetPageLocation;
7
5
  export declare function SetViewportSize(width: number, height: number): Messages.SetViewportSize;
@@ -19,11 +17,11 @@ export declare function SetInputTarget(id: number, label: string): Messages.SetI
19
17
  export declare function SetInputValue(id: number, value: string, mask: number): Messages.SetInputValue;
20
18
  export declare function SetInputChecked(id: number, checked: boolean): Messages.SetInputChecked;
21
19
  export declare function MouseMove(x: number, y: number): Messages.MouseMove;
20
+ export declare function NetworkRequest(type: string, method: string, url: string, request: string, response: string, status: number, timestamp: number, duration: number): Messages.NetworkRequest;
22
21
  export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
22
  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
23
  export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
25
- export declare function JSExceptionDeprecated(name: string, message: string, payload: string): Messages.JSExceptionDeprecated;
26
- export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
24
+ export declare function CustomEvent(name: string, payload: string): Messages.CustomEvent;
27
25
  export declare function UserID(id: string): Messages.UserID;
28
26
  export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
29
27
  export declare function Metadata(key: string, value: string): Messages.Metadata;
@@ -39,6 +37,8 @@ export declare function MobX(type: string, payload: string): Messages.MobX;
39
37
  export declare function NgRx(action: string, state: string, duration: number): Messages.NgRx;
40
38
  export declare function GraphQL(operationKind: string, operationName: string, variables: string, response: string): Messages.GraphQL;
41
39
  export declare function PerformanceTrack(frames: number, ticks: number, totalJSHeapSize: number, usedJSHeapSize: number): Messages.PerformanceTrack;
40
+ export declare function StringDict(key: number, value: string): Messages.StringDict;
41
+ export declare function SetNodeAttributeDict(id: number, nameKey: number, valueKey: number): Messages.SetNodeAttributeDict;
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;
@@ -57,5 +57,7 @@ export declare function AdoptedSSInsertRuleURLBased(sheetID: number, rule: strin
57
57
  export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Messages.AdoptedSSDeleteRule;
58
58
  export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
59
59
  export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
60
- export declare function Zustand(mutation: string, state: string): Messages.Zustand;
61
60
  export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
61
+ export declare function Zustand(mutation: string, state: string): Messages.Zustand;
62
+ export declare function BatchMetadata(version: number, pageNo: number, firstIndex: number, timestamp: number, location: string): Messages.BatchMetadata;
63
+ export declare function PartitionedMessage(partNo: number, partTotal: number): Messages.PartitionedMessage;