@openreplay/tracker 3.6.0-beta.0 → 3.6.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.
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 OpenReplay.com <support@openreplay.com>
1
+ Copyright (c) 2022 Asayer, Inc
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -14,6 +14,7 @@ export interface StartOptions {
14
14
  userID?: string;
15
15
  metadata?: Record<string, string>;
16
16
  forceNew?: boolean;
17
+ sessionHash?: string;
17
18
  }
18
19
  interface OnStartInfo {
19
20
  sessionID: string;
@@ -72,14 +73,14 @@ export default class App {
72
73
  private activityState;
73
74
  private readonly version;
74
75
  private readonly worker?;
75
- constructor(projectKey: string, sessionHash: string | undefined, options: Partial<Options>);
76
+ constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>);
76
77
  private _debug;
77
78
  send(message: Message, urgent?: boolean): void;
78
79
  private commit;
79
80
  safe<T extends (...args: any[]) => void>(fn: T): T;
80
81
  attachCommitCallback(cb: CommitCallback): void;
81
- attachStartCallback(cb: StartCallback): void;
82
- attachStopCallback(cb: () => any): void;
82
+ attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
83
+ attachStopCallback(cb: () => any, useSafe?: boolean): void;
83
84
  attachEventListener(target: EventTarget, type: string, listener: EventListener, useSafe?: boolean, useCapture?: boolean): void;
84
85
  checkRequiredVersion(version: string): boolean;
85
86
  private getTrackerInfo;
@@ -93,9 +94,11 @@ export default class App {
93
94
  metadata: Record<string, string>;
94
95
  userID: string | null;
95
96
  timestamp: number;
97
+ projectID?: string | undefined;
96
98
  };
97
99
  getSessionToken(): string | undefined;
98
100
  getSessionID(): string | undefined;
101
+ getSessionURL(): string | undefined;
99
102
  getHost(): string;
100
103
  getProjectKey(): string;
101
104
  getBaseHref(): string;
package/cjs/app/index.js CHANGED
@@ -23,7 +23,7 @@ var ActivityState;
23
23
  // TODO: use backendHost only
24
24
  exports.DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
25
25
  class App {
26
- constructor(projectKey, sessionHash, options) {
26
+ constructor(projectKey, sessionToken, options) {
27
27
  // if (options.onStart !== undefined) {
28
28
  // deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)")
29
29
  // } ?? maybe onStart is good
@@ -32,7 +32,7 @@ class App {
32
32
  this.stopCallbacks = [];
33
33
  this.commitCallbacks = [];
34
34
  this.activityState = ActivityState.NotActive;
35
- this.version = '3.5.16'; // TODO: version compatability check inside each plugin.
35
+ this.version = '3.6.0'; // TODO: version compatability check inside each plugin.
36
36
  this.projectKey = projectKey;
37
37
  this.options = Object.assign({
38
38
  revID: '',
@@ -46,8 +46,8 @@ class App {
46
46
  verbose: false,
47
47
  __is_snippet: false,
48
48
  __debug_report_edp: null,
49
- localStorage: null,
50
- sessionStorage: null,
49
+ localStorage: window === null || window === void 0 ? void 0 : window.localStorage,
50
+ sessionStorage: window === null || window === void 0 ? void 0 : window.sessionStorage,
51
51
  }, options);
52
52
  this.revID = this.options.revID;
53
53
  this.sanitizer = new sanitizer_js_1.default(this, options);
@@ -69,11 +69,12 @@ class App {
69
69
  Object.entries(metadata).forEach(([key, value]) => this.send((0, messages_gen_js_1.Metadata)(key, value)));
70
70
  }
71
71
  });
72
- if (sessionHash != null) {
73
- this.session.applySessionHash(sessionHash);
72
+ // @depricated (use sessionHash on start instead)
73
+ if (sessionToken != null) {
74
+ this.session.applySessionHash(sessionToken);
74
75
  }
75
76
  try {
76
- this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";var t;!function(t){t[t.BatchMetadata=81]="BatchMetadata",t[t.PartitionedMessage=82]="PartitionedMessage",t[t.Timestamp=0]="Timestamp",t[t.SetPageLocation=4]="SetPageLocation",t[t.SetViewportSize=5]="SetViewportSize",t[t.SetViewportScroll=6]="SetViewportScroll",t[t.CreateDocument=7]="CreateDocument",t[t.CreateElementNode=8]="CreateElementNode",t[t.CreateTextNode=9]="CreateTextNode",t[t.MoveNode=10]="MoveNode",t[t.RemoveNode=11]="RemoveNode",t[t.SetNodeAttribute=12]="SetNodeAttribute",t[t.RemoveNodeAttribute=13]="RemoveNodeAttribute",t[t.SetNodeData=14]="SetNodeData",t[t.SetNodeScroll=16]="SetNodeScroll",t[t.SetInputTarget=17]="SetInputTarget",t[t.SetInputValue=18]="SetInputValue",t[t.SetInputChecked=19]="SetInputChecked",t[t.MouseMove=20]="MouseMove",t[t.ConsoleLog=22]="ConsoleLog",t[t.PageLoadTiming=23]="PageLoadTiming",t[t.PageRenderTiming=24]="PageRenderTiming",t[t.JSException=25]="JSException",t[t.RawCustomEvent=27]="RawCustomEvent",t[t.UserID=28]="UserID",t[t.UserAnonymousID=29]="UserAnonymousID",t[t.Metadata=30]="Metadata",t[t.CSSInsertRule=37]="CSSInsertRule",t[t.CSSDeleteRule=38]="CSSDeleteRule",t[t.Fetch=39]="Fetch",t[t.Profiler=40]="Profiler",t[t.OTable=41]="OTable",t[t.StateAction=42]="StateAction",t[t.Redux=44]="Redux",t[t.Vuex=45]="Vuex",t[t.MobX=46]="MobX",t[t.NgRx=47]="NgRx",t[t.GraphQL=48]="GraphQL",t[t.PerformanceTrack=49]="PerformanceTrack",t[t.ResourceTiming=53]="ResourceTiming",t[t.ConnectionInformation=54]="ConnectionInformation",t[t.SetPageVisibility=55]="SetPageVisibility",t[t.LongTask=59]="LongTask",t[t.SetNodeAttributeURLBased=60]="SetNodeAttributeURLBased",t[t.SetCSSDataURLBased=61]="SetCSSDataURLBased",t[t.TechnicalInfo=63]="TechnicalInfo",t[t.CustomIssue=64]="CustomIssue",t[t.CSSInsertRuleURLBased=67]="CSSInsertRuleURLBased",t[t.MouseClick=69]="MouseClick",t[t.CreateIFrameDocument=70]="CreateIFrameDocument",t[t.AdoptedSSReplaceURLBased=71]="AdoptedSSReplaceURLBased",t[t.AdoptedSSInsertRuleURLBased=73]="AdoptedSSInsertRuleURLBased",t[t.AdoptedSSDeleteRule=75]="AdoptedSSDeleteRule",t[t.AdoptedSSAddOwner=76]="AdoptedSSAddOwner",t[t.AdoptedSSRemoveOwner=77]="AdoptedSSRemoveOwner"}(t||(t={}));class e{constructor(t,e,i,s=10,n=1e3){this.onUnauthorised=e,this.onFailure=i,this.MAX_ATTEMPTS_COUNT=s,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(e=>{if(401===e.status)return this.busy=!1,void this.onUnauthorised();if(e.status>=400)return void this.retry(t);this.attemptsCount=0;const i=this.queue.shift();i?this.sendBatch(i):this.busy=!1}).catch(e=>{console.warn("OpenReplay:",e),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const e=t.length,i=new Uint8Array(3*e);let s=-1;for(let n=0,r=0,h=0;h!==e;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===e){i[s+=1]=239,i[s+=1]=191,i[s+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){i[s+=1]=239,i[s+=1]=191,i[s+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){i[s+=1]=240|n>>>18,i[s+=1]=128|n>>>12&63,i[s+=1]=128|n>>>6&63,i[s+=1]=128|63&n;continue}}n<=127?i[s+=1]=0|n:n<=2047?(i[s+=1]=192|n>>>6,i[s+=1]=128|63&n):(i[s+=1]=224|n>>>12,i[s+=1]=128|n>>>6&63,i[s+=1]=128|63&n)}return i.subarray(0,s+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,e){this.data.set(t,e)}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 e=i.encode(t),s=e.byteLength;return!(!this.uint(s)||this.offset+s>this.size)&&(this.data.set(e,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}}{encode(e){switch(e[0]){case t.BatchMetadata:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3])&&this.int(e[4])&&this.string(e[5]);case t.PartitionedMessage:return this.uint(e[1])&&this.uint(e[2]);case t.Timestamp:return this.uint(e[1]);case t.SetPageLocation:return this.string(e[1])&&this.string(e[2])&&this.uint(e[3]);case t.SetViewportSize:return this.uint(e[1])&&this.uint(e[2]);case t.SetViewportScroll:return this.int(e[1])&&this.int(e[2]);case t.CreateDocument:return!0;case t.CreateElementNode:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3])&&this.string(e[4])&&this.boolean(e[5]);case t.CreateTextNode:case t.MoveNode:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3]);case t.RemoveNode:return this.uint(e[1]);case t.SetNodeAttribute:return this.uint(e[1])&&this.string(e[2])&&this.string(e[3]);case t.RemoveNodeAttribute:case t.SetNodeData:return this.uint(e[1])&&this.string(e[2]);case t.SetNodeScroll:return this.uint(e[1])&&this.int(e[2])&&this.int(e[3]);case t.SetInputTarget:return this.uint(e[1])&&this.string(e[2]);case t.SetInputValue:return this.uint(e[1])&&this.string(e[2])&&this.int(e[3]);case t.SetInputChecked:return this.uint(e[1])&&this.boolean(e[2]);case t.MouseMove:return this.uint(e[1])&&this.uint(e[2]);case t.ConsoleLog:return this.string(e[1])&&this.string(e[2]);case t.PageLoadTiming:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3])&&this.uint(e[4])&&this.uint(e[5])&&this.uint(e[6])&&this.uint(e[7])&&this.uint(e[8])&&this.uint(e[9]);case t.PageRenderTiming:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3]);case t.JSException:return this.string(e[1])&&this.string(e[2])&&this.string(e[3]);case t.RawCustomEvent:return this.string(e[1])&&this.string(e[2]);case t.UserID:case t.UserAnonymousID:return this.string(e[1]);case t.Metadata:return this.string(e[1])&&this.string(e[2]);case t.CSSInsertRule:return this.uint(e[1])&&this.string(e[2])&&this.uint(e[3]);case t.CSSDeleteRule:return this.uint(e[1])&&this.uint(e[2]);case t.Fetch:return this.string(e[1])&&this.string(e[2])&&this.string(e[3])&&this.string(e[4])&&this.uint(e[5])&&this.uint(e[6])&&this.uint(e[7]);case t.Profiler:return this.string(e[1])&&this.uint(e[2])&&this.string(e[3])&&this.string(e[4]);case t.OTable:return this.string(e[1])&&this.string(e[2]);case t.StateAction:return this.string(e[1]);case t.Redux:return this.string(e[1])&&this.string(e[2])&&this.uint(e[3]);case t.Vuex:case t.MobX:return this.string(e[1])&&this.string(e[2]);case t.NgRx:return this.string(e[1])&&this.string(e[2])&&this.uint(e[3]);case t.GraphQL:return this.string(e[1])&&this.string(e[2])&&this.string(e[3])&&this.string(e[4]);case t.PerformanceTrack:return this.int(e[1])&&this.int(e[2])&&this.uint(e[3])&&this.uint(e[4]);case t.ResourceTiming:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3])&&this.uint(e[4])&&this.uint(e[5])&&this.uint(e[6])&&this.string(e[7])&&this.string(e[8]);case t.ConnectionInformation:return this.uint(e[1])&&this.string(e[2]);case t.SetPageVisibility:return this.boolean(e[1]);case t.LongTask:return this.uint(e[1])&&this.uint(e[2])&&this.uint(e[3])&&this.uint(e[4])&&this.string(e[5])&&this.string(e[6])&&this.string(e[7]);case t.SetNodeAttributeURLBased:return this.uint(e[1])&&this.string(e[2])&&this.string(e[3])&&this.string(e[4]);case t.SetCSSDataURLBased:return this.uint(e[1])&&this.string(e[2])&&this.string(e[3]);case t.TechnicalInfo:case t.CustomIssue:return this.string(e[1])&&this.string(e[2]);case t.CSSInsertRuleURLBased:return this.uint(e[1])&&this.string(e[2])&&this.uint(e[3])&&this.string(e[4]);case t.MouseClick:return this.uint(e[1])&&this.uint(e[2])&&this.string(e[3])&&this.string(e[4]);case t.CreateIFrameDocument:return this.uint(e[1])&&this.uint(e[2]);case t.AdoptedSSReplaceURLBased:return this.uint(e[1])&&this.string(e[2])&&this.string(e[3]);case t.AdoptedSSInsertRuleURLBased:return this.uint(e[1])&&this.string(e[2])&&this.uint(e[3])&&this.string(e[4]);case t.AdoptedSSDeleteRule:case t.AdoptedSSAddOwner:case t.AdoptedSSRemoveOwner:return this.uint(e[1])&&this.uint(e[2])}}}class n{constructor(t,e,i,n){this.pageNo=t,this.timestamp=e,this.url=i,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,e){for(let e=0;e<3;e++)this.sizeBuffer[e]=t>>8*e;this.encoder.set(this.sizeBuffer,e)}prepare(){if(!this.encoder.isEmpty())return;const e=[t.BatchMetadata,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(e),this.writeFields(e),this.isEmpty=!0}writeWithSize(e){const i=this.encoder;if(!this.writeType(e)||!i.skip(3))return!1;const s=i.getCurrentOffset(),n=this.writeFields(e);if(n){const n=i.getCurrentOffset()-s;if(n>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(n,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&e[0]===t.Timestamp,this.nextIndex++}return n}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(e){if(e[0]===t.Timestamp&&(this.timestamp=e[1]),e[0]===t.SetPageLocation&&(this.url=e[1]),!this.writeWithSize(e))for(this.finaliseBatch();!this.writeWithSize(e);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",e),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 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,a=null;function o(){a&&a.finaliseBatch()}function u(){r.Stopping,null!==d&&(clearInterval(d),d=null),a&&(a.clean(),a=null),r.NotActive}r.NotActive;let c,d=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return o(),void u();if(Array.isArray(i)){if(!a)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const e=a;i.forEach(i=>{i[0]===t.SetPageVisibility&&(i[1]?c=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(c)),e.writeMessage(i)})}else{if("start"===i.type)return r.Starting,h=new e(i.ingestPoint,()=>{self.postMessage("restart")},()=>{h&&(h.clean(),h=null),u(),self.postMessage("failed")},i.connAttemptCount,i.connAttemptGap),a=new n(i.pageNo,i.timestamp,i.url,t=>h&&h.push(t)),null===d&&(d=setInterval(o,1e4)),r.Active;if("auth"===i.type){if(!h)throw new Error("WebWorker: sender not initialised. Received auth.");if(!a)throw new Error("WebWorker: writer not initialised. Received auth.");return h.authorise(i.token),void(i.beaconSizeLimit&&a.setBeaconSizeLimit(i.beaconSizeLimit))}}}else o()};'], { type: 'text/javascript' })));
77
+ 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])}}}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' })));
77
78
  this.worker.onerror = (e) => {
78
79
  this._debug('webworker_error', e);
79
80
  };
