UNPKG

@gojek/clickstream-web

Version:

A Modern, Fast, and Lightweight Event Ingestion library for Web

2 lines (1 loc) 26.1 kB
"use strict";function e(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var i=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,i.get?i:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("protobufjs/minimal.js"));function n(e,t){return function(e,t){if(t.get)return t.get.call(e);return t.value}(e,s(e,t,"get"))}function i(e,t,n){return function(e,t,n){if(t.set)t.set.call(e,n);else{if(!t.writable)throw new TypeError("attempted to set read only private field");t.value=n}}(e,s(e,t,"set"),n),n}function s(e,t,n){if(!t.has(e))throw new TypeError("attempted to "+n+" private field on non-instance");return t.get(e)}function r(e,t,n){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return n}function o(e,t){if(t.has(e))throw new TypeError("Cannot initialize the same private elements twice on an object")}function a(e,t,n){o(e,t),t.set(e,n)}function c(e,t){o(e,t),t.add(e)}const u={event:{classification:{instant:[]},group:""},batch:{maxTimeBetweenTwoBatches:10,maxBatchSize:5e4,dbName:"clickstream_db"},network:{url:"",headers:new Headers({}),maxRetries:5,timeBetweenTwoRetries:1e3,timeToResumeRetries:2e4},crypto:null},h="instant",l="realTime",d="batchCreated",p="batchFailed",w={CLICKSTREAM_ERROR:"clickstreamError",VALIDATION_ERROR:"validationError",DATABASE_ERROR:"databaseError",NETWORK_ERROR:"networkError",TRACKING_ERROR:"trackingError",CLEANUP_ERROR:"cleanupError"},f="Clickstream Error",v="Validation Error",g="Database Error",b="Network Error",m="Cleanup Error";class y extends Error{constructor(e,t){super(e,t),this.name=t?.name??f,this.code=t?.code??w.CLICKSTREAM_ERROR}}class k extends y{constructor(e,t){super(e,t),this.name=v,this.code=w.VALIDATION_ERROR}}class S extends y{constructor(e,t){super(e,t),this.name=g,this.code=w.DATABASE_ERROR}}class T extends y{constructor(e,t){super(e,t),this.name=b,this.code=w.NETWORK_ERROR}}let O;t.default&&(O=t.default);const R=O.Reader,E=O.Writer,B=O.util,j=O.roots.default||(O.roots.default={});j.EventService=(()=>{function e(e,t,n){O.rpc.Service.call(this,e,t,n)}return(e.prototype=Object.create(O.rpc.Service.prototype)).constructor=e,e.create=function(e,t,n){return new this(e,t,n)},Object.defineProperty(e.prototype.sendEvent=function e(t,n){return this.rpcCall(e,j.SendEventRequest,j.SendEventResponse,t,n)},"name",{value:"SendEvent"}),e})();const P=j.SendEventRequest=(()=>{function e(e){if(this.events=[],e)for(let t=Object.keys(e),n=0;n<t.length;++n)null!=e[t[n]]&&(this[t[n]]=e[t[n]])}return e.prototype.reqGuid="",e.prototype.sentTime=null,e.prototype.events=B.emptyArray,e.create=function(t){return new e(t)},e.encode=function(e,t){if(t||(t=E.create()),null!=e.reqGuid&&Object.hasOwnProperty.call(e,"reqGuid")&&t.uint32(10).string(e.reqGuid),null!=e.sentTime&&Object.hasOwnProperty.call(e,"sentTime")&&j.Timestamp.encode(e.sentTime,t.uint32(18).fork()).ldelim(),null!=e.events&&e.events.length)for(let n=0;n<e.events.length;++n)j.Event.encode(e.events[n],t.uint32(26).fork()).ldelim();return t},e.decode=function(e,t){e instanceof R||(e=R.create(e));let n=void 0===t?e.len:e.pos+t,i=new j.SendEventRequest;for(;e.pos<n;){let t=e.uint32();switch(t>>>3){case 1:i.reqGuid=e.string();break;case 2:i.sentTime=j.Timestamp.decode(e,e.uint32());break;case 3:i.events&&i.events.length||(i.events=[]),i.events.push(j.Event.decode(e,e.uint32()));break;default:e.skipType(7&t)}}return i},e.verify=function(e){if("object"!=typeof e||null===e)return"object expected";if(null!=e.reqGuid&&e.hasOwnProperty("reqGuid")&&!B.isString(e.reqGuid))return"reqGuid: string expected";if(null!=e.sentTime&&e.hasOwnProperty("sentTime")){let t=j.Timestamp.verify(e.sentTime);if(t)return"sentTime."+t}if(null!=e.events&&e.hasOwnProperty("events")){if(!Array.isArray(e.events))return"events: array expected";for(let t=0;t<e.events.length;++t){let n=j.Event.verify(e.events[t]);if(n)return"events."+n}}return null},e.getTypeUrl=function(e){return void 0===e&&(e="type.googleapis.com"),e+"/SendEventRequest"},e})();j.Timestamp=(()=>{function e(e){if(e)for(let t=Object.keys(e),n=0;n<t.length;++n)null!=e[t[n]]&&(this[t[n]]=e[t[n]])}return e.prototype.seconds=B.Long?B.Long.fromBits(0,0,!1):0,e.prototype.nanos=0,e.create=function(t){return new e(t)},e.encode=function(e,t){return t||(t=E.create()),null!=e.seconds&&Object.hasOwnProperty.call(e,"seconds")&&t.uint32(8).int64(e.seconds),null!=e.nanos&&Object.hasOwnProperty.call(e,"nanos")&&t.uint32(16).int32(e.nanos),t},e.decode=function(e,t){e instanceof R||(e=R.create(e));let n=void 0===t?e.len:e.pos+t,i=new j.Timestamp;for(;e.pos<n;){let t=e.uint32();switch(t>>>3){case 1:i.seconds=e.int64();break;case 2:i.nanos=e.int32();break;default:e.skipType(7&t)}}return i},e.verify=function(e){return"object"!=typeof e||null===e?"object expected":null!=e.seconds&&e.hasOwnProperty("seconds")&&!(B.isInteger(e.seconds)||e.seconds&&B.isInteger(e.seconds.low)&&B.isInteger(e.seconds.high))?"seconds: integer|Long expected":null!=e.nanos&&e.hasOwnProperty("nanos")&&!B.isInteger(e.nanos)?"nanos: integer expected":null},e.getTypeUrl=function(e){return void 0===e&&(e="type.googleapis.com"),e+"/Timestamp"},e})();const W=j.Event=(()=>{function e(e){if(e)for(let t=Object.keys(e),n=0;n<t.length;++n)null!=e[t[n]]&&(this[t[n]]=e[t[n]])}return e.prototype.eventBytes=B.newBuffer([]),e.prototype.type="",e.create=function(t){return new e(t)},e.encode=function(e,t){return t||(t=E.create()),null!=e.eventBytes&&Object.hasOwnProperty.call(e,"eventBytes")&&t.uint32(10).bytes(e.eventBytes),null!=e.type&&Object.hasOwnProperty.call(e,"type")&&t.uint32(18).string(e.type),t},e.decode=function(e,t){e instanceof R||(e=R.create(e));let n=void 0===t?e.len:e.pos+t,i=new j.Event;for(;e.pos<n;){let t=e.uint32();switch(t>>>3){case 1:i.eventBytes=e.bytes();break;case 2:i.type=e.string();break;default:e.skipType(7&t)}}return i},e.verify=function(e){return"object"!=typeof e||null===e?"object expected":null!=e.eventBytes&&e.hasOwnProperty("eventBytes")&&!(e.eventBytes&&"number"==typeof e.eventBytes.length||B.isString(e.eventBytes))?"eventBytes: buffer expected":null!=e.type&&e.hasOwnProperty("type")&&!B.isString(e.type)?"type: string expected":null},e.getTypeUrl=function(e){return void 0===e&&(e="type.googleapis.com"),e+"/Event"},e})(),x=j.SendEventResponse=(()=>{function e(e){if(this.data={},e)for(let t=Object.keys(e),n=0;n<t.length;++n)null!=e[t[n]]&&(this[t[n]]=e[t[n]])}return e.prototype.status=0,e.prototype.code=0,e.prototype.sentTime=B.Long?B.Long.fromBits(0,0,!1):0,e.prototype.reason="",e.prototype.data=B.emptyObject,e.create=function(t){return new e(t)},e.encode=function(e,t){if(t||(t=E.create()),null!=e.status&&Object.hasOwnProperty.call(e,"status")&&t.uint32(8).int32(e.status),null!=e.code&&Object.hasOwnProperty.call(e,"code")&&t.uint32(16).int32(e.code),null!=e.sentTime&&Object.hasOwnProperty.call(e,"sentTime")&&t.uint32(24).int64(e.sentTime),null!=e.reason&&Object.hasOwnProperty.call(e,"reason")&&t.uint32(34).string(e.reason),null!=e.data&&Object.hasOwnProperty.call(e,"data"))for(let n=Object.keys(e.data),i=0;i<n.length;++i)t.uint32(42).fork().uint32(10).string(n[i]).uint32(18).string(e.data[n[i]]).ldelim();return t},e.decode=function(e,t){e instanceof R||(e=R.create(e));let n,i,s=void 0===t?e.len:e.pos+t,r=new j.SendEventResponse;for(;e.pos<s;){let t=e.uint32();switch(t>>>3){case 1:r.status=e.int32();break;case 2:r.code=e.int32();break;case 3:r.sentTime=e.int64();break;case 4:r.reason=e.string();break;case 5:{r.data===B.emptyObject&&(r.data={});let t=e.uint32()+e.pos;for(n="",i="";e.pos<t;){let t=e.uint32();switch(t>>>3){case 1:n=e.string();break;case 2:i=e.string();break;default:e.skipType(7&t)}}r.data[n]=i;break}default:e.skipType(7&t)}}return r},e.verify=function(e){if("object"!=typeof e||null===e)return"object expected";if(null!=e.status&&e.hasOwnProperty("status"))switch(e.status){default:return"status: enum value expected";case 0:case 1:case 2:}if(null!=e.code&&e.hasOwnProperty("code"))switch(e.code){default:return"code: enum value expected";case 0:case 1:case 2:case 3:case 4:case 5:}if(null!=e.sentTime&&e.hasOwnProperty("sentTime")&&!(B.isInteger(e.sentTime)||e.sentTime&&B.isInteger(e.sentTime.low)&&B.isInteger(e.sentTime.high)))return"sentTime: integer|Long expected";if(null!=e.reason&&e.hasOwnProperty("reason")&&!B.isString(e.reason))return"reason: string expected";if(null!=e.data&&e.hasOwnProperty("data")){if(!B.isObject(e.data))return"data: object expected";let t=Object.keys(e.data);for(let n=0;n<t.length;++n)if(!B.isString(e.data[t[n]]))return"data: string{k:string} expected"}return null},e.getTypeUrl=function(e){return void 0===e&&(e="type.googleapis.com"),e+"/SendEventResponse"},e})();j.Status=(()=>{const e={},t=Object.create(e);return t[e[0]="STATUS_UNSPECIFIED"]=0,t[e[1]="STATUS_SUCCESS"]=1,t[e[2]="STATUS_ERROR"]=2,t})(),j.Code=(()=>{const e={},t=Object.create(e);return t[e[0]="CODE_UNSPECIFIED"]=0,t[e[1]="CODE_OK"]=1,t[e[2]="CODE_BAD_REQUEST"]=2,t[e[3]="CODE_INTERNAL_ERROR"]=3,t[e[4]="CODE_MAX_CONNECTION_LIMIT_REACHED"]=4,t[e[5]="CODE_MAX_USER_LIMIT_REACHED"]=5,t})();let A=!1;function M(e,t){return e?[e,...t]:t}const G={info:function(e="",...t){A&&console.log(...M(e,t))},debug:function(e="",...t){A&&console.debug(...M(e,t))},warn:function(e="",...t){A&&console.warn(...M(e,t))},error:function(e="",...t){console.error(...M(e,t))},get logging(){return A},set logging(e){A=Boolean(e)}};var q=new WeakMap,N=new WeakMap,_=new WeakMap,C=new WeakMap,I=new WeakMap,D=new WeakMap,L=new WeakSet,z=new WeakSet,U=new WeakSet;class Q{constructor({config:e,eventBus:t,store:n,id:s}){c(this,U),c(this,z),c(this,L),a(this,q,{writable:!0,value:void 0}),a(this,N,{writable:!0,value:void 0}),a(this,_,{writable:!0,value:void 0}),a(this,C,{writable:!0,value:void 0}),a(this,I,{writable:!0,value:0}),a(this,D,{writable:!0,value:void 0}),i(this,q,e),i(this,_,t),i(this,N,n),i(this,I,0),i(this,D,void 0),i(this,C,s)}async send(e,{retry:t=!1}={}){const n=r(this,L,$).call(this,e);r(this,U,K).call(this,n,{retry:t})}}function $(e){const t=n(this,C).uuidv4(),{seconds:i}=(()=>{const e=new Date;return{seconds:Math.floor(e.getTime()/1e3)}})();G.info("Network:","generated reqGuid",t),G.info("Network:","generated timestamp(seconds)",i);const s=e.filter((e=>e.eventType===l));s.length&&n(this,N).isOpen&&(n(this,N).update(s,"reqGuid",t),G.info("Network:","updated reqGuid for all events in store"));const r=e.map((e=>{const{data:t,type:n}=e;return W.create({eventBytes:t,type:n})})),o=P.create({reqGuid:t,sentTime:{seconds:i},events:[...r]});return G.debug("Network:","network request",o),{reqGuid:t,body:P.encode(o).finish()}}function H(e){const{maxRetries:t,timeBetweenTwoRetries:s,timeToResumeRetries:o}=n(this,q);n(this,I)<t?(n(this,D)&&(window.clearTimeout(n(this,D)),i(this,D,void 0)),i(this,I,n(this,I)+1),G.debug("Network:","retry",n(this,I)),window.setTimeout((()=>{n(this,_).emit(p,{reqGuid:e.reqGuid})}),s)):n(this,I)===t&&void 0===n(this,D)&&(G.debug("Network:","waiting for",o),i(this,D,window.setTimeout((()=>{i(this,I,0),r(this,z,H).call(this,e)}),o)))}async function K(e,{retry:t}){const i=new Headers(n(this,q).headers);i.append("Content-Type","application/proto");try{const s=await fetch(n(this,q).url,{method:"POST",headers:i,body:e.body});if(!s.ok)return G.error("Network:",new T(`Network request to raccoon failed with status code ${s.status}`)),void(t&&r(this,z,H).call(this,e));if(G.info("Network:","received response from raccoon "),n(this,N).isOpen()){const e=await s.blob(),t=await(async e=>e.arrayBuffer?e.arrayBuffer():new Promise(((t,n)=>{const i=new FileReader;i.onloadend=()=>{2===i.readyState&&t(i.result)},i.onerror=e=>n(e),i.readAsArrayBuffer(e)})))(e),i=new Uint8Array(t),r=x.decode(i);G.debug("Network:","response data from Raccoon",r,JSON.stringify(r,void 0,2));const o=await n(this,N).readByReqGuid(r.data.req_guid);n(this,N).remove(o),G.debug("remove events from store with reqGuid",r.data.req_guid)}}catch(n){G.error("Network:",new T(n.message,{cause:n})),t&&r(this,z,H).call(this,e)}}var F=new WeakMap,V=new WeakMap,X=new WeakMap,J=new WeakMap,Y=new WeakSet,Z=new WeakSet;class ee{constructor({config:e,store:t,id:n,isRealTimeEventsSupported:s}){c(this,Z),c(this,Y),a(this,F,{writable:!0,value:void 0}),a(this,V,{writable:!0,value:void 0}),a(this,X,{writable:!0,value:void 0}),a(this,J,{writable:!0,value:void 0}),i(this,F,e),i(this,V,t),i(this,X,n),i(this,J,s)}process(e){const t=r(this,Y,te).call(this,e);return{type:t,event:r(this,Z,ne).call(this,e,t)}}}function te(e){return n(this,J)?n(this,V).isOpen()?n(this,F)?.classification?.instant?.includes(e.eventName)?(G.info("Processor:",`"${e.eventName}" event is classified as QoS0 as per configuration`),h):(G.info("Processor:",`"${e.eventName}" event is considered as QoS1 by default configuration`),l):(G.info("Processor:",`treating "${e.eventName}" event as QoS0 as indexedDB is not supported`),h):(G.info("Processor:",`treating "${e.eventName}" event as QoS0 as QoS1 events are not supported`),h)}function ne(e,t){const i=e.constructor,s=i.encode(e).finish();try{if(i.decode){const e=i.decode(s);G.debug("Processor:","decoded event payload",e)}}catch(e){G.debug("Processor:","event decoding failed",e)}const r=i.getTypeUrl("").split("."),o=r[r.length-1].toLowerCase(),a=n(this,F).group?`${n(this,F).group}-${o}`:o;G.info("Processor:","topic name is set to",a);const c={data:s,eventType:t,type:a};return t===l&&(c.eventGuid=n(this,X).uuidv4(),c.reqGuid=""),G.info("Processor:","created a new event"),G.debug("Processor:","new event data",c),c}var ie=new WeakMap,se=new WeakMap,re=new WeakMap,oe=new WeakMap,ae=new WeakMap,ce=new WeakMap,ue=new WeakMap,he=new WeakMap,le=new WeakSet,de=new WeakSet,pe=new WeakSet,we=new WeakSet,fe=new WeakSet,ve=new WeakSet,ge=new WeakSet,be=new WeakSet,me=new WeakSet,ye=new WeakSet;class ke{constructor({config:e,eventBus:t,store:n}){c(this,ye),c(this,me),c(this,be),c(this,ge),c(this,ve),c(this,fe),c(this,we),c(this,pe),c(this,de),c(this,le),a(this,ie,{writable:!0,value:void 0}),a(this,se,{writable:!0,value:void 0}),a(this,re,{writable:!0,value:void 0}),a(this,oe,{writable:!0,value:void 0}),a(this,ae,{writable:!0,value:void 0}),a(this,ce,{writable:!0,value:void 0}),a(this,ue,{writable:!0,value:void 0}),a(this,he,{writable:!0,value:void 0}),i(this,oe,e),i(this,ae,t),i(this,ce,n),i(this,ie,void 0),i(this,se,0),i(this,re,!1),i(this,ue,[]),i(this,he,[])}isRunning(){return n(this,re)}start(){i(this,re,!0),r(this,ye,xe).call(this),r(this,we,Re).call(this)}stop(){r(this,de,Te).call(this),i(this,se,0),i(this,re,!1)}pause(){i(this,re,!1)}resume(){i(this,re,!0)}async free(){try{this.stop(),G.info("Scheduler:","scheduler is stopped"),G.info("Scheduler:","flushing all events"),n(this,ce).isOpen()&&await r(this,le,Se).call(this),r(this,fe,Ee).call(this)}catch(e){return Promise.reject(e)}}}async function Se(){let e=await n(this,ce).read();e=e.filter((e=>![...n(this,ue),...n(this,he)].some((t=>t.eventGuid===e.eventGuid)))),G.debug("Scheduler:","flushed events",e),n(this,ue).push(...e),r(this,pe,Oe).call(this)}function Te(){void 0!==n(this,ie)&&(clearInterval(n(this,ie)),i(this,ie,void 0))}function Oe(){n(this,ue).length&&n(this,ae).emit(d,{batch:n(this,ue)}),i(this,se,0),i(this,he,n(this,ue)),i(this,ue,[])}function Re(){n(this,ae)?.on(p,(async e=>{G.debug("Scheduler:","batch failed with reqGuid",e.detail.reqGuid);const t=await n(this,ce).readByReqGuid(e.detail.reqGuid);n(this,ae).emit(d,{batch:t})})),G.info("Scheduler:",'added "BATCH_FAILED" listener')}function Ee(){n(this,ae)?.remove(p),G.info("Scheduler:",'removed "BATCH_FAILED" listener')}function Be(e){return e.reduce(((e,t)=>e+new Blob(t?.data).size),0)}function je(e){const t=r(this,ve,Be).call(this,[e[0]]),i=r(this,ve,Be).call(this,n(this,ue)),s=n(this,oe).maxBatchSize-i;return G.debug("Scheduler:","current batch size",i),G.debug("Scheduler:","max batch size",n(this,oe).maxBatchSize),G.debug("Scheduler:","remaining batch size",s),e.splice(0,Math.ceil(s/t)+1)}async function Pe(){if(!n(this,ce).isOpen())return G.debug("Scheduler:","store is not open"),[];try{let e=await n(this,ce).read();if(e=e.filter((e=>![...n(this,ue),...n(this,he)].some((t=>t.eventGuid===e.eventGuid)))),!e.length)return G.debug("no new QoS1 events are found"),[];const t=r(this,ge,je).call(this,e);return G.debug("Scheduler:","events before splitting by size",e,e.length),G.debug("Scheduler:","events after splitting by size",t,t.length),t}catch(e){return G.error("Scheduler:",e),[]}}async function We(){const e=await r(this,be,Pe).call(this);G.debug("Scheduler:","QoS1 events",e),e.length&&(n(this,ue).push(...e),G.debug("Scheduler:","QoS1 events pushed in batch",n(this,ue)))}function xe(){r(this,de,Te).call(this),i(this,ie,setInterval((()=>{if(!n(this,re))return void G.debug("Scheduler:","batching is not running");i(this,se,n(this,se)+1),r(this,me,We).call(this);const e=r(this,ve,Be).call(this,n(this,ue));e>=n(this,oe).maxBatchSize?(r(this,pe,Oe).call(this),G.info("Scheduler:","this batch of size",e,"batch has reached max size threshold of",n(this,oe).maxBatchSize)):n(this,se)>=n(this,oe).maxTimeBetweenTwoBatches&&(r(this,pe,Oe).call(this),G.info("Scheduler:","batch has waited max time of",n(this,oe).maxTimeBetweenTwoBatches))}),1e3))}class Ae{constructor(){this.eventTarget=new EventTarget}emit(e,t){const n=new CustomEvent(e,{detail:t});this.eventTarget.dispatchEvent(n)}on(e,t){this.eventTarget.addEventListener(e,t)}remove(e,t){this.eventTarget.removeEventListener(e,t)}}const Me="events";var Ge=new WeakMap,qe=new WeakMap,Ne=new WeakMap,_e=new WeakMap;class Ce{constructor({name:e="clickstream_db",version:t=1}){a(this,Ge,{writable:!0,value:void 0}),a(this,qe,{writable:!0,value:void 0}),a(this,Ne,{writable:!0,value:void 0}),a(this,_e,{writable:!0,value:void 0}),i(this,Ge,e),i(this,qe,t),i(this,_e,!1)}isOpen(){return n(this,_e)}open(){return new Promise(((e,t)=>{const s=window.indexedDB.open(n(this,Ge),n(this,qe));s.onblocked=e=>{G.info("Store:","please close all other tabs with this site open"),t(e.target.error)},s.onerror=e=>{t(e.target.error)},s.onsuccess=t=>{i(this,Ne,t.target.result),i(this,_e,!0),e("success"),G.info("Store:","store is open with name",n(this,Ge)),n(this,Ne).addEventListener("close",(()=>{G.info("Store:","database connection is closed")}))},s.onupgradeneeded=e=>{if(i(this,Ne,e.target.result),0===e.oldVersion){const e=n(this,Ne).createObjectStore(Me,{keyPath:"eventGuid"});e.createIndex("reqGuid","reqGuid",{unique:!1}),e.createIndex("eventGuid","eventGuid",{unique:!0})}n(this,Ne).onversionchange=e=>{n(this,Ne).close(),i(this,_e,!1),G.info("Store:","a new version of this page is ready, please reload or close this tab"),t(e.target.error)}}}))}read(){return new Promise(((e,t)=>{try{const i=n(this,Ne).transaction(Me).objectStore(Me);i.getAll().onsuccess=t=>{e(t.target.result)},i.getAll().onerror=e=>{t(e.target.error)}}catch(e){i(this,_e,!1),G.error("Store:",new S(e.message,{cause:e}))}}))}readByReqGuid(e){return new Promise((t=>{const s=[];try{const i=n(this,Ne).transaction([Me],"readwrite").objectStore(Me);i.index("reqGuid").openCursor().onsuccess=n=>{try{const i=n.target.result;i?(i.value.reqGuid===e&&s.push(i.value),i.continue()):t(s)}catch(e){G.error("Store:",new S(e.message,{cause:e}))}}}catch(e){i(this,_e,!1),G.error("Store:",new S(e.message,{cause:e}))}}))}write(e){return new Promise(((t,s)=>{Array.isArray(e)||(e=[e]);try{const i=n(this,Ne).transaction([Me],"readwrite"),r=i.objectStore(Me);i.oncomplete=()=>{t("success")},i.onerror=e=>{s(e.target.error)};try{e.forEach((e=>{r.add(e)}))}catch(e){G.error("Store:",new S(e.message,{cause:e}))}}catch(e){i(this,_e,!1),G.error("Store:",new S(e.message,{cause:e}))}}))}update(e,t,s){try{const i=n(this,Ne).transaction([Me],"readwrite").objectStore(Me);try{e.forEach((e=>{e[t]=s,i.put(e)}))}catch(e){G.error("Store:",new S(e.message,{cause:e}))}}catch(e){i(this,_e,!1),G.error("Store:",new S(e.message,{cause:e}))}}remove(e){return new Promise(((t,s)=>{try{const i=n(this,Ne).transaction([Me],"readwrite"),r=i.objectStore(Me);i.oncomplete=()=>{t("success")},i.onerror=e=>{s(e.target.error)};try{e.forEach((e=>{r.delete(e.eventGuid)}))}catch(e){G.error("Store:",new S(e.message,{cause:e}))}}catch(e){i(this,_e,!1),G.error("Store:",new S(e.message,{cause:e}))}}))}delete(){return new Promise(((e,t)=>{let s=window.indexedDB.deleteDatabase(n(this,Ge));s.onerror=e=>{t(e.target.error)},s.onsuccess=t=>{i(this,Ne,null),i(this,_e,!1),e(t.target.result)}}))}}var Ie=new WeakMap;class De{constructor({crypto:e}){a(this,Ie,{writable:!0,value:void 0}),i(this,Ie,e||crypto)}uuidv4(){return"10000000-1000-4000-8000-100000000000".replace(/[018]/g,(e=>(e^n(this,Ie).getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16)))}}const Le=e=>Number.isInteger(e)&&e>0,ze=e=>"string"==typeof e,Ue=e=>void 0!==e;class Qe{validate(e,t,n,i){if(!n?.url)throw new k("provide url in network config");if(Ue(n.url)&&!ze(n.url)&&!(n.url instanceof URL))throw new k("network url must be of type string or instance of URL");if(!n?.headers)throw new k('provide "Authorization" header in network config');if(Ue(n.headers)&&!(n.headers instanceof Headers))throw new k("network headers must be instance of Headers");if(!n.headers.get("Authorization"))throw new k('provide "Authorization" header in network config');if(Ue(n.timeBetweenTwoRetries)&&!Le(n.timeBetweenTwoRetries))throw new k('"timeBetweenTwoRetries" must be a positive integer');if(Ue(n.timeToResumeRetries)&&!Le(n.timeToResumeRetries))throw new k('"timeToResumeRetries" must be a positive integer');if(Ue(e?.classification?.instant)){if(e.classification.instant.some((e=>!ze(e))))throw new k('"instant" event names must be of type string')}if(Ue(e?.group)&&!ze(e.group))throw new k('"group" name must be of type string');if(Ue(t?.maxTimeBetweenTwoBatches)&&!Le(t.maxTimeBetweenTwoBatches))throw new k("maxTimeBetweenTwoBatches must be a positive integer");if(Ue(t?.maxBatchSize)&&!Le(t.maxBatchSize))throw new k('"maxBatchSize" must be a positive integer');if(Ue(t?.dbName)&&!ze(t.dbName))throw new k('"dbName" name must be of type string');if(Ue(i)&&"object"!=typeof i)throw new k('"crypto" must be of type object')}}const $e="Cickstream:",He="browser",Ke="node",Fe="unknown",Ve=async()=>{const e="object"==typeof globalThis.process?Ke:void 0!==globalThis.window?He:Fe;if(G.debug($e,"runtime detected:",e),e===He){const{vendor:e,userAgent:t,platform:n}=globalThis.navigator;G.debug($e,"url:",document?.location.href??null),G.debug($e,"platform:",n),G.debug($e,"vendor:",e),G.debug($e,"userAgent:",t)}else e===Ke&&G.debug($e,`node version: ${globalThis.process.version}`)},Xe=()=>void 0!==globalThis.indexedDB&&void 0!==globalThis.EventTarget;var Je=new WeakMap,Ye=new WeakMap,Ze=new WeakMap,et=new WeakMap,tt=new WeakMap,nt=new WeakMap,it=new WeakMap,st=new WeakMap,rt=new WeakMap,ot=new WeakMap,at=new WeakMap,ct=new WeakSet,ut=new WeakSet;function ht(){n(this,at)&&(r(this,ut,lt).call(this),n(this,Ze).start(),G.info($e,"scheduler is up and running"))}function lt(){n(this,it)?.on(d,(e=>{G.info($e,"new batch created"),G.debug($e,"new batch data",e.detail.batch),n(this,et).send(e.detail.batch,{retry:!0})}))}exports.Clickstream=class{constructor({event:e,batch:t,network:s,crypto:o,debug:h}){c(this,ut),c(this,ct),a(this,Je,{writable:!0,value:void 0}),a(this,Ye,{writable:!0,value:void 0}),a(this,Ze,{writable:!0,value:void 0}),a(this,et,{writable:!0,value:void 0}),a(this,tt,{writable:!0,value:void 0}),a(this,nt,{writable:!0,value:void 0}),a(this,it,{writable:!0,value:void 0}),a(this,st,{writable:!0,value:void 0}),a(this,rt,{writable:!0,value:void 0}),a(this,ot,{writable:!0,value:void 0}),a(this,at,{writable:!0,value:void 0}),h&&(G.logging=h,G.info($e,"logging is set to",G.logging)),Ve(),G.info($e,"configuration received"),G.debug($e,"event configuration received",e),G.debug($e,"batch configuration received",t),G.debug($e,"network configuration received",s),G.debug($e,"crypto configuration received",o),(new Qe).validate(e,t,s,o),G.info($e,"configuration validation is successful"),i(this,at,Xe()),G.info($e,`QoS1 events are ${n(this,at)?"":"not"} supported`),i(this,st,Object.assign(u.event,e)),i(this,rt,Object.assign(u.batch,t)),i(this,ot,Object.assign(u.network,s)),G.info($e,"configuration merged with default configuration"),G.debug($e,"event configuration",n(this,st)),G.debug($e,"batch configuration",n(this,rt)),G.debug($e,"network configuration",n(this,ot)),G.debug($e,"crypto configuration",o),i(this,Je,!0),i(this,tt,new Ce({name:n(this,rt).dbName})),n(this,at)&&i(this,it,new Ae),i(this,nt,new De({crypto:o})),i(this,Ye,new ee({config:n(this,st),store:n(this,tt),id:n(this,nt),isRealTimeEventsSupported:Xe})),i(this,Ze,new ke({config:n(this,rt),eventBus:n(this,it),store:n(this,tt)})),i(this,et,new Q({config:n(this,ot),eventBus:n(this,it),store:n(this,tt),id:n(this,nt)})),r(this,ct,ht).call(this)}async track(e){if(!n(this,Je))return Promise.reject(new y("Tracking is paused, call .resume() method to resume tracking",{code:w.TRACKING_ERROR}));if(n(this,at)&&!n(this,Ze).isRunning()&&(n(this,Ze).start(),G.info($e,"restarted scheduler")),n(this,at)&&!n(this,tt)?.isOpen())try{await n(this,tt).open()}catch(e){return Promise.reject(new S(e.message,{cause:e}))}const{type:t,event:i}=n(this,Ye).process(e);G.info($e,"event type is set to",t);try{t===l?(await n(this,tt).write(i),G.info($e,"event is stored in the store with eventGuid",i.eventGuid)):t===h&&(G.info($e,"event is sent to transport layer"),n(this,et).send([i]))}catch(e){return Promise.reject(new y(e.message,{cause:e}))}}pause(){i(this,Je,!1),G.info($e,"tracking is set to",n(this,Je))}resume(){i(this,Je,!0),G.info($e,"tracking is set to",n(this,Je))}async free(){try{await n(this,Ze).free(),G.info($e,"scheduler resources are released"),n(this,tt).isOpen()&&(await n(this,tt).delete(),G.info($e,"store is deleted")),G.info($e,"cleanup is done")}catch(e){return Promise.reject(new y(e.message,{name:m,code:w.CLEANUP_ERROR}))}}},exports.errorCodes=w;