@@ -152,20 +153,28 @@ class App {
152
153
  }; // TODO: correct typing
153
154
  }
154
155
  attachCommitCallback(cb) {
156
+ // TODO!: what if start callback added when activityState === Active ?
157
+ // For example - attachEventListener() called during dynamic <iframe> appearance
155
158
  this.commitCallbacks.push(cb);
156
159
  }
157
- attachStartCallback(cb) {
160
+ attachStartCallback(cb, useSafe = false) {
161
+ if (useSafe) {
162
+ cb = this.safe(cb);
163
+ }
158
164
  this.startCallbacks.push(cb);
159
165
  }
160
- attachStopCallback(cb) {
166
+ attachStopCallback(cb, useSafe = false) {
167
+ if (useSafe) {
168
+ cb = this.safe(cb);
169
+ }
161
170
  this.stopCallbacks.push(cb);
162
171
  }
163
172
  attachEventListener(target, type, listener, useSafe = true, useCapture = true) {
164
173
  if (useSafe) {
165
174
  listener = this.safe(listener);
166
175
  }
167
- this.attachStartCallback(() => target.addEventListener(type, listener, useCapture));
168
- this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture));
176
+ this.attachStartCallback(() => target.addEventListener(type, listener, useCapture), useSafe);
177
+ this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture), useSafe);
169
178
  }
170
179
  // TODO: full correct semantic
171
180
  checkRequiredVersion(version) {
@@ -202,6 +211,14 @@ class App {
202
211
  getSessionID() {
203
212
  return this.session.getInfo().sessionID || undefined;
204
213
  }
214
+ getSessionURL() {
215
+ const { projectID, sessionID } = this.session.getInfo();
216
+ if (!projectID || !sessionID) {
217
+ this.debug.error('OpenReplay error: Unable to build session URL');
218
+ return undefined;
219
+ }
220
+ return this.options.ingestPoint.replace(/\/ingest$/, `${projectID}/session/${sessionID}`);
221
+ }
205
222
  getHost() {
206
223
  return new URL(this.options.ingestPoint).hostname;
207
224
  }
@@ -251,6 +268,9 @@ class App {
251
268
  return Promise.resolve(UnsuccessfulStart('OpenReplay: trying to call `start()` on the instance that has been started already.'));
252
269
  }
253
270
  this.activityState = ActivityState.Starting;
271
+ if (startOpts.sessionHash) {
272
+ this.session.applySessionHash(startOpts.sessionHash);
273
+ }
254
274
  const timestamp = (0, utils_js_1.timestamp)();
255
275
  const startWorkerMsg = {
256
276
  type: 'start',
@@ -296,7 +316,7 @@ class App {
296
316
  if (!this.worker) {
297
317
  return Promise.reject('no worker found after start request (this might not happen)');
298
318
  }
299
- const { token, userUUID, sessionID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
319
+ const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
300
320
  } = r;
301
321
  if (typeof token !== 'string' ||
302
322
  typeof userUUID !== 'string' ||
@@ -307,18 +327,18 @@ class App {
307
327
  }
308
328
  this.session.setSessionToken(token);
309
329
  this.localStorage.setItem(this.options.local_uuid_key, userUUID);
310
- this.session.update({ sessionID, timestamp: startTimestamp || timestamp }); // TODO: no no-explicit 'any'
330
+ this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
311
331
  const startWorkerMsg = {
312
332
  type: 'auth',
313
333
  token,
314
334
  beaconSizeLimit,
315
335
  };
316
336
  this.worker.postMessage(startWorkerMsg);
317
- this.activityState = ActivityState.Active;
318
337
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
319
338
  this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
320
339
  this.observer.observe();
321
340
  this.ticker.start();
341
+ this.activityState = ActivityState.Active;
322
342
  this.notify.log('OpenReplay tracking started.');
323
343
  // get rid of onStart ?
324
344
  if (typeof this.options.onStart === 'function') {